summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/TestsAutoLoader.php20
-rw-r--r--tests/browser/Gemfile.lock82
-rw-r--r--tests/browser/environment_variables5
-rw-r--r--tests/browser/environments.yml35
-rw-r--r--tests/browser/features/file.feature11
-rw-r--r--tests/browser/features/login.feature11
-rw-r--r--tests/browser/features/preferences.feature11
-rw-r--r--tests/browser/features/step_definitions/create_account_steps.rb4
-rw-r--r--tests/browser/features/step_definitions/create_and_follow_wiki_link_steps.rb12
-rw-r--r--tests/browser/features/step_definitions/edit_page_steps.rb3
-rw-r--r--tests/browser/features/step_definitions/file_steps.rb4
-rw-r--r--tests/browser/features/step_definitions/login_steps.rb24
-rw-r--r--tests/browser/features/step_definitions/main_page_links_steps.rb22
-rw-r--r--tests/browser/features/step_definitions/preferences_appearance_steps.rb44
-rw-r--r--tests/browser/features/step_definitions/preferences_editing_steps.rb20
-rw-r--r--tests/browser/features/step_definitions/preferences_user_profile_steps.rb17
-rw-r--r--tests/browser/features/step_definitions/view_history_steps.rb3
-rw-r--r--tests/browser/features/support/env.rb6
-rw-r--r--tests/browser/features/support/modules/url_module.rb10
-rw-r--r--tests/browser/features/support/pages/create_account_page.rb5
-rw-r--r--tests/browser/features/support/pages/edit_page.rb10
-rw-r--r--tests/browser/features/support/pages/file_does_not_exist_page.rb5
-rw-r--r--tests/browser/features/support/pages/login_error_page.rb4
-rw-r--r--tests/browser/features/support/pages/main_page.rb23
-rw-r--r--tests/browser/features/support/pages/preferences_appearance_page.rb46
-rw-r--r--tests/browser/features/support/pages/preferences_editing_page.rb23
-rw-r--r--tests/browser/features/support/pages/preferences_page.rb11
-rw-r--r--tests/browser/features/support/pages/preferences_user_profile_page.rb23
-rw-r--r--tests/browser/features/support/pages/view_history_page.rb3
-rw-r--r--tests/browser/features/support/pages/ztargetpage.rb8
-rw-r--r--tests/parser/ParserTestResult.php5
-rw-r--r--tests/parser/parserTest.inc39
-rw-r--r--tests/parser/parserTests.txt4368
-rw-r--r--tests/parser/parserTestsParserHook.php1
-rw-r--r--tests/parser/preprocess/All_system_messages.expected7
-rw-r--r--tests/parser/preprocess/All_system_messages.txt7
-rw-r--r--tests/parserTests.php4
-rw-r--r--tests/phpunit/LessFileCompilationTest.php2
-rw-r--r--tests/phpunit/Makefile7
-rw-r--r--tests/phpunit/MediaWikiTestCase.php102
-rw-r--r--tests/phpunit/ResourceLoaderTestCase.php23
-rw-r--r--tests/phpunit/bootstrap.php7
-rw-r--r--tests/phpunit/data/composer/composer.json48
-rw-r--r--tests/phpunit/data/composer/composer.lock1195
-rw-r--r--tests/phpunit/data/composer/new-composer.json48
-rw-r--r--tests/phpunit/data/cssmin/circle.svg4
-rw-r--r--tests/phpunit/data/gitinfo/info-testValidJsonData.json8
-rw-r--r--tests/phpunit/data/helpers/WellProtectedClass.php21
-rw-r--r--tests/phpunit/data/media/Soccer_ball_animated.svg110
-rw-r--r--tests/phpunit/data/media/Tux.svg1804
-rw-r--r--tests/phpunit/data/resourceloader/add.gifbin0 -> 74 bytes
-rw-r--r--tests/phpunit/data/resourceloader/bold-a.svg6
-rw-r--r--tests/phpunit/data/resourceloader/bold-b.svg6
-rw-r--r--tests/phpunit/data/resourceloader/bold-f.svg6
-rw-r--r--tests/phpunit/data/resourceloader/help-ltr.svg10
-rw-r--r--tests/phpunit/data/resourceloader/help-rtl.svg10
-rw-r--r--tests/phpunit/data/resourceloader/next.svg4
-rw-r--r--tests/phpunit/data/resourceloader/next_massage.svg4
-rw-r--r--tests/phpunit/data/resourceloader/prev.svg4
-rw-r--r--tests/phpunit/data/resourceloader/remove.svg6
-rw-r--r--tests/phpunit/data/resourceloader/remove_variantize.svg6
-rw-r--r--tests/phpunit/data/templates/foobar.mustache1
-rw-r--r--tests/phpunit/data/templates/foobar_args.mustache1
-rw-r--r--tests/phpunit/includes/BlockTest.php12
-rw-r--r--tests/phpunit/includes/EditPageTest.php7
-rw-r--r--tests/phpunit/includes/GitInfoTest.php2
-rw-r--r--tests/phpunit/includes/GlobalFunctions/GlobalTest.php78
-rw-r--r--tests/phpunit/includes/GlobalFunctions/wfAppendQueryTest.php67
-rw-r--r--tests/phpunit/includes/GlobalFunctions/wfEscapeShellArgTest.php43
-rw-r--r--tests/phpunit/includes/GlobalFunctions/wfThumbIsStandardTest.php104
-rw-r--r--tests/phpunit/includes/HtmlFormatterTest.php14
-rw-r--r--tests/phpunit/includes/HtmlTest.php28
-rw-r--r--tests/phpunit/includes/HttpTest.php321
-rw-r--r--tests/phpunit/includes/ImportTest.php68
-rw-r--r--tests/phpunit/includes/LinkerTest.php56
-rw-r--r--tests/phpunit/includes/MWTimestampTest.php26
-rw-r--r--tests/phpunit/includes/MediaWikiVersionFetcherTest.php1
-rw-r--r--tests/phpunit/includes/MessageTest.php407
-rw-r--r--tests/phpunit/includes/MovePageTest.php63
-rw-r--r--tests/phpunit/includes/OutputPageTest.php45
-rw-r--r--tests/phpunit/includes/PrefixSearchTest.php306
-rw-r--r--tests/phpunit/includes/SampleTest.php2
-rw-r--r--tests/phpunit/includes/SanitizerTest.php29
-rw-r--r--tests/phpunit/includes/StatusTest.php15
-rw-r--r--tests/phpunit/includes/TemplateParserTest.php63
-rw-r--r--tests/phpunit/includes/TestUser.php126
-rw-r--r--tests/phpunit/includes/TestingAccessWrapper.php50
-rw-r--r--tests/phpunit/includes/TestingAccessWrapperTest.php34
-rw-r--r--tests/phpunit/includes/TitleMethodsTest.php41
-rw-r--r--tests/phpunit/includes/TitlePermissionTest.php28
-rw-r--r--tests/phpunit/includes/TitleTest.php54
-rw-r--r--tests/phpunit/includes/UserTest.php91
-rw-r--r--tests/phpunit/includes/XmlSelectTest.php2
-rw-r--r--tests/phpunit/includes/XmlTest.php12
-rw-r--r--tests/phpunit/includes/actions/ActionTest.php12
-rw-r--r--tests/phpunit/includes/api/ApiContinuationManagerTest.php195
-rw-r--r--tests/phpunit/includes/api/ApiErrorFormatterTest.php351
-rw-r--r--tests/phpunit/includes/api/ApiLoginTest.php3
-rw-r--r--tests/phpunit/includes/api/ApiMainTest.php68
-rw-r--r--tests/phpunit/includes/api/ApiMessageTest.php103
-rw-r--r--tests/phpunit/includes/api/ApiOptionsTest.php28
-rw-r--r--tests/phpunit/includes/api/ApiResultTest.php1563
-rw-r--r--tests/phpunit/includes/api/ApiTestCase.php24
-rw-r--r--tests/phpunit/includes/api/ApiTestCaseUpload.php22
-rw-r--r--tests/phpunit/includes/api/ApiUploadTest.php65
-rw-r--r--tests/phpunit/includes/api/MockApi.php3
-rw-r--r--tests/phpunit/includes/api/MockApiQueryBase.php8
-rw-r--r--tests/phpunit/includes/api/PrefixUniquenessTest.php2
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatDbgTest.php55
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatDumpTest.php63
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatJsonTest.php106
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatNoneTest.php38
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatPhpTest.php139
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatTestBase.php70
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatTxtTest.php55
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatWddxTest.php74
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatXmlTest.php119
-rw-r--r--tests/phpunit/includes/api/query/ApiQueryBasicTest.php2
-rw-r--r--tests/phpunit/includes/api/query/ApiQueryContinue2Test.php5
-rw-r--r--tests/phpunit/includes/api/query/ApiQueryContinueTest.php26
-rw-r--r--tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php5
-rw-r--r--tests/phpunit/includes/api/query/ApiQueryTest.php56
-rw-r--r--tests/phpunit/includes/api/query/ApiQueryTestBase.php22
-rw-r--r--tests/phpunit/includes/cache/GenderCacheTest.php8
-rw-r--r--tests/phpunit/includes/cache/LocalisationCacheTest.php54
-rw-r--r--tests/phpunit/includes/cache/RedisBloomCacheTest.php71
-rw-r--r--tests/phpunit/includes/changes/EnhancedChangesListTest.php13
-rw-r--r--tests/phpunit/includes/changes/OldChangesListTest.php1
-rw-r--r--tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php1
-rw-r--r--tests/phpunit/includes/changes/RecentChangeTest.php65
-rw-r--r--tests/phpunit/includes/changes/TestRecentChangesHelper.php1
-rw-r--r--tests/phpunit/includes/composer/ComposerVersionNormalizerTest.php1
-rw-r--r--tests/phpunit/includes/config/GlobalVarConfigTest.php24
-rw-r--r--tests/phpunit/includes/config/HashConfigTest.php2
-rw-r--r--tests/phpunit/includes/content/ContentHandlerTest.php15
-rw-r--r--tests/phpunit/includes/content/JsonContentTest.php142
-rw-r--r--tests/phpunit/includes/content/TextContentTest.php21
-rw-r--r--tests/phpunit/includes/context/RequestContextTest.php (renamed from tests/phpunit/includes/RequestContextTest.php)8
-rw-r--r--tests/phpunit/includes/db/DatabaseMysqlBaseTest.php1
-rw-r--r--tests/phpunit/includes/db/DatabaseSQLTest.php80
-rw-r--r--tests/phpunit/includes/db/DatabaseSqliteTest.php45
-rw-r--r--tests/phpunit/includes/db/LBFactoryTest.php1
-rw-r--r--tests/phpunit/includes/db/ORMRowTest.php1
-rw-r--r--tests/phpunit/includes/db/ORMTableTest.php19
-rw-r--r--tests/phpunit/includes/db/TestORMRowTest.php37
-rw-r--r--tests/phpunit/includes/debug/MWDebugTest.php5
-rw-r--r--tests/phpunit/includes/debug/logging/LegacyLoggerTest.php122
-rw-r--r--tests/phpunit/includes/deferred/LinksUpdateTest.php (renamed from tests/phpunit/includes/LinksUpdateTest.php)0
-rw-r--r--tests/phpunit/includes/deferred/SearchUpdateTest.php (renamed from tests/phpunit/includes/search/SearchUpdateTest.php)6
-rw-r--r--tests/phpunit/includes/diff/ArrayDiffFormatterTest.php1
-rw-r--r--tests/phpunit/includes/diff/DiffOpTest.php5
-rw-r--r--tests/phpunit/includes/diff/DiffTest.php1
-rw-r--r--tests/phpunit/includes/diff/DifferenceEngineTest.php1
-rw-r--r--tests/phpunit/includes/exception/BadTitleErrorTest.php17
-rw-r--r--tests/phpunit/includes/exception/ErrorPageErrorTest.php24
-rw-r--r--tests/phpunit/includes/exception/MWExceptionHandlerTest.php2
-rw-r--r--tests/phpunit/includes/exception/ThrottledErrorTest.php17
-rw-r--r--tests/phpunit/includes/externalstore/ExternalStoreTest.php (renamed from tests/phpunit/includes/ExternalStoreTest.php)0
-rw-r--r--tests/phpunit/includes/filebackend/FileBackendTest.php68
-rw-r--r--tests/phpunit/includes/filerepo/StoreBatchTest.php19
-rw-r--r--tests/phpunit/includes/filerepo/file/LocalFileTest.php (renamed from tests/phpunit/includes/LocalFileTest.php)1
-rw-r--r--tests/phpunit/includes/installer/DatabaseUpdaterTest.php279
-rw-r--r--tests/phpunit/includes/installer/InstallDocFormatterTest.php15
-rw-r--r--tests/phpunit/includes/jobqueue/JobQueueTest.php9
-rw-r--r--tests/phpunit/includes/jobqueue/JobTest.php67
-rw-r--r--tests/phpunit/includes/json/FormatJsonTest.php116
-rw-r--r--tests/phpunit/includes/libs/ArrayUtilsTest.php (renamed from tests/phpunit/includes/ArrayUtilsTest.php)2
-rw-r--r--tests/phpunit/includes/libs/CSSMinTest.php49
-rw-r--r--tests/phpunit/includes/libs/DeferredStringifierTest.php50
-rw-r--r--tests/phpunit/includes/libs/GenericArrayObjectTest.php3
-rw-r--r--tests/phpunit/includes/libs/HashRingTest.php2
-rw-r--r--tests/phpunit/includes/libs/IEUrlExtensionTest.php2
-rw-r--r--tests/phpunit/includes/libs/IPSetTest.php2
-rw-r--r--tests/phpunit/includes/libs/JavaScriptMinifierTest.php11
-rw-r--r--tests/phpunit/includes/libs/MWMessagePackTest.php2
-rw-r--r--tests/phpunit/includes/libs/ObjectFactoryTest.php60
-rw-r--r--tests/phpunit/includes/libs/ProcessCacheLRUTest.php50
-rw-r--r--tests/phpunit/includes/libs/RunningStatTest.php2
-rw-r--r--tests/phpunit/includes/libs/StringUtilsTest.php (renamed from tests/phpunit/includes/utils/StringUtilsTest.php)2
-rw-r--r--tests/phpunit/includes/libs/XhprofTest.php320
-rw-r--r--tests/phpunit/includes/libs/XmlTypeCheckTest.php (renamed from tests/phpunit/includes/XmlTypeCheckTest.php)2
-rw-r--r--tests/phpunit/includes/libs/composer/ComposerJsonTest.php57
-rw-r--r--tests/phpunit/includes/libs/composer/ComposerLockTest.php62
-rw-r--r--tests/phpunit/includes/logging/LogFormatterTest.php53
-rw-r--r--tests/phpunit/includes/mail/MailAddressTest.php7
-rw-r--r--tests/phpunit/includes/media/BitmapScalingTest.php4
-rw-r--r--tests/phpunit/includes/media/FormatMetadataTest.php32
-rw-r--r--tests/phpunit/includes/media/MediaHandlerTest.php82
-rw-r--r--tests/phpunit/includes/media/SVGMetadataExtractorTest.php5
-rw-r--r--tests/phpunit/includes/normal/CleanUpTest.php409
-rw-r--r--tests/phpunit/includes/objectcache/BagOStuffTest.php14
-rw-r--r--tests/phpunit/includes/page/ArticleTablesTest.php (renamed from tests/phpunit/includes/ArticleTablesTest.php)0
-rw-r--r--tests/phpunit/includes/page/ArticleTest.php (renamed from tests/phpunit/includes/ArticleTest.php)0
-rw-r--r--tests/phpunit/includes/page/ImagePage404Test.php (renamed from tests/phpunit/includes/ImagePage404Test.php)0
-rw-r--r--tests/phpunit/includes/page/ImagePageTest.php (renamed from tests/phpunit/includes/ImagePageTest.php)0
-rw-r--r--tests/phpunit/includes/page/WikiPageTest.php (renamed from tests/phpunit/includes/WikiPageTest.php)4
-rw-r--r--tests/phpunit/includes/page/WikiPageTestContentHandlerUseDB.php (renamed from tests/phpunit/includes/WikiPageTestContentHandlerUseDB.php)0
-rw-r--r--tests/phpunit/includes/parser/NewParserTest.php38
-rw-r--r--tests/phpunit/includes/parser/ParserOutputTest.php5
-rw-r--r--tests/phpunit/includes/parser/TagHooksTest.php2
-rw-r--r--tests/phpunit/includes/password/PasswordTest.php (renamed from tests/phpunit/includes/PasswordTest.php)6
-rw-r--r--tests/phpunit/includes/password/PasswordTestCase.php7
-rw-r--r--tests/phpunit/includes/registration/ExtensionProcessorTest.php374
-rw-r--r--tests/phpunit/includes/registration/ExtensionRegistryTest.php195
-rw-r--r--tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php247
-rw-r--r--tests/phpunit/includes/resourceloader/ResourceLoaderImageModuleTest.php162
-rw-r--r--tests/phpunit/includes/resourceloader/ResourceLoaderImageTest.php122
-rw-r--r--tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php61
-rw-r--r--tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php (renamed from tests/phpunit/includes/resourceloader/ResourceLoaderStartupModuleTest.php)86
-rw-r--r--tests/phpunit/includes/resourceloader/ResourceLoaderTest.php185
-rw-r--r--tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php84
-rw-r--r--tests/phpunit/includes/resourceloader/templates/template.html1
-rw-r--r--tests/phpunit/includes/resourceloader/templates/template2.html1
-rw-r--r--tests/phpunit/includes/resourceloader/templates/template_awesome.handlebars1
-rw-r--r--tests/phpunit/includes/search/SearchEngineTest.php67
-rw-r--r--tests/phpunit/includes/site/CachingSiteStoreTest.php161
-rw-r--r--tests/phpunit/includes/site/DBSiteStoreTest.php133
-rw-r--r--tests/phpunit/includes/site/FileBasedSiteLookupTest.php101
-rw-r--r--tests/phpunit/includes/site/HashSiteStoreTest.php105
-rw-r--r--tests/phpunit/includes/site/MediaWikiSiteTest.php1
-rw-r--r--tests/phpunit/includes/site/SiteExporterTest.php147
-rw-r--r--tests/phpunit/includes/site/SiteImporterTest.php200
-rw-r--r--tests/phpunit/includes/site/SiteImporterTest.xml19
-rw-r--r--tests/phpunit/includes/site/SiteListTest.php1
-rw-r--r--tests/phpunit/includes/site/SiteSQLStoreTest.php106
-rw-r--r--tests/phpunit/includes/site/SiteTest.php1
-rw-r--r--tests/phpunit/includes/site/SitesCacheFileBuilderTest.php135
-rw-r--r--tests/phpunit/includes/site/TestSites.php3
-rw-r--r--tests/phpunit/includes/skins/SkinTemplateTest.php1
-rw-r--r--tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php62
-rw-r--r--tests/phpunit/includes/specialpage/SpecialPageTest.php (renamed from tests/phpunit/includes/SpecialPageTest.php)1
-rw-r--r--tests/phpunit/includes/specialpage/SpecialPageTestHelper.php24
-rw-r--r--tests/phpunit/includes/specials/SpecialBooksourcesTest.php36
-rw-r--r--tests/phpunit/includes/specials/SpecialMIMESearchTest.php4
-rw-r--r--tests/phpunit/includes/title/ForeignTitleTest.php103
-rw-r--r--tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php1
-rw-r--r--tests/phpunit/includes/title/MediaWikiTitleCodecTest.php11
-rw-r--r--tests/phpunit/includes/title/NaiveForeignTitleFactoryTest.php91
-rw-r--r--tests/phpunit/includes/title/NaiveImportTitleFactoryTest.php89
-rw-r--r--tests/phpunit/includes/title/NamespaceAwareForeignTitleFactoryTest.php89
-rw-r--r--tests/phpunit/includes/title/NamespaceImportTitleFactoryTest.php77
-rw-r--r--tests/phpunit/includes/title/SubpageImportTitleFactoryTest.php86
-rw-r--r--tests/phpunit/includes/title/TitleValueTest.php1
-rw-r--r--tests/phpunit/includes/upload/UploadBaseTest.php41
-rw-r--r--tests/phpunit/includes/upload/UploadFromUrlTest.php5
-rw-r--r--tests/phpunit/includes/utils/CdbTest.php90
-rw-r--r--tests/phpunit/includes/utils/IPTest.php2
-rw-r--r--tests/phpunit/includes/utils/MWCryptHKDFTest.php6
-rw-r--r--tests/phpunit/includes/utils/MWFunctionTest.php (renamed from tests/phpunit/includes/MWFunctionTest.php)1
-rw-r--r--tests/phpunit/includes/utils/UIDGeneratorTest.php6
-rw-r--r--tests/phpunit/includes/utils/ZipDirectoryReaderTest.php2
-rw-r--r--tests/phpunit/install-phpunit.sh38
-rw-r--r--tests/phpunit/languages/LanguageConverterTest.php (renamed from tests/phpunit/includes/LanguageConverterTest.php)0
-rw-r--r--tests/phpunit/languages/SpecialPageAliasTest.php1
-rw-r--r--tests/phpunit/languages/classes/LanguageAmTest.php (renamed from tests/phpunit/languages/LanguageAmTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageArTest.php (renamed from tests/phpunit/languages/LanguageArTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageArqTest.php (renamed from tests/phpunit/languages/LanguageArqTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageBeTest.php (renamed from tests/phpunit/languages/LanguageBeTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageBe_taraskTest.php (renamed from tests/phpunit/languages/LanguageBe_taraskTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageBhoTest.php (renamed from tests/phpunit/languages/LanguageBhoTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageBsTest.php (renamed from tests/phpunit/languages/LanguageBsTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageCsTest.php (renamed from tests/phpunit/languages/LanguageCsTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageCuTest.php (renamed from tests/phpunit/languages/LanguageCuTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageCyTest.php (renamed from tests/phpunit/languages/LanguageCyTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageDsbTest.php (renamed from tests/phpunit/languages/LanguageDsbTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageFrTest.php (renamed from tests/phpunit/languages/LanguageFrTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageGaTest.php (renamed from tests/phpunit/languages/LanguageGaTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageGdTest.php (renamed from tests/phpunit/languages/LanguageGdTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageGvTest.php (renamed from tests/phpunit/languages/LanguageGvTest.php)2
-rw-r--r--tests/phpunit/languages/classes/LanguageHeTest.php (renamed from tests/phpunit/languages/LanguageHeTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageHiTest.php (renamed from tests/phpunit/languages/LanguageHiTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageHrTest.php (renamed from tests/phpunit/languages/LanguageHrTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageHsbTest.php (renamed from tests/phpunit/languages/LanguageHsbTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageHuTest.php (renamed from tests/phpunit/languages/LanguageHuTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageHyTest.php (renamed from tests/phpunit/languages/LanguageHyTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageKshTest.php (renamed from tests/phpunit/languages/LanguageKshTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageLnTest.php (renamed from tests/phpunit/languages/LanguageLnTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageLtTest.php (renamed from tests/phpunit/languages/LanguageLtTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageLvTest.php (renamed from tests/phpunit/languages/LanguageLvTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageMgTest.php (renamed from tests/phpunit/languages/LanguageMgTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageMkTest.php (renamed from tests/phpunit/languages/LanguageMkTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageMlTest.php (renamed from tests/phpunit/languages/LanguageMlTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageMoTest.php (renamed from tests/phpunit/languages/LanguageMoTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageMtTest.php (renamed from tests/phpunit/languages/LanguageMtTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageNlTest.php (renamed from tests/phpunit/languages/LanguageNlTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageNsoTest.php (renamed from tests/phpunit/languages/LanguageNsoTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguagePlTest.php (renamed from tests/phpunit/languages/LanguagePlTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageRoTest.php (renamed from tests/phpunit/languages/LanguageRoTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageRuTest.php (renamed from tests/phpunit/languages/LanguageRuTest.php)14
-rw-r--r--tests/phpunit/languages/classes/LanguageSeTest.php (renamed from tests/phpunit/languages/LanguageSeTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageSgsTest.php (renamed from tests/phpunit/languages/LanguageSgsTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageShTest.php (renamed from tests/phpunit/languages/LanguageShTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageSkTest.php (renamed from tests/phpunit/languages/LanguageSkTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageSlTest.php (renamed from tests/phpunit/languages/LanguageSlTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageSmaTest.php (renamed from tests/phpunit/languages/LanguageSmaTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageSrTest.php (renamed from tests/phpunit/languages/LanguageSrTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageTiTest.php (renamed from tests/phpunit/languages/LanguageTiTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageTlTest.php (renamed from tests/phpunit/languages/LanguageTlTest.php)4
-rw-r--r--tests/phpunit/languages/classes/LanguageTrTest.php (renamed from tests/phpunit/languages/LanguageTrTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageUkTest.php (renamed from tests/phpunit/languages/LanguageUkTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageUzTest.php (renamed from tests/phpunit/languages/LanguageUzTest.php)0
-rw-r--r--tests/phpunit/languages/classes/LanguageWaTest.php (renamed from tests/phpunit/languages/LanguageWaTest.php)0
-rw-r--r--tests/phpunit/maintenance/DumpTestCase.php24
-rw-r--r--tests/phpunit/maintenance/backupTextPassTest.php126
-rw-r--r--tests/phpunit/phpunit.php6
-rw-r--r--tests/phpunit/structure/AutoLoaderTest.php39
-rw-r--r--tests/phpunit/structure/AvailableRightsTest.php51
-rw-r--r--tests/phpunit/structure/ResourcesTest.php5
-rw-r--r--tests/phpunit/suite.xml2
-rw-r--r--tests/phpunit/suites/ExtensionsTestSuite.php2
-rw-r--r--tests/qunit/QUnitTestResources.php11
-rw-r--r--tests/qunit/data/testrunner.js40
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.accessKeyLabel.test.js14
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js2
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.client.test.js638
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js7
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.placeholder.test.js6
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js223
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js51
-rw-r--r--tests/qunit/suites/resources/mediawiki.api/mediawiki.api.options.test.js78
-rw-r--r--tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js62
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js59
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js61
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.cookie.test.js19
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.errorLogger.test.js42
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js575
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js17
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.messagePoster.factory.test.js28
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.template.test.js63
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.test.js89
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.track.test.js42
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.user.test.js48
-rw-r--r--tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js208
-rw-r--r--tests/qunit/suites/resources/startup.test.js1
-rw-r--r--tests/testHelpers.inc8
335 files changed, 17240 insertions, 5582 deletions
diff --git a/tests/TestsAutoLoader.php b/tests/TestsAutoLoader.php
index 2e8fed44..def23dad 100644
--- a/tests/TestsAutoLoader.php
+++ b/tests/TestsAutoLoader.php
@@ -44,18 +44,18 @@ $wgAutoloadClasses += array(
'ResourceLoaderTestCase' => "$testDir/phpunit/ResourceLoaderTestCase.php",
'ResourceLoaderTestModule' => "$testDir/phpunit/ResourceLoaderTestCase.php",
'ResourceLoaderFileModuleTestModule' => "$testDir/phpunit/ResourceLoaderTestCase.php",
- 'ResourceLoaderWikiModuleTestModule' => "$testDir/phpunit/ResourceLoaderTestCase.php",
'TestUser' => "$testDir/phpunit/includes/TestUser.php",
'LessFileCompilationTest' => "$testDir/phpunit/LessFileCompilationTest.php",
# tests/phpunit/includes
- 'BlockTest' => "$testDir/phpunit/includes/BlockTest.php",
- 'RevisionStorageTest' => "$testDir/phpunit/includes/RevisionStorageTest.php",
- 'WikiPageTest' => "$testDir/phpunit/includes/WikiPageTest.php",
+ 'TestingAccessWrapper' => "$testDir/phpunit/includes/TestingAccessWrapper.php",
# tests/phpunit/includes/api
'ApiFormatTestBase' => "$testDir/phpunit/includes/api/format/ApiFormatTestBase.php",
+ 'ApiQueryTestBase' => "$testDir/phpunit/includes/api/query/ApiQueryTestBase.php",
+ 'ApiQueryContinueTestBase' => "$testDir/phpunit/includes/api/query/ApiQueryContinueTestBase.php",
'ApiTestCase' => "$testDir/phpunit/includes/api/ApiTestCase.php",
+ 'ApiTestCaseUpload' => "$testDir/phpunit/includes/api/ApiTestCaseUpload.php",
'ApiTestContext' => "$testDir/phpunit/includes/api/ApiTestContext.php",
'MockApi' => "$testDir/phpunit/includes/api/MockApi.php",
'MockApiQueryBase' => "$testDir/phpunit/includes/api/MockApiQueryBase.php",
@@ -79,9 +79,16 @@ $wgAutoloadClasses += array(
'PageORMTableForTesting' => "$testDir/phpunit/includes/db/ORMTableTest.php",
'DatabaseTestHelper' => "$testDir/phpunit/includes/db/DatabaseTestHelper.php",
- # tests/phpunit/includes/passwords
+ # tests/phpunit/includes/diff
+ 'FakeDiffOp' => "$testDir/phpunit/includes/diff/FakeDiffOp.php",
+
+ # tests/phpunit/includes/password
'PasswordTestCase' => "$testDir/phpunit/includes/password/PasswordTestCase.php",
+ # tests/phpunit/includes/resourceloader
+ 'ResourceLoaderImageModuleTest' => "$testDir/phpunit/includes/resourceloader/ResourceLoaderImageModuleTest.php",
+ 'ResourceLoaderImageModuleTestable' => "$testDir/phpunit/includes/resourceloader/ResourceLoaderImageModuleTest.php",
+
# tests/phpunit/languages
'LanguageClassesTestCase' => "$testDir/phpunit/languages/LanguageClassesTestCase.php",
@@ -112,4 +119,7 @@ $wgAutoloadClasses += array(
# tests/phpunit/includes/site
'SiteTest' => "$testDir/phpunit/includes/site/SiteTest.php",
'TestSites' => "$testDir/phpunit/includes/site/TestSites.php",
+
+ # tests/phpunit/includes/specialpage
+ 'SpecialPageTestHelper' => "$testDir/phpunit/includes/specialpage/SpecialPageTestHelper.php",
);
diff --git a/tests/browser/Gemfile.lock b/tests/browser/Gemfile.lock
deleted file mode 100644
index 1ea4eb55..00000000
--- a/tests/browser/Gemfile.lock
+++ /dev/null
@@ -1,82 +0,0 @@
-GEM
- remote: https://rubygems.org/
- specs:
- builder (3.2.2)
- childprocess (0.5.3)
- ffi (~> 1.0, >= 1.0.11)
- cucumber (1.3.16)
- builder (>= 2.1.2)
- diff-lcs (>= 1.1.3)
- gherkin (~> 2.12)
- multi_json (>= 1.7.5, < 2.0)
- multi_test (>= 0.1.1)
- data_magic (0.19)
- faker (>= 1.1.2)
- yml_reader (>= 0.3)
- diff-lcs (1.2.5)
- domain_name (0.5.20)
- unf (>= 0.0.5, < 1.0.0)
- faker (1.4.3)
- i18n (~> 0.5)
- faraday (0.9.0)
- multipart-post (>= 1.2, < 3)
- faraday-cookie_jar (0.0.6)
- faraday (>= 0.7.4)
- http-cookie (~> 1.0.0)
- ffi (1.9.3)
- gherkin (2.12.2)
- multi_json (~> 1.3)
- headless (1.0.2)
- http-cookie (1.0.2)
- domain_name (~> 0.5)
- i18n (0.6.11)
- json (1.8.1)
- mediawiki_api (0.2.1)
- faraday (~> 0.9, >= 0.9.0)
- faraday-cookie_jar (~> 0.0, >= 0.0.6)
- mediawiki_selenium (0.3.2)
- cucumber (~> 1.3, >= 1.3.10)
- headless (~> 1.0, >= 1.0.1)
- json (~> 1.8, >= 1.8.1)
- mediawiki_api (~> 0.2, >= 0.2.1)
- page-object (~> 1.0)
- rest-client (~> 1.6, >= 1.6.7)
- rspec-expectations (~> 2.14, >= 2.14.4)
- syntax (~> 1.2, >= 1.2.0)
- mime-types (2.3)
- multi_json (1.10.1)
- multi_test (0.1.1)
- multipart-post (2.0.0)
- netrc (0.7.7)
- page-object (1.0.2)
- page_navigation (>= 0.9)
- selenium-webdriver (>= 2.42.0)
- watir-webdriver (>= 0.6.9)
- page_navigation (0.9)
- data_magic (>= 0.14)
- rest-client (1.7.2)
- mime-types (>= 1.16, < 3.0)
- netrc (~> 0.7)
- rspec-expectations (2.99.2)
- diff-lcs (>= 1.1.3, < 2.0)
- rubyzip (1.1.6)
- selenium-webdriver (2.42.0)
- childprocess (>= 0.5.0)
- multi_json (~> 1.0)
- rubyzip (~> 1.0)
- websocket (~> 1.0.4)
- syntax (1.2.0)
- unf (0.1.4)
- unf_ext
- unf_ext (0.0.6)
- watir-webdriver (0.6.10)
- selenium-webdriver (>= 2.18.0)
- websocket (1.0.7)
- yml_reader (0.3)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- mediawiki_api
- mediawiki_selenium
diff --git a/tests/browser/environment_variables b/tests/browser/environment_variables
deleted file mode 100644
index 25c45775..00000000
--- a/tests/browser/environment_variables
+++ /dev/null
@@ -1,5 +0,0 @@
-export MEDIAWIKI_URL=http://localhost/wiki/
-export MEDIAWIKI_API_URL=http://localhost/w/api.php
-export MEDIAWIKI_USER=Selenium_user
-export MEDIAWIKI_PASSWORD=Selenium_password
-export BROWSER=firefox
diff --git a/tests/browser/environments.yml b/tests/browser/environments.yml
new file mode 100644
index 00000000..8f8381ed
--- /dev/null
+++ b/tests/browser/environments.yml
@@ -0,0 +1,35 @@
+# Customize this configuration as necessary to provide defaults for various
+# test environments.
+#
+# The set of defaults to use is determined by the MEDIAWIKI_ENVIRONMENT
+# environment variable.
+#
+# export MEDIAWIKI_ENVIRONMENT=mw-vagrant-host
+# bundle exec cucumber
+#
+# Additional variables set by the environment will override the corresponding
+# defaults defined here.
+#
+# export MEDIAWIKI_ENVIRONMENT=mw-vagrant-host
+# export MEDIAWIKI_USER=Selenium_user2
+# bundle exec cucumber
+#
+mw-vagrant-host:
+ mediawiki_url: http://127.0.0.1:8080/wiki/
+ mediawiki_user: Selenium_user
+ mediawiki_password: vagrant
+
+mw-vagrant-guest:
+ mediawiki_url: http://127.0.0.1/wiki/
+ mediawiki_user: Selenium_user
+ mediawiki_password: vagrant
+
+beta:
+ mediawiki_url: http://en.wikipedia.beta.wmflabs.org/wiki/
+ mediawiki_user: Selenium_user
+ # mediawiki_password: SET THIS IN THE ENVIRONMENT!
+
+test2:
+ mediawiki_url: http://test2.wikipedia.org/wiki/
+ mediawiki_user: Selenium_user
+ # mediawiki_password: SET THIS IN THE ENVIRONMENT!
diff --git a/tests/browser/features/file.feature b/tests/browser/features/file.feature
index 0bd36ed6..35a6675d 100644
--- a/tests/browser/features/file.feature
+++ b/tests/browser/features/file.feature
@@ -1,14 +1,3 @@
-#
-# This file is subject to the license terms in the LICENSE file found in the
-# qa-browsertests top-level directory and at
-# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/LICENSE. No part of
-# qa-browsertests, including this file, may be copied, modified, propagated, or
-# distributed except according to the terms contained in the LICENSE file.
-#
-# Copyright 2012-2014 by the Mediawiki developers. See the CREDITS file in the
-# qa-browsertests top-level directory and at
-# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/CREDITS
-#
@chrome @clean @firefox @internet_explorer_6 @internet_explorer_7 @internet_explorer_8 @internet_explorer_9 @internet_explorer_10 @phantomjs
Feature: File
diff --git a/tests/browser/features/login.feature b/tests/browser/features/login.feature
index c34d23d3..2cb63564 100644
--- a/tests/browser/features/login.feature
+++ b/tests/browser/features/login.feature
@@ -1,14 +1,3 @@
-#
-# This file is subject to the license terms in the LICENSE file found in the
-# qa-browsertests top-level directory and at
-# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/LICENSE. No part of
-# qa-browsertests, including this file, may be copied, modified, propagated, or
-# distributed except according to the terms contained in the LICENSE file.
-#
-# Copyright 2012-2014 by the Mediawiki developers. See the CREDITS file in the
-# qa-browsertests top-level directory and at
-# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/CREDITS
-#
@chrome @clean @firefox @internet_explorer_6 @internet_explorer_7 @internet_explorer_8 @internet_explorer_9 @internet_explorer_10 @phantomjs
Feature: Log in
diff --git a/tests/browser/features/preferences.feature b/tests/browser/features/preferences.feature
index 9e3abfde..9fed9cf4 100644
--- a/tests/browser/features/preferences.feature
+++ b/tests/browser/features/preferences.feature
@@ -1,14 +1,3 @@
-#
-# This file is subject to the license terms in the LICENSE file found in the
-# qa-browsertests top-level directory and at
-# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/LICENSE. No part of
-# qa-browsertests, including this file, may be copied, modified, propagated, or
-# distributed except according to the terms contained in the LICENSE file.
-#
-# Copyright 2012-2014 by the Mediawiki developers. See the CREDITS file in the
-# qa-browsertests top-level directory and at
-# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/CREDITS
-#
@chrome @clean @firefox @internet_explorer_6 @internet_explorer_7 @internet_explorer_8 @internet_explorer_9 @internet_explorer_10 @login @phantomjs
Feature: Preferences
diff --git a/tests/browser/features/step_definitions/create_account_steps.rb b/tests/browser/features/step_definitions/create_account_steps.rb
index 7fa29843..03bff66f 100644
--- a/tests/browser/features/step_definitions/create_account_steps.rb
+++ b/tests/browser/features/step_definitions/create_account_steps.rb
@@ -10,9 +10,9 @@
# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/CREDITS
#
Given(/^I go to Create account page at (.+)$/) do |path|
- visit(CreateAccountPage, :using_params => {:page_title => path})
+ visit(CreateAccountPage, using_params: { page_title: path })
end
Then(/^form has Create account button$/) do
- on(CreateAccountPage).create_account_element.should exist
+ expect(on(CreateAccountPage).create_account_element).to exist
end
diff --git a/tests/browser/features/step_definitions/create_and_follow_wiki_link_steps.rb b/tests/browser/features/step_definitions/create_and_follow_wiki_link_steps.rb
index ba41f7fb..504d3454 100644
--- a/tests/browser/features/step_definitions/create_and_follow_wiki_link_steps.rb
+++ b/tests/browser/features/step_definitions/create_and_follow_wiki_link_steps.rb
@@ -1,28 +1,26 @@
Given(/^I go to the "(.+)" page with content "(.+)"$/) do |page_title, page_content|
@wikitext = page_content
- on(APIPage).create page_title, page_content
+ api.create_page page_title, page_content
step "I am on the #{page_title} page"
end
Given(/^I am on the (.+) page$/) do |article|
article = article.gsub(/ /, '_')
- visit(ZtargetPage, :using_params => {:article_name => article})
+ visit(ZtargetPage, using_params: { article_name: article })
end
Given(/^I create page "(.*?)" with content "(.*?)"$/) do |page_title, page_content|
- on(APIPage).create page_title, page_content
+ api.create_page page_title, page_content
end
-
When(/^I click the Link Target link$/) do
on(ZtargetPage).link_target_page_link
end
Then(/^I should be on the Link Target Test Page$/) do
- @browser.url.should match /Link_Target_Test_Page/
+ expect(@browser.url).to match /Link_Target_Test_Page/
end
Then(/^the page content should contain "(.*?)"$/) do |content|
- on(ZtargetPage).page_content.should match content
+ expect(on(ZtargetPage).page_content).to match content
end
-
diff --git a/tests/browser/features/step_definitions/edit_page_steps.rb b/tests/browser/features/step_definitions/edit_page_steps.rb
index 5ab02bec..0e0aeb17 100644
--- a/tests/browser/features/step_definitions/edit_page_steps.rb
+++ b/tests/browser/features/step_definitions/edit_page_steps.rb
@@ -19,6 +19,5 @@ When(/^I save the edit$/) do
end
Then(/^the edited page content should contain "(.*?)"$/) do |content|
- on(MainPage).page_content.should match(content + @random_string)
+ expect(on(MainPage).page_content).to match(content + @random_string)
end
-
diff --git a/tests/browser/features/step_definitions/file_steps.rb b/tests/browser/features/step_definitions/file_steps.rb
index a2ed1bfc..a80ca504 100644
--- a/tests/browser/features/step_definitions/file_steps.rb
+++ b/tests/browser/features/step_definitions/file_steps.rb
@@ -10,9 +10,9 @@
# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/CREDITS
#
Given(/^I am at file that does not exist$/) do
- visit(FileDoesNotExistPage, using_params: {page_name: @random_string})
+ visit(FileDoesNotExistPage, using_params: { page_name: @random_string })
end
Then(/^page should show that no such file exists$/) do
- on(FileDoesNotExistPage).file_does_not_exist_message_element.should be_visible
+ expect(on(FileDoesNotExistPage).file_does_not_exist_message_element).to be_visible
end
diff --git a/tests/browser/features/step_definitions/login_steps.rb b/tests/browser/features/step_definitions/login_steps.rb
index b654b2d3..bff5bddd 100644
--- a/tests/browser/features/step_definitions/login_steps.rb
+++ b/tests/browser/features/step_definitions/login_steps.rb
@@ -14,52 +14,52 @@ Given(/^I am at Log in page$/) do
end
When(/^I log in with incorrect password$/) do
- on(LoginPage).login_with(ENV["MEDIAWIKI_USER"], "incorrect password", false)
+ on(LoginPage).login_with(user, 'incorrect password', false)
end
When(/^I log in with incorrect username$/) do
- on(LoginPage).login_with("incorrect username", ENV["MEDIAWIKI_PASSWORD"], false)
+ on(LoginPage).login_with('incorrect username', password, false)
end
When(/^I log in without entering credentials$/) do
- on(LoginPage).login_with("", "", false)
+ on(LoginPage).login_with('', '', false)
end
When(/^I log in without entering password$/) do
- on(LoginPage).login_with(ENV["MEDIAWIKI_USER"], "", false)
+ on(LoginPage).login_with(user, '', false)
end
Then(/^error box should be visible$/) do
- on(LoginErrorPage).error_box_element.should be_visible
+ expect(on(LoginErrorPage).error_box_element).to be_visible
end
Then(/^error box should not be visible$/) do
- on(LoginErrorPage).error_box_element.should_not be_visible
+ expect(on(LoginErrorPage).error_box_element).not_to be_visible
end
Then(/^feedback should be (.+)$/) do |feedback|
on(LoginPage) do |page|
page.feedback_element.when_present.click
- page.feedback.should match Regexp.escape(feedback)
+ expect(page.feedback).to match Regexp.escape(feedback)
end
end
Then(/^Log in element should be there$/) do
- on(LoginPage).login_element.should exist
+ expect(on(LoginPage).login_element).to exist
end
Then(/^main page should open$/) do
- @browser.url.should == on(MainPage).class.url
+ expect(@browser.url).to eq on(MainPage).class.url
end
Then(/^Password element should be there$/) do
- on(LoginPage).password_element.should exist
+ expect(on(LoginPage).password_element).to exist
end
Then(/^there should be a link to (.+)$/) do |text|
- on(LoginPage).username_displayed_element.when_present.text.should == text
+ expect(on(LoginPage).username_displayed_element.when_present.text).to eq text
end
Then(/^Username element should be there$/) do
- on(LoginPage).username_element.should exist
+ expect(on(LoginPage).username_element).to exist
end
diff --git a/tests/browser/features/step_definitions/main_page_links_steps.rb b/tests/browser/features/step_definitions/main_page_links_steps.rb
index c76fd2ba..7f588c05 100644
--- a/tests/browser/features/step_definitions/main_page_links_steps.rb
+++ b/tests/browser/features/step_definitions/main_page_links_steps.rb
@@ -3,45 +3,45 @@ Given(/^I open the main wiki URL$/) do
end
Then(/^I should see a link for View History$/) do
- on(MainPage).view_history_link_element.should be_visible
+ expect(on(MainPage).view_history_link_element).to be_visible
end
Then(/^I should see a link for Edit$/) do
- on(MainPage).edit_link_element.should be_visible
+ expect(on(MainPage).edit_link_element).to be_visible
end
Then(/^I should see a link for Recent changes$/) do
- on(MainPage).recent_changes_link_element.should be_visible
+ expect(on(MainPage).recent_changes_link_element).to be_visible
end
Then(/^I should see a link for Random page$/) do
- on(MainPage).random_page_link_element.should be_visible
+ expect(on(MainPage).random_page_link_element).to be_visible
end
Then(/^I should see a link for Help$/) do
- on(MainPage).help_link_element.should be_visible
+ expect(on(MainPage).help_link_element).to be_visible
end
Then(/^I should see a link for What links here$/) do
- on(MainPage).what_links_here_link_element.should be_visible
+ expect(on(MainPage).what_links_here_link_element).to be_visible
end
Then(/^I should see a link for Related changes$/) do
- on(MainPage).related_changes_link_element.should be_visible
+ expect(on(MainPage).related_changes_link_element).to be_visible
end
Then(/^I should see a link for Special pages$/) do
- on(MainPage).special_pages_link_element.should be_visible
+ expect(on(MainPage).special_pages_link_element).to be_visible
end
Then(/^I should see a link for Printable version$/) do
- on(MainPage).printable_version_link_element.should be_visible
+ expect(on(MainPage).printable_version_link_element).to be_visible
end
Then(/^I should see a link for Permanent link$/) do
- on(MainPage).permanent_link_link_element.should be_visible
+ expect(on(MainPage).permanent_link_link_element).to be_visible
end
Then(/^I should see a link for Page information$/) do
- on(MainPage).page_information_link_element.should be_visible
+ expect(on(MainPage).page_information_link_element).to be_visible
end
diff --git a/tests/browser/features/step_definitions/preferences_appearance_steps.rb b/tests/browser/features/step_definitions/preferences_appearance_steps.rb
index 0046af69..133eec3b 100644
--- a/tests/browser/features/step_definitions/preferences_appearance_steps.rb
+++ b/tests/browser/features/step_definitions/preferences_appearance_steps.rb
@@ -18,68 +18,66 @@ When(/^I navigate to Preferences$/) do
end
Then(/^I can click Save$/) do
- on(PreferencesPage).save_button_element.should exist
+ expect(on(PreferencesPage).save_button_element).to exist
end
Then(/^I can restore default settings$/) do
- on(PreferencesAppearancePage).restore_default_link_element.should exist
+ expect(on(PreferencesAppearancePage).restore_default_link_element).to exist
end
Then(/^I can see local time$/) do
- on(PreferencesAppearancePage).local_time_span_element.should exist
+ expect(on(PreferencesAppearancePage).local_time_span_element).to exist
end
Then(/^I can see time offset section$/) do
- on(PreferencesAppearancePage).time_offset_table_element.should be_visible
+ expect(on(PreferencesAppearancePage).time_offset_table_element).to be_visible
end
Then(/^I can select date format$/) do
on(PreferencesAppearancePage) do |page|
- page.no_preference_radio_element.should exist
- page.mo_day_year_radio_element.should exist
- page.day_mo_year_radio_element.should exist
- page.year_mo_day_radio_element.should exist
- page.iso_8601_radio_element.should exist
+ expect(page.no_preference_radio_element).to exist
+ expect(page.mo_day_year_radio_element).to exist
+ expect(page.day_mo_year_radio_element).to exist
+ expect(page.year_mo_day_radio_element).to exist
+ expect(page.iso_8601_radio_element).to exist
end
end
Then(/^I can select image size$/) do
- on(PreferencesAppearancePage).size_select_element.should exist
+ expect(on(PreferencesAppearancePage).size_select_element).to exist
end
Then(/^I can select my time zone$/) do
on(PreferencesAppearancePage) do |page|
- page.time_offset_select_element.should exist
- page.other_offset_element.should exist
+ expect(page.time_offset_select_element).to exist
+ expect(page.other_offset_element).to exist
end
end
Then(/^I can select skins$/) do
on(PreferencesAppearancePage) do |page|
- page.cologne_blue_element.should exist
- page.modern_element.should exist
- page.monobook_element.should exist
- page.vector_element.should exist
+ expect(page.cologne_blue_element).to exist
+ expect(page.modern_element).to exist
+ expect(page.monobook_element).to exist
+ expect(page.vector_element).to exist
end
end
Then(/^I can select Threshold for stub link$/) do
- on(PreferencesAppearancePage).threshold_select_element.should exist
+ expect(on(PreferencesAppearancePage).threshold_select_element).to exist
end
Then(/^I can select thumbnail size$/) do
- on(PreferencesAppearancePage).thumb_select_element.should exist
+ expect(on(PreferencesAppearancePage).thumb_select_element).to exist
end
Then(/^I can select underline preferences$/) do
- on(PreferencesAppearancePage).underline_select_element.should exist
+ expect(on(PreferencesAppearancePage).underline_select_element).to exist
end
Then(/^I have advanced options checkboxes$/) do
on(PreferencesAppearancePage) do |page|
- page.hidden_categories_check_element.should exist
- page.auto_number_check_element.should exist
+ expect(page.hidden_categories_check_element).to exist
+ expect(page.auto_number_check_element).to exist
end
end
-
-
diff --git a/tests/browser/features/step_definitions/preferences_editing_steps.rb b/tests/browser/features/step_definitions/preferences_editing_steps.rb
index ad29a745..0a98e889 100644
--- a/tests/browser/features/step_definitions/preferences_editing_steps.rb
+++ b/tests/browser/features/step_definitions/preferences_editing_steps.rb
@@ -14,41 +14,41 @@ When(/^I click Editing$/) do
end
Then(/^I can select edit area font style$/) do
- on(PreferencesEditingPage).edit_area_font_style_select_element.when_present.should exist
+ expect(on(PreferencesEditingPage).edit_area_font_style_select_element.when_present).to exist
end
Then(/^I can select live preview$/) do
- on(PreferencesEditingPage).live_preview_check_element.when_present.should exist
+ expect(on(PreferencesEditingPage).live_preview_check_element.when_present).to exist
end
Then(/^I can select section editing by double clicking$/) do
- on(PreferencesEditingPage).edit_section_double_click_check_element.when_present.should exist
+ expect(on(PreferencesEditingPage).edit_section_double_click_check_element.when_present).to exist
end
Then(/^I can select section editing by right clicking$/) do
- on(PreferencesEditingPage).edit_section_right_click_check_element.when_present.should exist
+ expect(on(PreferencesEditingPage).edit_section_right_click_check_element.when_present).to exist
end
Then(/^I can select section editing via edit links$/) do
- on(PreferencesEditingPage).edit_section_edit_link_element.when_present.should exist
+ expect(on(PreferencesEditingPage).edit_section_edit_link_element.when_present).to exist
end
Then(/^I can select show edit toolbar$/) do
- on(PreferencesEditingPage).show_edit_toolbar_check_element.when_present.should exist
+ expect(on(PreferencesEditingPage).show_edit_toolbar_check_element.when_present).to exist
end
Then(/^I can select show preview before edit box$/) do
- on(PreferencesEditingPage).preview_on_top_check_element.when_present.should exist
+ expect(on(PreferencesEditingPage).preview_on_top_check_element.when_present).to exist
end
Then(/^I can select show preview on first edit$/) do
- on(PreferencesEditingPage).preview_on_first_check_element.when_present.should exist
+ expect(on(PreferencesEditingPage).preview_on_first_check_element.when_present).to exist
end
Then(/^I can select to prompt me when entering a blank edit summary$/) do
- on(PreferencesEditingPage).forced_edit_summary_check_element.when_present.should exist
+ expect(on(PreferencesEditingPage).forced_edit_summary_check_element.when_present).to exist
end
Then(/^I can select to warn me when I leave an edit page with unsaved changes$/) do
- on(PreferencesEditingPage).unsaved_changes_check_element.when_present.should exist
+ expect(on(PreferencesEditingPage).unsaved_changes_check_element.when_present).to exist
end
diff --git a/tests/browser/features/step_definitions/preferences_user_profile_steps.rb b/tests/browser/features/step_definitions/preferences_user_profile_steps.rb
index 529af66d..9c65db83 100644
--- a/tests/browser/features/step_definitions/preferences_user_profile_steps.rb
+++ b/tests/browser/features/step_definitions/preferences_user_profile_steps.rb
@@ -15,29 +15,28 @@ end
Then(/^I can change my gender$/) do
on(PreferencesUserProfilePage) do |page|
- page.gender_undefined_radio_element.should exist
- page.gender_male_radio_element.should exist
- page.gender_female_radio_element.should exist
+ expect(page.gender_undefined_radio_element).to exist
+ expect(page.gender_male_radio_element).to exist
+ expect(page.gender_female_radio_element).to exist
end
end
Then(/^I can change my language$/) do
- on(PreferencesUserProfilePage).lang_select_element.should exist
+ expect(on(PreferencesUserProfilePage).lang_select_element).to exist
end
Then(/^I can change my signature$/) do
- on(PreferencesUserProfilePage).signature_field_element.should exist
+ expect(on(PreferencesUserProfilePage).signature_field_element).to exist
end
Then(/^I can see my Basic informations$/) do
- on(PreferencesUserProfilePage).basic_info_table_element.should exist
+ expect(on(PreferencesUserProfilePage).basic_info_table_element).to exist
end
Then(/^I can see my email$/) do
- on(PreferencesUserProfilePage).email_table_element.should exist
+ expect(on(PreferencesUserProfilePage).email_table_element).to exist
end
Then(/^I can see my signature$/) do
- on(PreferencesUserProfilePage).signature_table_element.should exist
+ expect(on(PreferencesUserProfilePage).signature_table_element).to exist
end
-
diff --git a/tests/browser/features/step_definitions/view_history_steps.rb b/tests/browser/features/step_definitions/view_history_steps.rb
index 1ecc0085..d9b93817 100644
--- a/tests/browser/features/step_definitions/view_history_steps.rb
+++ b/tests/browser/features/step_definitions/view_history_steps.rb
@@ -3,6 +3,5 @@ When(/^I click View History$/) do
end
Then(/^I should see a link to a previous version of the page$/) do
- on(ViewHistoryPage).old_version_link_element.should be_visible
+ expect(on(ViewHistoryPage).old_version_link_element).to be_visible
end
-
diff --git a/tests/browser/features/support/env.rb b/tests/browser/features/support/env.rb
index 7c122366..5eff4ce5 100644
--- a/tests/browser/features/support/env.rb
+++ b/tests/browser/features/support/env.rb
@@ -1,2 +1,4 @@
-require "mediawiki_api"
-require "mediawiki_selenium"
+require 'mediawiki_selenium'
+
+require 'mediawiki_selenium/support'
+require 'mediawiki_selenium/step_definitions'
diff --git a/tests/browser/features/support/modules/url_module.rb b/tests/browser/features/support/modules/url_module.rb
deleted file mode 100644
index 6c329e87..00000000
--- a/tests/browser/features/support/modules/url_module.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-module URL
- def self.url(name)
- if ENV["MEDIAWIKI_URL"]
- mediawiki_url = ENV["MEDIAWIKI_URL"]
- else
- mediawiki_url = "http://127.0.0.1:80/w/index.php"
- end
- "#{mediawiki_url}#{name}"
- end
-end
diff --git a/tests/browser/features/support/pages/create_account_page.rb b/tests/browser/features/support/pages/create_account_page.rb
index 380bccbc..98b893a6 100644
--- a/tests/browser/features/support/pages/create_account_page.rb
+++ b/tests/browser/features/support/pages/create_account_page.rb
@@ -12,8 +12,7 @@
class CreateAccountPage
include PageObject
- include URL
- page_url URL.url("<%=params[:page_title]%>")
+ page_url '<%=params[:page_title]%>'
- button(:create_account, id: "wpCreateaccount")
+ button(:create_account, id: 'wpCreateaccount')
end
diff --git a/tests/browser/features/support/pages/edit_page.rb b/tests/browser/features/support/pages/edit_page.rb
index b619c342..b0f6bffe 100644
--- a/tests/browser/features/support/pages/edit_page.rb
+++ b/tests/browser/features/support/pages/edit_page.rb
@@ -1,8 +1,8 @@
class EditPage
include PageObject
- text_area(:edit_page_content, id: "wpTextbox1")
- button(:preview_button, id: "wpPreview")
- button(:show_changes_button, id: "wpDiff")
- button(:save_button, id: "wpSave")
-end \ No newline at end of file
+ text_area(:edit_page_content, id: 'wpTextbox1')
+ button(:preview_button, id: 'wpPreview')
+ button(:show_changes_button, id: 'wpDiff')
+ button(:save_button, id: 'wpSave')
+end
diff --git a/tests/browser/features/support/pages/file_does_not_exist_page.rb b/tests/browser/features/support/pages/file_does_not_exist_page.rb
index c8491f3b..90762d22 100644
--- a/tests/browser/features/support/pages/file_does_not_exist_page.rb
+++ b/tests/browser/features/support/pages/file_does_not_exist_page.rb
@@ -12,8 +12,7 @@
class FileDoesNotExistPage
include PageObject
- include URL
- page_url URL.url("File:<%=params[:page_name]%>")
+ page_url 'File:<%=params[:page_name]%>'
- div(:file_does_not_exist_message, id: "mw-imagepage-nofile")
+ div(:file_does_not_exist_message, id: 'mw-imagepage-nofile')
end
diff --git a/tests/browser/features/support/pages/login_error_page.rb b/tests/browser/features/support/pages/login_error_page.rb
index 4fc9ca7f..9a1805f3 100644
--- a/tests/browser/features/support/pages/login_error_page.rb
+++ b/tests/browser/features/support/pages/login_error_page.rb
@@ -1,5 +1,5 @@
class LoginErrorPage
include PageObject
- div(:error_box, class: "errorbox")
-end \ No newline at end of file
+ div(:error_box, class: 'errorbox')
+end
diff --git a/tests/browser/features/support/pages/main_page.rb b/tests/browser/features/support/pages/main_page.rb
index 7d96c2b2..6d76b01c 100644
--- a/tests/browser/features/support/pages/main_page.rb
+++ b/tests/browser/features/support/pages/main_page.rb
@@ -1,19 +1,18 @@
class MainPage
include PageObject
- include URL
- page_url URL.url("")
+ page_url ''
a(:edit_link, href: /action=edit/)
- 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")
+ 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/)
- 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")
+ 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/)
- li(:what_links_here_link, id: "t-whatlinkshere")
-end \ No newline at end of file
+ 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 c24e3862..83c3952f 100644
--- a/tests/browser/features/support/pages/preferences_appearance_page.rb
+++ b/tests/browser/features/support/pages/preferences_appearance_page.rb
@@ -12,30 +12,28 @@
class PreferencesAppearancePage
include PageObject
- include URL
- page_url URL.url("Special:Preferences#mw-prefsection-rendering")
+ page_url 'Special:Preferences#mw-prefsection-rendering'
- checkbox(:auto_number_check, id: "mw-input-wpnumberheadings")
- radio_button(:cologne_blue, id: "mw-input-wpskin-cologneblue")
- radio_button(:day_mo_year_radio, id: "mw-input-wpdate-dmy")
- checkbox(:dont_show_aft_check, id: "mw-input-wparticlefeedback-disable")
- checkbox(:exclude_from_experiments_check, id: "mw-input-wpvector-noexperiments")
- checkbox(:hidden_categories_check, id: "mw-input-wpshowhiddencats")
- radio_button(:iso_8601_radio, id: "mw-input-wpdate-ISO_8601")
- span(:local_time_span, id: "wpLocalTime")
- radio_button(:mo_day_year_radio, id: "mw-input-wpdate-mdy")
- radio_button(:modern, id: "mw-input-wpskin-modern")
- 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")
+ checkbox(:auto_number_check, id: 'mw-input-wpnumberheadings')
+ radio_button(:cologne_blue, id: 'mw-input-wpskin-cologneblue')
+ radio_button(:day_mo_year_radio, id: 'mw-input-wpdate-dmy')
+ checkbox(:dont_show_aft_check, id: 'mw-input-wparticlefeedback-disable')
+ checkbox(:exclude_from_experiments_check, id: 'mw-input-wpvector-noexperiments')
+ checkbox(:hidden_categories_check, id: 'mw-input-wpshowhiddencats')
+ radio_button(:iso_8601_radio, id: 'mw-input-wpdate-ISO_8601')
+ span(:local_time_span, id: 'wpLocalTime')
+ radio_button(:mo_day_year_radio, id: 'mw-input-wpdate-mdy')
+ radio_button(:modern, id: 'mw-input-wpskin-modern')
+ 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/)
- 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")
- table(:time_offset_table, id: "mw-htmlform-timeoffset")
- select_list(:thumb_select, id: "mw-input-wpthumbsize")
- select_list(:underline_select, id: "mw-input-wpunderline")
- radio_button(:vector, id: "mw-input-wpskin-vector")
- radio_button(:year_mo_day_radio, id: "mw-input-wpdate-ymd")
+ 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')
+ table(:time_offset_table, id: 'mw-htmlform-timeoffset')
+ select_list(:thumb_select, id: 'mw-input-wpthumbsize')
+ select_list(:underline_select, id: 'mw-input-wpunderline')
+ radio_button(:vector, id: 'mw-input-wpskin-vector')
+ radio_button(:year_mo_day_radio, id: 'mw-input-wpdate-ymd')
end
-
diff --git a/tests/browser/features/support/pages/preferences_editing_page.rb b/tests/browser/features/support/pages/preferences_editing_page.rb
index aed9c41d..25c384f7 100644
--- a/tests/browser/features/support/pages/preferences_editing_page.rb
+++ b/tests/browser/features/support/pages/preferences_editing_page.rb
@@ -12,17 +12,16 @@
class PreferencesEditingPage
include PageObject
- include URL
- page_url URL.url("Special:Preferences#mw-prefsection-rendering")
+ page_url 'Special:Preferences#mw-prefsection-rendering'
- select_list(:edit_area_font_style_select, id: "mw-input-wpeditfont")
- checkbox(:edit_section_double_click_check, id: "mw-input-wpeditondblclick")
- checkbox(:edit_section_edit_link, id: "mw-input-wpeditsectiononrightclick")
- checkbox(:edit_section_right_click_check, id: "mw-input-wpeditsectiononrightclick")
- checkbox(:forced_edit_summary_check, id: "mw-input-wpforceeditsummary")
- checkbox(:live_preview_check, id: "mw-input-wpuselivepreview")
- checkbox(:preview_on_first_check, id: "mw-input-wppreviewonfirst")
- checkbox(:preview_on_top_check, id: "mw-input-wppreviewontop")
- checkbox(:show_edit_toolbar_check, id: "mw-input-wpshowtoolbar")
- checkbox(:unsaved_changes_check, id: "mw-input-wpuseeditwarning")
+ select_list(:edit_area_font_style_select, id: 'mw-input-wpeditfont')
+ checkbox(:edit_section_double_click_check, id: 'mw-input-wpeditondblclick')
+ checkbox(:edit_section_edit_link, id: 'mw-input-wpeditsectiononrightclick')
+ checkbox(:edit_section_right_click_check, id: 'mw-input-wpeditsectiononrightclick')
+ checkbox(:forced_edit_summary_check, id: 'mw-input-wpforceeditsummary')
+ checkbox(:live_preview_check, id: 'mw-input-wpuselivepreview')
+ checkbox(:preview_on_first_check, id: 'mw-input-wppreviewonfirst')
+ checkbox(:preview_on_top_check, id: 'mw-input-wppreviewontop')
+ checkbox(:show_edit_toolbar_check, id: 'mw-input-wpshowtoolbar')
+ checkbox(:unsaved_changes_check, id: 'mw-input-wpuseeditwarning')
end
diff --git a/tests/browser/features/support/pages/preferences_page.rb b/tests/browser/features/support/pages/preferences_page.rb
index 919ba27f..b305ee2c 100644
--- a/tests/browser/features/support/pages/preferences_page.rb
+++ b/tests/browser/features/support/pages/preferences_page.rb
@@ -12,11 +12,10 @@
class PreferencesPage
include PageObject
- include URL
- page_url URL.url("Special:Preferences")
+ page_url 'Special:Preferences'
- a(:appearance_link, id: "preftab-rendering")
- a(:editing_link, id: "preftab-editing")
- a(:user_profile_link, id: "preftab-personal")
- button(:save_button, id: "prefcontrol")
+ a(:appearance_link, id: 'preftab-rendering')
+ a(:editing_link, id: 'preftab-editing')
+ a(:user_profile_link, id: 'preftab-personal')
+ button(:save_button, id: 'prefcontrol')
end
diff --git a/tests/browser/features/support/pages/preferences_user_profile_page.rb b/tests/browser/features/support/pages/preferences_user_profile_page.rb
index 28e10b97..9e95eb5a 100644
--- a/tests/browser/features/support/pages/preferences_user_profile_page.rb
+++ b/tests/browser/features/support/pages/preferences_user_profile_page.rb
@@ -12,17 +12,16 @@
class PreferencesUserProfilePage
include PageObject
- include URL
- page_url URL.url("Special:Preferences#mw-prefsection-personal")
+ page_url 'Special:Preferences#mw-prefsection-personal'
- table(:basic_info_table, id: "mw-htmlform-info")
- link(:change_password_link, text: "Change password")
- table(:email_table, id: "mw-htmlform-email")
- radio_button(:gender_female_radio, id: "mw-input-wpgender-male")
- radio_button(:gender_male_radio, id: "mw-input-wpgender-female")
- radio_button(:gender_undefined_radio, id: "mw-input-wpgender-unknown")
- select_list(:lang_select, id: "mw-input-wplanguage")
- checkbox(:remember_password_check, id: "mw-input-wprememberpassword")
- text_field(:signature_field, id: "mw-input-wpnickname")
- table(:signature_table, id: "mw-htmlform-signature")
+ table(:basic_info_table, id: 'mw-htmlform-info')
+ link(:change_password_link, text: 'Change password')
+ table(:email_table, id: 'mw-htmlform-email')
+ radio_button(:gender_female_radio, id: 'mw-input-wpgender-male')
+ radio_button(:gender_male_radio, id: 'mw-input-wpgender-female')
+ radio_button(:gender_undefined_radio, id: 'mw-input-wpgender-unknown')
+ select_list(:lang_select, id: 'mw-input-wplanguage')
+ checkbox(:remember_password_check, id: 'mw-input-wprememberpassword')
+ text_field(:signature_field, id: 'mw-input-wpnickname')
+ table(:signature_table, id: 'mw-htmlform-signature')
end
diff --git a/tests/browser/features/support/pages/view_history_page.rb b/tests/browser/features/support/pages/view_history_page.rb
index 66895986..bb9c5862 100644
--- a/tests/browser/features/support/pages/view_history_page.rb
+++ b/tests/browser/features/support/pages/view_history_page.rb
@@ -3,5 +3,4 @@ class ViewHistoryPage
a(:view_history_link, href: /action=history/)
a(:old_version_link, href: /oldid=/)
-
-end \ No newline at end of file
+end
diff --git a/tests/browser/features/support/pages/ztargetpage.rb b/tests/browser/features/support/pages/ztargetpage.rb
index c1f46eca..da789e5e 100644
--- a/tests/browser/features/support/pages/ztargetpage.rb
+++ b/tests/browser/features/support/pages/ztargetpage.rb
@@ -1,7 +1,7 @@
class ZtargetPage < MainPage
- include URL
- page_url URL.url("<%=params[:article_name]%>")
include PageObject
- a(:link_target_page_link, text: "link to the test target page")
-end \ No newline at end of file
+ page_url '<%=params[:article_name]%>'
+
+ a(:link_target_page_link, text: 'link to the test target page')
+end
diff --git a/tests/parser/ParserTestResult.php b/tests/parser/ParserTestResult.php
index 7d9415a2..a7b36721 100644
--- a/tests/parser/ParserTestResult.php
+++ b/tests/parser/ParserTestResult.php
@@ -1,10 +1,9 @@
<?php
/**
+ * @file
+ *
* @copyright Copyright © 2013, Antoine Musso
* @copyright Copyright © 2013, Wikimedia Foundation Inc.
- * @license GNU GPL v2
- *
- * @file
*/
/**
diff --git a/tests/parser/parserTest.inc b/tests/parser/parserTest.inc
index a9df6832..1cffa20c 100644
--- a/tests/parser/parserTest.inc
+++ b/tests/parser/parserTest.inc
@@ -559,7 +559,7 @@ class ParserTest {
$parser->setTransparentTagHook( $tag, $callback );
}
- wfRunHooks( 'ParserTestParser', array( &$parser ) );
+ Hooks::run( 'ParserTestParser', array( &$parser ) );
return $parser;
}
@@ -593,6 +593,14 @@ class ParserTest {
}
}
+ if ( isset( $opts['tidy'] ) ) {
+ if ( !$this->tidySupport->isEnabled() ) {
+ return $this->showSkipped();
+ } else {
+ $options->setTidy( true );
+ }
+ }
+
if ( isset( $opts['title'] ) ) {
$titleText = $opts['title'];
} else {
@@ -624,10 +632,6 @@ class ParserTest {
$output->setTOCEnabled( !isset( $opts['notoc'] ) );
$out = $output->getText();
if ( isset( $opts['tidy'] ) ) {
- if ( !$this->tidySupport->isEnabled() ) {
- return $this->showSkipped();
- }
- $out = MWTidy::tidy( $out );
$out = preg_replace( '/\s+$/', '', $out );
}
@@ -639,6 +643,14 @@ class ParserTest {
$out = "$title\n$out";
}
+ if ( isset( $opts['showindicators'] ) ) {
+ $indicators = '';
+ foreach ( $output->getIndicators() as $id => $content ) {
+ $indicators .= "$id=$content\n";
+ }
+ $out = $indicators . $out;
+ }
+
if ( isset( $opts['ill'] ) ) {
$out = implode( ' ', $output->getLanguageLinks() );
} elseif ( isset( $opts['cat'] ) ) {
@@ -877,10 +889,7 @@ class ParserTest {
'wgDisableLangConversion' => false,
'wgDisableTitleConversion' => false,
// Tidy options.
- // We always set 'wgUseTidy' to false when parsing, but certain
- // test-running modes still use tidy if available, so ensure
- // that the tidy-related options are all set to their defaults.
- 'wgUseTidy' => false,
+ 'wgUseTidy' => isset( $opts['tidy'] ),
'wgAlwaysUseTidy' => false,
'wgDebugTidy' => false,
'wgTidyConf' => $IP . '/includes/tidy.conf',
@@ -901,7 +910,7 @@ class ParserTest {
$this->savedGlobals = array();
/** @since 1.20 */
- wfRunHooks( 'ParserTestGlobals', array( &$settings ) );
+ Hooks::run( 'ParserTestGlobals', array( &$settings ) );
foreach ( $settings as $var => $val ) {
if ( array_key_exists( $var, $GLOBALS ) ) {
@@ -941,7 +950,7 @@ class ParserTest {
$tables = array( 'user', 'user_properties', 'user_former_groups', 'page', 'page_restrictions',
'protected_titles', 'revision', 'text', 'pagelinks', 'imagelinks',
'categorylinks', 'templatelinks', 'externallinks', 'langlinks', 'iwlinks',
- 'site_stats', 'hitcounter', 'ipblocks', 'image', 'oldimage',
+ 'site_stats', 'ipblocks', 'image', 'oldimage',
'recentchanges', 'watchlist', 'interwiki', 'logging',
'querycache', 'objectcache', 'job', 'l10n_cache', 'redirect', 'querycachetwo',
'archive', 'user_groups', 'page_props', 'category', 'msg_resource', 'msg_resource_links'
@@ -954,7 +963,7 @@ class ParserTest {
// Allow extensions to add to the list of tables to duplicate;
// may be necessary if they hook into page save or other code
// which will require them while running tests.
- wfRunHooks( 'ParserTestTables', array( &$tables ) );
+ Hooks::run( 'ParserTestTables', array( &$tables ) );
return $tables;
}
@@ -1493,8 +1502,10 @@ class ParserTest {
* Insert a temporary test article
* @param string $name The title, including any prefix
* @param string $text The article text
- * @param int $line The input line number, for reporting errors
- * @param bool $ignoreDuplicate Whether to silently ignore duplicate pages
+ * @param int|string $line The input line number, for reporting errors
+ * @param bool|string $ignoreDuplicate Whether to silently ignore duplicate pages
+ * @throws Exception
+ * @throws MWException
*/
public static function addArticle( $name, $text, $line = 'unknown', $ignoreDuplicate = '' ) {
global $wgCapitalLinks;
diff --git a/tests/parser/parserTests.txt b/tests/parser/parserTests.txt
index f915922f..e9653529 100644
--- a/tests/parser/parserTests.txt
+++ b/tests/parser/parserTests.txt
@@ -16,7 +16,7 @@
# cat add category links
# ill add inter-language links
# subpage enable subpages (disabled by default)
-# noxml don't check for XML well formdness
+# noxml don't check for XML well-formedness
# title=[[XXX]] run test using article title XXX
# language=XXX set content language to XXX for this test
# variant=XXX set the variant of language for this test (eg zh-tw)
@@ -26,6 +26,7 @@
# php php-only test (not run by the parsoid parser unless
# the test includes an html/parsoid section)
# showtitle make the first line the title
+# showindicators make the first lines the page status indicators
# comment run through Linker::formatComment() instead of main parser
# local format section links in edit comment text as local links
# notoc disable table of contents
@@ -69,6 +70,12 @@ Template:pipe
|
!! endarticle
+!! article
+Template:=
+!! text
+<nowiki>=</nowiki>
+!! endarticle
+
!!article
MediaWiki:bad image list
!!text
@@ -112,22 +119,50 @@ Template:echo_with_div
!! endarticle
!! article
-Template:attr_str
+Template:table_attribs
!! text
-{{{1}}}="{{{2}}}"
+<noinclude>
+|</noinclude>style="color:red;"|Foo
!! endarticle
!! article
-Template:table_attribs
+Template:table_attribs_2
+!! text
+<noinclude>
+|</noinclude>style="color:red;"|Foo
+|Bar||Baz
+!! endarticle
+
+!! article
+Template:table_attribs_3
+!! text
+<noinclude>
+|</noinclude>style{{=}}"background:&#35;f9f9f9;"|Foo
+!! endarticle
+
+!! article
+Template:table_attribs_4
+!! text
+| style="background-color:#DC241f;" width="10px" |
+!! endarticle
+
+!! article
+Template:table_attribs_5
!! text
<noinclude>
-|</noinclude>style="color: red"| Foo
+|</noinclude>style="color:red;"||Bar
+!! endarticle
+
+!! article
+Template:table_header_cells
+!! text
+{{table_attribs}}!!style='color:red;'|''Bar''||style='color:brown;'|''Foo'' and Baz
!! endarticle
!! article
Template:table_cells
!! text
-{{table_attribs}} || Bar || Baz
+{{table_attribs}}||style='color:red;'|''Bar''||style='color:brown;'|''Foo'' and Baz
!! endarticle
!! article
@@ -137,6 +172,22 @@ Template:image_attribs
[[File:foobar.jpg|</noinclude>right|Caption text<noinclude>]]</noinclude>
!! endarticle
+## See T48811 for details
+!! article
+Template:mixed_attr_content_template
+!! text
+style="color:red;" title="T48811"
+|-
+|foo
+!! endarticle
+
+!! article
+Template:definition_list
+!! text
+one
+::two
+!! endarticle
+
!! article
A?b
!! text
@@ -155,6 +206,39 @@ Template:OpenTable
{|
!!endarticle
+!!article
+Template:EmptyLITest
+!!text
+*a
+*
+*
+*b
+!!endarticle
+
+!!article
+Template:EmptyTRTest
+!!text
+{|
+|-
+|-
+|foo
+|-
+|-
+|bar
+|}
+!!endarticle
+
+!!article
+Template:EmptyTRWithHTMLAttrTest
+!!text
+<table>
+<tr align="center"></tr>
+<tr><td>foo</td></tr>
+<tr align="center"></tr>
+<tr><td>bar</td></tr>
+</table>
+!!endarticle
+
###
### Basic tests
###
@@ -505,11 +589,8 @@ Italics and bold: 2-quote opening sequence: (2,2)
</p>
!!end
-
!! test
Italics and bold: 2-quote opening sequence: (2,3)
-!! options
-parsoid=wt2html
!! wikitext
''foo'''
!! html/*
@@ -517,18 +598,6 @@ parsoid=wt2html
</p>
!!end
-
-# same html as previous, but wikitext adjusted to match parsoid html2wt
-!! test
-Italics and bold: 2-quote opening sequence: (2,3) w/ nowiki
-!! wikitext
-''<nowiki>foo'</nowiki>''
-!! html
-<p><i>foo'</i>
-</p>
-!! end
-
-
!! test
Italics and bold: 2-quote opening sequence: (2,4)
!! options
@@ -540,18 +609,16 @@ parsoid=wt2html
</p>
!!end
-
# same html as previous, but wikitext adjusted to match parsoid html2wt
!! test
Italics and bold: 2-quote opening sequence: (2,4) w/ nowiki
!! wikitext
-''<nowiki>foo''</nowiki>''
+''foo<nowiki>''</nowiki>''
!! html
<p><i>foo''</i>
</p>
!! end
-
# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
!! test
Italics and bold: 2-quote opening sequence: (2,5)
@@ -589,12 +656,11 @@ Italics and bold: 2-quote opening sequence: (2,5+3) w/ nowiki
Italics and bold: 3-quote opening sequence: (3,2)
!! wikitext
'''foo''
-!! html
+!! html/*
<p>'<i>foo</i>
</p>
!!end
-
!! test
Italics and bold: 3-quote opening sequence: (3,3)
!! wikitext
@@ -604,11 +670,8 @@ Italics and bold: 3-quote opening sequence: (3,3)
</p>
!!end
-
!! test
Italics and bold: 3-quote opening sequence: (3,4)
-!! options
-parsoid=wt2html
!! wikitext
'''foo''''
!! html/*
@@ -616,18 +679,6 @@ parsoid=wt2html
</p>
!!end
-
-# same html as previous, but wikitext adjusted to match parsoid html2wt
-!! test
-Italics and bold: 3-quote opening sequence: (3,4) w/ nowiki
-!! wikitext
-'''<nowiki>foo'</nowiki>'''
-!! html
-<p><b>foo'</b>
-</p>
-!! end
-
-
# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
!! test
Italics and bold: 3-quote opening sequence: (3,5)
@@ -672,7 +723,6 @@ parsoid=wt2html
</p>
!!end
-
# same html as previous, but wikitext adjusted to match parsoid html2wt
!! test
Italics and bold: 4-quote opening sequence: (4,2) w/ nowiki
@@ -683,17 +733,15 @@ Italics and bold: 4-quote opening sequence: (4,2) w/ nowiki
</p>
!! end
-
!! test
Italics and bold: 4-quote opening sequence: (4,3)
!! wikitext
''''foo'''
-!! html
+!! html/*
<p>'<b>foo</b>
</p>
!!end
-
!! test
Italics and bold: 4-quote opening sequence: (4,4)
!! options
@@ -705,18 +753,16 @@ parsoid=wt2html
</p>
!!end
-
# same html as previous, but wikitext adjusted to match parsoid html2wt
!! test
Italics and bold: 4-quote opening sequence: (4,4) w/ nowiki
!! wikitext
-''''<nowiki>foo'</nowiki>'''
+'<nowiki/>'''foo''''
!! html
<p>'<b>foo'</b>
</p>
!! end
-
# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
!! test
Italics and bold: 4-quote opening sequence: (4,5)
@@ -736,7 +782,7 @@ parsoid=wt2html
!! test
Italics and bold: 4-quote opening sequence: (4,5+2) w/ nowiki
!! wikitext
-''''foo'''''<nowiki/>''
+'<nowiki/>'''foo'''''<nowiki/>''
!! html/php
<p>'<b>foo</b>
</p>
@@ -761,7 +807,6 @@ parsoid=wt2html
</p>
!!end
-
# same html as previous, but wikitext adjusted to match parsoid html2wt
# skipping wt2html and html2html because it wants to put <i> before <b>
!! test
@@ -786,7 +831,6 @@ parsoid=wt2html
</p>
!!end
-
# same html as previous, but wikitext adjusted to match parsoid html2wt
!! test
Italics and bold: 5-quote opening sequence: (5,3+2)
@@ -797,7 +841,6 @@ Italics and bold: 5-quote opening sequence: (5,3+2)
</p>
!! end
-
!! test
Italics and bold: 5-quote opening sequence: (5,4)
!! options
@@ -809,18 +852,6 @@ parsoid=wt2html
</p>
!!end
-
-# same html as previous, but wikitext adjusted to match parsoid html2wt
-!! test
-Italics and bold: 5-quote opening sequence: (5,4+2) w/ nowiki
-!! wikitext
-'''''<nowiki>foo'</nowiki>'''''
-!! html
-<p><i><b>foo'</b></i>
-</p>
-!! end
-
-
!! test
Italics and bold: 5-quote opening sequence: (5,5)
!! wikitext
@@ -830,6 +861,15 @@ Italics and bold: 5-quote opening sequence: (5,5)
</p>
!!end
+!! test
+Italics and bold: 5-quote opening sequence: (5,6)
+!! wikitext
+'''''foo''''''
+!! html/*
+<p><i><b>foo'</b></i>
+</p>
+!! end
+
###
### multiple quote sequences in a line
###
@@ -849,7 +889,7 @@ parsoid=wt2html
!! test
Italics and bold: multiple quote sequences: (2,4,2+3) w/ nowiki
!! wikitext
-''<nowiki>foo'</nowiki>'''bar'''''
+''foo'<nowiki/>'''bar'''''
!! html
<p><i>foo'<b>bar</b></i>
</p>
@@ -872,7 +912,7 @@ parsoid=wt2html
!! test
Italics and bold: multiple quote sequences: (2,4,3+2) w/ nowiki
!! wikitext
-''<nowiki>foo'</nowiki>'''bar'''''
+''foo'<nowiki/>'''bar'''''
!! html
<p><i>foo'<b>bar</b></i>
</p>
@@ -895,7 +935,7 @@ parsoid=wt2html
!! test
Italics and bold: multiple quote sequences: (2,4,4+2) w/ nowiki
!! wikitext
-''<nowiki>foo'</nowiki>'''<nowiki>bar'</nowiki>'''''
+''foo'<nowiki/>'''bar'<nowiki/>'''''
!! html
<p><i>foo'<b>bar'</b></i>
</p>
@@ -997,14 +1037,11 @@ parsoid=wt2html
# same html as previous, but wikitext adjusted to match parsoid html2wt
-# add 'parsoid' option to use 'parsoid' normalization of the placeholder
!! test
Italics and bold: other quote tests: (3,2,3+2+2,2)
-!! options
-parsoid
!! wikitext
'''this is about ''foo'''''<nowiki/>''s family''
-!! html/*
+!! html
<p><b>this is about <i>foo</i></b><i>s family</i>
</p>
!! end
@@ -1012,10 +1049,9 @@ parsoid
!! test
Italics and bold: other quote tests: (3,2,3,3)
-!! options
!! wikitext
'''this is about ''foo'''s family'''
-!! html
+!! html/*
<p>'<i>this is about </i>foo<b>s family</b>
</p>
!!end
@@ -1035,9 +1071,11 @@ Italics and bold: other quote tests: (3,(2,2),3)
Italicized possessive
!! wikitext
The ''[[Main Page]]'''s talk page.
-!! html
+!! html/php
<p>The <i><a href="/wiki/Main_Page" title="Main Page">Main Page</a>'</i>s talk page.
</p>
+!! html/parsoid
+<p>The <i><a rel="mw:WikiLink" href="Main_Page" title="Main Page">Main Page</a>'</i>s talk page.</p>
!! end
!! test
@@ -1201,38 +1239,84 @@ Ruby markup (W3C-style)
</p>
!! end
-# There is a tidy bug here: http://sourceforge.net/p/tidy/bugs/946/
+# The next two test different paths in the sanitizer.
!! test
Non-word characters don't terminate tag names (bug 17663, 40670, 52022)
!! wikitext
-<b→> doesn't work! </b→>
+<blockquote|>a</blockquote>
+
+<b→> doesn't terminate </b→>
-<bä> doesn't work! </bä>
+<bä> doesn't terminate </bä>
-<boo> works fine </boo>
+<boo> doesn't terminate </boo>
-<s.foo>s.foo</s.foo>
+<s.foo> doesn't terminate </s.foo>
<sub-ID#1>
!! html
-<p>&lt;b→&gt; doesn't work! &lt;/b→&gt;
-</p><p>&lt;bä&gt; doesn't work! &lt;/bä&gt;
-</p><p>&lt;boo&gt; works fine &lt;/boo&gt;
-</p><p>&lt;s.foo&gt;s.foo&lt;/s.foo&gt;
+<p>&lt;blockquote|&gt;a&lt;/blockquote&gt;
+</p><p>&lt;b→&gt; doesn't terminate &lt;/b→&gt;
+</p><p>&lt;bä&gt; doesn't terminate &lt;/bä&gt;
+</p><p>&lt;boo&gt; doesn't terminate &lt;/boo&gt;
+</p><p>&lt;s.foo&gt; doesn't terminate &lt;/s.foo&gt;
</p><p>&lt;sub-ID#1&gt;
</p>
!! end
+# There is a tidy bug here: http://sourceforge.net/p/tidy/bugs/946/
+# If the non-word-character tag made it through the sanitizer, tidy
+# would munge it up.
+!! test
+Non-word characters don't terminate tag names + tidy
+!! wikitext
+<blockquote|>a</blockquote>
+
+<b→> doesn't terminate </b→>
+
+<bä> doesn't terminate </bä>
+
+<boo> doesn't terminate </boo>
+
+<s.foo> doesn't terminate </s.foo>
+
+<sub-ID#1>
+!! html+tidy
+<p>&lt;blockquote|&gt;a</p>
+<p>&lt;b→&gt; doesn't terminate &lt;/b→&gt;</p>
+<p>&lt;bä&gt; doesn't terminate &lt;/bä&gt;</p>
+<p>&lt;boo&gt; doesn't terminate &lt;/boo&gt;</p>
+<p>&lt;s.foo&gt; doesn't terminate &lt;/s.foo&gt;</p>
+<p>&lt;sub-ID#1&gt;</p>
+!! end
+
+###
+### See tests/parser/parserTestsParserHook.php for the <tåg> extension)
+### This checks that HTML5 tags (with non-word characters in the tag
+### name) make it safely through the parser -- the Sanitizer will
+### munge them later, as it should.
+###
+!! test
+Non-word characters are valid in extension tags (T19663)
+!! wikitext
+<tåg>tåg</tåg>
+!! html
+<pre>
+'tåg'
+array (
+)
+</pre>
+
+!! end
+
!! test
Isolated close tags should be treated as literal text (bug 52760)
!! wikitext
</b>
<s.foo>s</s>
-!! html
-<p>&lt;/b&gt;
-</p><p>&lt;s.foo&gt;s&lt;/s&gt;
-</p>
+!! html+tidy
+<p>&lt;s.foo&gt;s</p>
!! end
###
@@ -1328,18 +1412,75 @@ parsoid
!! wikitext
{{echo|&ndash;}}
!! html
-<p><span typeof="mw:Transclusion mw:Entity" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&amp;ndash;"}},"i":0}}]}'>&ndash;</span>
-</p>
+<p><span typeof="mw:Transclusion mw:Entity" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&amp;ndash;"}},"i":0}}]}'>&ndash;</span></p>
!! end
!! test
Properly escape nowiki when combined with other wiki markup
!! options
parsoid=html2wt
+!! html
+<p>* &lt;/nowiki&gt; tag</p>
!! wikitext
<nowiki>* &lt;/nowiki&gt;</nowiki> tag
+!! end
+
+!! test
+T71950: 1. Put nowiki as close to cause as possible, even with non-quote escapable chars
+!! options
+parsoid=html2wt
!! html
-<p>* &lt;/nowiki&gt; tag</p>
+<p>This text: L'<a rel="mw:WikiLink" href="./Foo">Foo</a>
+This text: L''<a rel="mw:WikiLink" href="./Foo">Foo</a>
+This text: L'''<a rel="mw:WikiLink" href="./Foo">Foo</a>''</p>
+!! wikitext
+This text: L'[[Foo]]
+This text: L<nowiki>''</nowiki>[[Foo]]
+This text: L<nowiki>'''</nowiki>[[Foo]]<nowiki>''</nowiki>
+!! end
+
+# This test fails because wikitext whitespace is not normalized before comparing.
+!! test
+T71950: 2. Put nowiki as close to cause as possible, after ' :'
+!! options
+parsoid=html2wt
+!! html
+<p>This text : L''<a rel="mw:WikiLink" href="./Foo">Foo</a>
+</p>
+!! wikitext
+This text : L<nowiki>''</nowiki>[[Foo]]
+!! end
+
+# This test and the next one are html2wt only as they test that incorrect wikitext
+# passed in template arguments gets escaped or wrapped in nowikis where required.
+!! test
+T71482: Use {{!}} instead of nowiki for single pipe in template argument
+!! options
+parsoid=html2wt
+!! html/parsoid
+<p><span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo|bar&quot;}},&quot;i&quot;:0}}]}" about="#mwt1"></span>
+<span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo|bar |[[&quot;}},&quot;i&quot;:0}}]}" about="#mwt2"></p>
+!! wikitext
+{{echo|foo{{!}}bar}}
+{{echo|<nowiki>foo|bar |[[</nowiki>}}
+!! end
+
+!! test
+T53961: Output correct nowikis in template arguments
+!! options
+parsoid=html2wt
+!! html/parsoid
+<p><span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;a [ b&quot;}},&quot;i&quot;:0}}]}" about="#mwt1"></span>
+<span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;a }} b&quot;}},&quot;i&quot;:0}}]}" about="#mwt2"></span>
+<span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;a [[ b&quot;}},&quot;i&quot;:0}}]}" about="#mwt3"></span>
+<span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;a | {{ ]]&quot;}},&quot;i&quot;:0}}]}" about="#mwt4"></span>
+<span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;a }&quot;}},&quot;i&quot;:0}}]}" about="#mwt5"></span></p>
+!! wikitext
+{{echo|a [ b}}
+{{echo|a <nowiki>}}</nowiki> b}}
+{{echo|<nowiki>a [[ b</nowiki>}}
+{{echo|a {{!}} <nowiki>{{ ]]</nowiki>}}
+{{echo|a <nowiki>}</nowiki>}}
!! end
###
@@ -1488,6 +1629,19 @@ Comment semantics: unclosed comment at end
!! end
+# Bug 58184: document parsoid's behaviour
+!! test
+Suppress comment closing tag in lenient browsers
+!! options
+parsoid=wt2html,html2html
+!! wikitext
+<!-- Browsers--!> think this is closed -->
+!! html/php
+
+!! html/parsoid
+<!-- Browsers--¡> think this is closed -->
+!! end
+
!! test
Comment in template title
!! wikitext
@@ -1649,6 +1803,11 @@ x <div>foo</div> z
<p>z</p>
!! end
+# Tidy strips out the empty <div> tags. Parsoid doesn't.
+# So, we have a separate section for Parsoid. We don't want
+# to mimic this stripping behavior in Parsoid. It affects
+# editing experience and also requires us to maintain additional
+# info for RT-ing.
!! test
Empty lines between lines with block tags
!! wikitext
@@ -1687,10 +1846,22 @@ b
<p>d</p>
<p><br /></p>
<div>e</div>
+!! html/parsoid
+<div data-parsoid='{"stx":"html"}'></div>
+
+<p><br /></p>
+<div data-parsoid='{"stx":"html"}'></div><p>a</p>
+
+<p>b</p>
+<div data-parsoid='{"stx":"html"}'>a</div><p>b</p>
+
+<div data-parsoid='{"stx":"html"}'>b</div><p>d</p>
+
+<p><br /></p>
+<div data-parsoid='{"stx":"html"}'>e</div>
!! end
## PHP parser emits output which is broken
-## XXX The parsoid output doesn't match the tidy output.
!! test
Unclosed HTML p-tags should be handled properly
!! wikitext
@@ -1700,15 +1871,42 @@ a
b
!! html/php+tidy
<div>
-<p>foo&lt;/div&gt;</p>
+<p>foo</p>
+</div>
<p>a</p>
-b</div>
+<p>b</p>
!! html/parsoid
<div data-parsoid='{"stx":"html"}'><p data-parsoid='{"stx":"html", "autoInsertedEnd":true}'>foo</p></div>
<p>a</p>
<p>b</p>
!! end
+## SSS FIXME: I can come up with other scenarios where this doesn't work because
+## of eager output of buffered tokens in the p-wrapper. But, I'm going to ignore
+## them for now.
+!! test
+1. P-wrapping should leave sol-transparent tags outside p-tags where possible
+!! options
+parsoid=wt2html
+!! wikitext
+a [[Category:A1]] [[Category:A2]]
+[[Category:A3]]
+[[Category:A4]]
+!! html/parsoid
+<p>a</p>
+<link href="Category:A1"/> <link href="Category:A2"/> <link href="Category:A3"/> <link href="Category:A4"/>
+!! end
+
+!! test
+2. P-wrapping should leave sol-transparent tags outside p-tags where possible
+!! options
+parsoid=wt2html
+!! wikitext
+[[Category:A1]]a
+!! html/parsoid
+<link href="Category:A1"/><p>a</p>
+!! end
+
###
### Preformatted text
###
@@ -1966,8 +2164,11 @@ Entities inside <pre>
</p>
!! end
+# Parsoid doesn't strip empty tags, like Tidy does.
!! test
Empty pre; pre inside other HTML tags (bug 54946)
+!! options
+parsoid=wt2html,wt2wt
!! wikitext
a
@@ -1975,7 +2176,7 @@ a
foo
</pre></div>
<pre></pre>
-!! html
+!! html/php
<p>a
</p>
<div><pre>
@@ -1983,12 +2184,18 @@ foo
</pre></div>
<pre></pre>
-!! html+tidy
+!! html/php+tidy
<p>a</p>
<div>
<pre>
foo
</pre></div>
+!! html/parsoid
+<p>a</p>
+
+<div><pre>foo
+</pre></div>
+<pre></pre>
!! end
!! test
@@ -2156,10 +2363,11 @@ parsoid=wt2html
<table><pre></pre></table>
!! html/parsoid
-<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;pre &lt;pre>x&lt;/pre>"}},"i":0}}]}'>&lt;pre </span>
-<pre>x</pre>
+<pre about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"a":{"&lt;pre":null},"sa":{"&lt;pre":""},"stx":"html","pi":[[{"k":"1","spc":["","","",""]}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;pre &lt;pre>x&lt;/pre>"}},"i":0}}]}'>x</pre>
+
+
+<p>&lt;pre </p>
-<span>&lt;pre </span>
<table></table>
!! end
@@ -2335,6 +2543,41 @@ Templates: Handle comments in the target
<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo"}},"i":0}}]}'>foo</p>
!!end
+!! test
+Templates: Handle comments in parameter names (bug 67657)
+!! wikitext
+{{echo|1
+<!-- should be ignored -->
+=foo}}
+
+{{echo|
+<!-- should be ignored -->
+1 = foo}}
+
+{{echo|1<!-- should be ignored --> = foo}}
+
+{{echo|<!-- should be ignored -->1 = foo}}
+!!html/parsoid
+<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo","key":{"wt":"1\n&lt;!-- should be ignored -->"}}},"i":0}}]}'>foo</p>
+
+<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo","key":{"wt":"&lt;!-- should be ignored -->\n1"}}},"i":0}}]}'>foo</p>
+
+<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo","key":{"wt":"1&lt;!-- should be ignored -->"}}},"i":0}}]}'>foo</p>
+
+<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo","key":{"wt":"&lt;!-- should be ignored -->1"}}},"i":0}}]}'>foo</p>
+!!end
+
+!! test
+Templates: Other wikitext in parameter names (bug 67657)
+!! wikitext
+{{echo|''1''=foo}}
+!!html/parsoid
+<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"&#39;&#39;1&#39;&#39;":{"wt":"foo"}},"i":0}}]}'>{{{1}}}</p>
+!!html/php
+<p>{{{1}}}
+</p>
+!!end
+
#--------------------------------------------------------------------
# Transclusion parameter escaping tests
#--------------------------------------------------------------------
@@ -2431,6 +2674,18 @@ parsoid
<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a : b"}},"i":0}}]}'>a<span typeof="mw:Placeholder" data-parsoid='{"isDisplayHack":true}'> </span>: b</p>
!! end
+## Bug T73412
+!! test
+Templates: Preserve blank parameter names
+!! wikitext
+{{echo|=foo}}
+!! html/php
+<p>{{{1}}}
+</p>
+!! html/parsoid
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"":{"wt":"foo"}},"i":0}}]}'>{{{1}}}</p>
+!! end
+
###
### Parsoid-centric tests for testing RT edge cases for pre
###
@@ -2559,12 +2814,8 @@ c
!! html/parsoid
<pre>a</pre>
-
-<table>
-
-<tbody>
-<tr>
-<td> b</td></tr>
+ <table>
+ <tbody><tr><td> b</td></tr>
</tbody></table>
!!end
@@ -2613,6 +2864,12 @@ a
c <blockquote> foo </blockquote>
<pre><span> foo </span>
</pre>
+!! html/parsoid
+ <p>a </p><p data-parsoid='{"stx":"html"}'> foo </p>
+ <p>b </p><div data-parsoid='{"stx":"html"}'> foo </div>
+ <p>c </p><blockquote data-parsoid='{"stx":"html"}'> foo </blockquote>
+<pre><span> foo </span>
+</pre>
!! html+tidy
<p>a</p>
<p>foo</p>
@@ -2637,6 +2894,9 @@ a
</pre>
b <div> foo </div>
+!! html/parsoid
+<pre>a <span data-parsoid='{"stx":"html"}'>foo</span></pre>
+ b <div data-parsoid='{"stx":"html"}'> foo </div>
!! html+tidy
<pre>
a <span>foo</span>
@@ -2718,7 +2978,7 @@ File:foobar.jpg
!! html
a <ul class="gallery mw-gallery-traditional">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
</div>
</div></li>
@@ -2730,7 +2990,7 @@ File:foobar.jpg
<li class="gallerybox" style="width: 155px">
<div style="width: 155px">
<div class="thumb" style="width: 150px;">
-<div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div>
+<div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div>
</div>
<div class="gallerytext"></div>
</div>
@@ -2878,8 +3138,7 @@ parsoid=wt2html,wt2wt
{{echo| [[Category:foo]]}} <!-- No pre-wrapping -->
!! html
<link rel="mw:PageProp/Category" href="./Category:Foo"> <!-- No pre-wrapping -->
-<span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":" [[Category:foo]]"}},"i":0}}]}'> </span>
-<link rel="mw:PageProp/Category" href="./Category:Foo" about="#mwt1"> <!-- No pre-wrapping -->
+<span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":" [[Category:foo]]"}},"i":0}}]}'> </span><link rel="mw:PageProp/Category" href="./Category:Foo" about="#mwt1"> <!-- No pre-wrapping -->
!! end
!! test
@@ -2892,7 +3151,6 @@ parsoid=wt2html,wt2wt
!! html
<pre>
<link rel="mw:PageProp/Category" href="./Category:Foo"> a
-
<link rel="mw:PageProp/Category" href="./Category:Foo"> <span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"b"}},"i":0}}]}'>b</span></pre>
!! end
@@ -3110,10 +3368,12 @@ Definition list with wikilink containing colon
Definition list with news link containing colon
!! wikitext
; news:alt.wikipedia.rox: This isn't even a real newsgroup!
-!! html
+!! html/php
<dl><dt> <a rel="nofollow" class="external free" href="news:alt.wikipedia.rox">news:alt.wikipedia.rox</a></dt>
<dd> This isn't even a real newsgroup!</dd></dl>
+!! html/parsoid
+<dl><dt> <a rel="mw:ExtLink" href="news:alt.wikipedia.rox" data-parsoid='{"stx":"url"}'>news:alt.wikipedia.rox</a></dt><dd data-parsoid='{"stx":"row"}'> This isn't even a real newsgroup!</dd></dl>
!! end
!! test
@@ -3803,7 +4063,7 @@ Definition Lists: Weird Ones: Test 1
<dl>
<dt>
<dl>
-<dt> foo<span typeof="mw:Placeholder" data-parsoid='{"src":" "}'>&nbsp;</span></dt>
+<dt> foo<span typeof="mw:Placeholder">&nbsp;</span></dt>
<dd data-parsoid='{"stx":"row"}'> bar (who uses this?)</dd>
</dl></dt>
</dl></dd>
@@ -3815,6 +4075,122 @@ Definition Lists: Weird Ones: Test 1
</ul>
!! end
+!! test
+Definition Lists: colons occurring in tags
+!! wikitext
+;a:b
+;'''a:b'''
+;<i>a:b</i>
+;<span>a:b</span>
+;<div>a:b</div>
+;<div>a
+:b</div>
+;{{echo|a:b}}
+;{{echo|''a:b''}}
+;;;''a:b''
+!! html+tidy
+<dl>
+<dt>a</dt>
+<dd>b</dd>
+<dt><b>a:b</b></dt>
+<dt><i>a:b</i></dt>
+<dt><span>a:b</span></dt>
+<dd>
+<div>a:b</div>
+</dd>
+<dd>
+<div>a
+<dl>
+<dd>b</dd>
+</dl>
+</div>
+</dd>
+<dt>a</dt>
+<dd>b</dd>
+<dt><i>a:b</i></dt>
+</dl>
+<dl>
+<dd>
+<dl>
+<dd>
+<dl>
+<dt><i>a:b</i></dt>
+</dl>
+</dd>
+</dl>
+</dd>
+</dl>
+!! end
+
+!! test
+Definition Lists: colons and tables 1
+!! wikitext
+:{|
+| x
+|}
+:{|
+| y
+|}
+!! html
+<dl><dd><table>
+<tr>
+<td> x
+</td></tr></table></dd></dl>
+<dl><dd><table>
+<tr>
+<td> y
+</td></tr></table></dd></dl>
+
+!! end
+
+# Parsoid's output (as documented below) differs from php's in this case.
+# This is probably a bug. If we fixup parsoid to match php's output, the
+# above test should pass and the below test case can be removed. It is
+# unclear which output is more desirable.
+
+!! test
+Definition Lists: colons and tables 2
+!! wikitext
+:{|
+| x
+|}
+:{|
+| y
+|}
+!! html/parsoid
+<dl><dd><table>
+<tr>
+<td> x
+</td></tr></table></dd>
+<dd><table>
+<tr>
+<td> y
+</td></tr></table></dd></dl>
+!! end
+
+!! test
+Definition Lists: template interaction
+!! wikitext
+::{{definition_list}}
+
+:one
+::{{definition_list}}
+:::two
+:::three
+::four
+!! html/parsoid
+<dl><dd><dl data-parsoid='{}'><dd about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[]]}' data-mw='{"parts":[":",{"template":{"target":{"wt":"definition_list","href":"./Template:Definition_list"},"params":{},"i":0}}]}'>one</dd><span about="#mwt1">
+</span><dd about="#mwt1">two</dd></dl></dd></dl>
+
+<dl><dd data-parsoid='{}'>one
+<dl><dd about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"pi":[[]]}' data-mw='{"parts":["::",{"template":{"target":{"wt":"definition_list","href":"./Template:Definition_list"},"params":{},"i":0}},"\n:::two\n:::three"]}'>one</dd><span about="#mwt2">
+</span><dd about="#mwt2">two
+<dl><dd>two</dd>
+<dd>three</dd></dl></dd>
+<dd data-parsoid='{}'>four</dd></dl></dd></dl>
+!! end
+
+
###
### External links
###
@@ -4004,8 +4380,79 @@ External links: with no contents
</p>
!! html/parsoid
<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo"></a></p>
-<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo">Bar</a></p>
-<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo"><span>Bar</span></a></p>
+<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" title="wikipedia:Foo">Bar</a></p>
+<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" title="wikipedia:Foo"><span>Bar</span></a></p>
+!! end
+
+!! test
+External links: Free with trailing punctuation
+!! wikitext
+http://example.com,
+http://example.com;
+http://example.com\
+http://example.com.
+http://example.com:
+http://example.com!
+http://example.com?
+http://example.com)
+http://example.com/url_with_(brackets)
+(http://example.com/url_without_brackets)
+http://example.com/url_with_entity&nbsp;
+http://example.com/url_with_entity&#xA0;
+http://example.com/url_with_entity&#160;
+http://example.com/url_with_entity&lt;
+http://example.com/url_with_entity&#x3C;
+http://example.com/url_with_entity&#60;
+!! html/php
+<p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>,
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>;
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>\
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>.
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>:
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>!
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>?
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>)
+<a rel="nofollow" class="external free" href="http://example.com/url_with_(brackets)">http://example.com/url_with_(brackets)</a>
+(<a rel="nofollow" class="external free" href="http://example.com/url_without_brackets">http://example.com/url_without_brackets</a>)
+<a rel="nofollow" class="external free" href="http://example.com/url_with_entity ">http://example.com/url_with_entity </a>
+<a rel="nofollow" class="external free" href="http://example.com/url_with_entity ">http://example.com/url_with_entity </a>
+<a rel="nofollow" class="external free" href="http://example.com/url_with_entity ">http://example.com/url_with_entity </a>
+<a rel="nofollow" class="external free" href="http://example.com/url_with_entity">http://example.com/url_with_entity</a>&lt;
+<a rel="nofollow" class="external free" href="http://example.com/url_with_entity%3C">http://example.com/url_with_entity%3C</a>
+<a rel="nofollow" class="external free" href="http://example.com/url_with_entity%3C">http://example.com/url_with_entity%3C</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://example.com">http://example.com</a>,
+<a rel="mw:ExtLink" href="http://example.com">http://example.com</a>;
+<a rel="mw:ExtLink" href="http://example.com">http://example.com</a>\
+<a rel="mw:ExtLink" href="http://example.com">http://example.com</a>.
+<a rel="mw:ExtLink" href="http://example.com">http://example.com</a>:
+<a rel="mw:ExtLink" href="http://example.com">http://example.com</a>!
+<a rel="mw:ExtLink" href="http://example.com">http://example.com</a>?
+<a rel="mw:ExtLink" href="http://example.com">http://example.com</a>)
+<a rel="mw:ExtLink" href="http://example.com/url_with_(brackets)">http://example.com/url_with_(brackets)</a>
+(<a rel="mw:ExtLink" href="http://example.com/url_without_brackets">http://example.com/url_without_brackets</a>)
+<a rel="mw:ExtLink" href="http://example.com/url_with_entity ">http://example.com/url_with_entity </a>
+<a rel="mw:ExtLink" href="http://example.com/url_with_entity ">http://example.com/url_with_entity </a>
+<a rel="mw:ExtLink" href="http://example.com/url_with_entity ">http://example.com/url_with_entity </a>
+<a rel="mw:ExtLink" href="http://example.com/url_with_entity">http://example.com/url_with_entity</a><span typeof="mw:Entity">&lt;</span>
+<a rel="mw:ExtLink" href="http://example.com/url_with_entity&lt;">http://example.com/url_with_entity&lt;</a>
+<a rel="mw:ExtLink" href="http://example.com/url_with_entity&lt;">http://example.com/url_with_entity&lt;</a></p>
+!! end
+
+!! test
+External links: No preceding word characters allowed (bug 65278)
+!! wikitext
+NOPEhttp://example.com
+N0http://example.com
+ok:http://example.com
+ok-http://example.com
+!! html
+<p>NOPEhttp://example.com
+N0http://example.com
+ok:<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>
+ok-<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>
+</p>
!! end
!! test
@@ -4095,10 +4542,12 @@ URL in text: [http://example.com http://example.com]
External links: Clickable images
!! wikitext
ja-style clickable images: [http://example.com http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png]
-!! html
+!! html/php
<p>ja-style clickable images: <a rel="nofollow" class="external text" href="http://example.com"><img src="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" /></a>
</p>
-!!end
+!! html/parsoid
+<p>ja-style clickable images: <a rel="mw:ExtLink" href="http://example.com"><img src="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" data-parsoid='{"type":"extlink"}'/></a></p>
+!! end
!! test
External links: raw ampersand
@@ -4288,10 +4737,12 @@ http://www.example.com/<hello>
BUG 289: literal ">"-token in URL-tail
!! wikitext
http://www.example.com/<b>html</b>
-!! html
+!! html/php
<p><a rel="nofollow" class="external free" href="http://www.example.com/">http://www.example.com/</a><b>html</b>
</p>
-!!end
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://www.example.com/" data-parsoid='{"stx":"url"}'>http://www.example.com/</a><b data-parsoid='{"stx":"html"}'>html</b></p>
+!! end
!! test
BUG 289: ">"-token in bracketed URL
@@ -4410,7 +4861,7 @@ http://www.example.com/?title=AT%26T
<p><a rel="mw:ExtLink" href="http://www.example.com/?title=AT%26T">http://www.example.com/?title=AT%26T</a></p>
!! end
-# According to http://dev.w3.org/html5/spec/Overview.html#parsing-urls a plain
+# According to http://www.w3.org/TR/2011/WD-html5-20110525/Overview.html#parsing-urls a plain
# % is actually legal in HTML5. Any change in output would need testing though.
!! test
Bug 4781, 5267: %25 in URL
@@ -4751,7 +5202,7 @@ Parenthesis in external links, w/ transclusion or comment
</p><p>(<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>)
</p>
!! html/parsoid
-<p>(<a data-mw='{"attribs":[[{"txt":"href"},{"html":"http://example.com/&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;hi&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[20,31,null,null]}\">hi&lt;/span>"}]]}' typeof="mw:ExpandedAttrs" about="#mwt2" rel="mw:ExtLink" href="http://example.com/hi" data-parsoid='{"stx":"url","a":{"href":"http://example.com/hi"},"sa":{"href":"http://example.com/{{echo|hi}}"}}'>http://example.com/hi</a>)</p>
+<p>(<a typeof="mw:ExpandedAttrs" about="#mwt2" rel="mw:ExtLink" href="http://example.com/hi" data-parsoid='{"stx":"url","a":{"href":"http://example.com/hi"},"sa":{"href":"http://example.com/{{echo|hi}}"}}' data-mw='{"attribs":[[{"txt":"href"},{"html":"http://example.com/&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[20,31,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;hi&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">hi&lt;/span>"}]]}'>http://example.com/hi</a>)</p>
<p>(<a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url","a":{"href":"http://example.com"},"sa":{"href":"http://example.com&lt;!-- hi -->"}}'>http://example.com</a>)</p>
!! end
@@ -5129,8 +5580,8 @@ Accept "!!" in table data
</td></tr></table>
!! html/parsoid
-<table data-parsoid='{}'>
-<tbody data-parsoid='{}'><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'> Foo!! </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'></td></tr>
+<table>
+<tbody><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'> Foo!! </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'></td></tr>
</tbody></table>
!! end
@@ -5295,7 +5746,6 @@ 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
@@ -5320,6 +5770,25 @@ parsoid=wt2html,html2html
<td><a rel="mw:ExtLink" href="ftp://|x||"></a>" onmouseover="alert(document.cookie)">test</td></tr></tbody></table>
!! end
+# FIXME: The php output is broken.
+!! test
+! and || in td attributes should not be parsed as <th>/<td>
+!! wikitext
+{|
+| style="color: red !important;" data-contrived="put this here ||" | foo
+|}
+!! html/php
+<table>
+<tr>
+<td> style="color: red !important;" data-contrived="put this here </td>
+<td> foo
+</td></tr></table>
+
+!! html/parsoid
+<table>
+<tbody><tr><td style="color: red !important;" data-contrived="put this here ||" data-parsoid='{"autoInsertedEnd":true}'> foo</td></tr>
+</tbody></table>
+!! end
!! test
Indented table markup mixed with indented pre content (proposed in bug 6200)
@@ -5344,50 +5813,83 @@ Indented table markup mixed with indented pre content (proposed in bug 6200)
!! end
!! test
-Template-generated table cell attributes and cell content
+1. Template-generated table cell attributes and cell content
!! wikitext
{|
|{{table_attribs}}
| {{table_attribs}}
+|| {{table_attribs_5}}
+| <!--foo--> <!--bar--> <!--baz--> {{table_attribs}}
+|align=center {{table_attribs}}
+| <!--foo--> align=center <!--bar--> {{table_attribs}}
|}
!! html
<table>
<tr>
-<td style="color: red"> Foo
+<td style="color:red;">Foo
</td>
-<td style="color: red"> Foo
+<td style="color:red;">Foo
+</td>
+<td> style="color:red;"</td>
+<td>Bar
+</td>
+<td style="color:red;">Foo
+</td>
+<td align="center" style="color:red;">Foo
+</td>
+<td align="center" style="color:red;">Foo
</td></tr></table>
!! end
!! test
-Template-generated table cell attributes and cell content (2)
+2. Template-generated table cell attributes and cell content
!! wikitext
{|
-|align=center {{table_attribs}}
+|{{table_attribs_2}}
|}
-!! html
+!! html/php
<table>
<tr>
-<td align="center" style="color: red"> Foo
+<td style="color:red;">Foo
+</td>
+<td>Bar</td>
+<td>Baz
</td></tr></table>
+!! html/parsoid
+<table>
+<tbody><tr><td about="#mwt1" typeof="mw:Transclusion" style="color:red;" data-mw='{"parts":["|",{"template":{"target":{"wt":"table_attribs_2","href":"./Template:Table_attribs_2"},"params":{},"i":0}}]}'>Foo</td>
+<td about="#mwt1">Bar</td><td about="#mwt1">Baz</td></tr>
+</tbody></table>
!! end
!! test
-Template-generated table cell attributes and cell content (3)
+3. Template-generated table cell attributes and cell content
!! wikitext
{|
+!align=center {{table_header_cells}}
+|-
|align=center {{table_cells}}
|}
-!! html
+!! html/php
<table>
<tr>
-<td align="center" style="color: red"> Foo </td>
-<td> Bar </td>
-<td> Baz
+<th align="center" style="color:red;">Foo</th>
+<th style="color:red;"><i>Bar</i></th>
+<th style="color:brown;"><i>Foo</i> and Baz
+</th></tr>
+<tr>
+<td align="center" style="color:red;">Foo</td>
+<td style="color:red;"><i>Bar</i></td>
+<td style="color:brown;"><i>Foo</i> and Baz
</td></tr></table>
+!! html/parsoid
+<table>
+<tbody><tr><th align="center" style="color:red;" typeof="mw:Transclusion" about="#mwt1" data-mw='{"parts":["!align=center ",{"template":{"target":{"wt":"table_header_cells","href":"./Template:Table_header_cells"},"params":{},"i":0}}]}'>Foo</th><th about="#mwt1" style="color:red;"><i about="#mwt1">Bar</i></th><th about="#mwt1" style="color:brown;"><i about="#mwt1">Foo</i> and Baz</th></tr><tr>
+<td align="center" style="color:red;" typeof="mw:Transclusion" about="#mwt1" data-mw='{"parts":["|align=center ",{"template":{"target":{"wt":"table_cells","href":"./Template:Table_cells"},"params":{},"i":0}}]}'>Foo</td><td about="#mwt1" style="color:red;"><i about="#mwt1">Bar</i></td><td about="#mwt1" style="color:brown;"><i about="#mwt1">Foo</i> and Baz</td></tr>
+</tbody></table>
!! end
!! test
@@ -5450,7 +5952,7 @@ Wikitext table with a lot of comments
<!-- c0 -->
| foo
<!-- c1 -->
-|- <!-- c2 -->
+|-<!-- c2 -->
<!-- c3 -->
|<!-- c4 -->
<!-- c5 -->
@@ -5467,6 +5969,26 @@ Wikitext table with a lot of comments
!! end
!! test
+Wikitext table comments represented in parsoid dom
+!! wikitext
+{|<!--c1--><!--c2-->
+|-<!--c3-->
+| x
+|}
+!! html/php+tidy
+<table>
+<tr>
+<td>x</td>
+</tr>
+</table>
+!! html/parsoid
+<table><!--c1--><!--c2-->
+<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'><!--c3-->
+<td data-parsoid='{"autoInsertedEnd":true}'> x</td></tr>
+</tbody></table>
+!! end
+
+!! test
Wikitext table with double-line table cell
!! wikitext
{|
@@ -5548,6 +6070,68 @@ Build table with {{!}}
!! end
+!! test
+Build table with pipe as data
+!! wikitext
+{| class="wikitable"
+! header
+! second header
+|- style="color:red;"
+| data || style="color:red;" | second data
+|-
+| style="color:red;" | data with | || style="color:red;" | second data with |
+|-
+|| data with | ||| second data with |
+|}
+!! html
+<table class="wikitable">
+<tr>
+<th> header
+</th>
+<th> second header
+</th></tr>
+<tr style="color:red;">
+<td> data </td>
+<td style="color:red;"> second data
+</td></tr>
+<tr>
+<td style="color:red;"> data with | </td>
+<td style="color:red;"> second data with |
+</td></tr>
+<tr>
+<td> data with | </td>
+<td> second data with |
+</td></tr></table>
+
+!! end
+
+!! test
+Build table with wikilink
+!! wikitext
+{| class="wikitable"
+! header || second header
+|- style="color:red;"
+| data [[Main Page|linktext]] || second data [[Main Page|linktext]]
+|-
+| data || second data [[Main Page|link|text with pipe]]
+|}
+!! html
+<table class="wikitable">
+<tr>
+<th> header </th>
+<th> second header
+</th></tr>
+<tr style="color:red;">
+<td> data <a href="/wiki/Main_Page" title="Main Page">linktext</a> </td>
+<td> second data <a href="/wiki/Main_Page" title="Main Page">linktext</a>
+</td></tr>
+<tr>
+<td> data </td>
+<td> second data <a href="/wiki/Main_Page" title="Main Page">link|text with pipe</a>
+</td></tr></table>
+
+!! end
+
# The expected HTML structure in this test is debatable. The PHP parser does
# not parse this kind of table at all. The main focus for Parsoid is on
# round-tripping, so this output is ok for now. TODO: revisit!
@@ -5574,7 +6158,7 @@ Wikitext table with html-syntax row
!! test
Implicit <td> after a |-
!! options
-parsoid=wt2html,wt2wt
+parsoid=wt2html,html2html
!! wikitext
{|
|-
@@ -5598,7 +6182,7 @@ a
!! test
<pre> tags should be recognized in an explicit <td> context, but not in an implicit <td> context
!! options
-parsoid=wt2html,wt2wt
+parsoid=wt2html,html2html
!! wikitext
{|
|-
@@ -5638,10 +6222,11 @@ a
!! end
# PHP + Tidy strips the list out of the table; Parsoid wraps it.
+# Parsoid generates the missing <td>, so wt2wt won't succeed.
!! test
Lists should be recognized in an implicit <td> context
!! options
-parsoid=wt2html,wt2wt
+parsoid=wt2html,html2html
!! wikitext
{|
|-
@@ -5668,6 +6253,28 @@ parsoid=wt2html,wt2wt
!! end
!! test
+Table cells not properly parsed in an implicit-td context
+!! wikitext
+{|
+|-
+{{table_attribs_4}} || a || b
+|}
+!! html/php+tidy
+<table>
+<tr>
+<td style="background-color:#DC241f;" width="10px"></td>
+<td>a</td>
+<td>b</td>
+</tr>
+</table>
+!! html/parsoid
+<table>
+<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
+<td style="background-color:#DC241f;" width="10px" about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"autoInsertedEnd":true,"pi":[[]]}' data-mw='{"parts":["",{"template":{"target":{"wt":"table_attribs_4","href":"./Template:Table_attribs_4"},"params":{},"i":0}}," "]}'> </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'> a </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'> b</td></tr>
+</tbody></table>
+!! end
+
+!! test
Parsoid: Round-trip tables directly followed by content (bug 51219)
!! options
parsoid=wt2html,wt2wt
@@ -5679,20 +6286,30 @@ parsoid=wt2html,wt2wt
{|
|baz
|}<b>quux</b>
-!! html
-<table><tbody>
+!! html+tidy
+<table>
<tr>
-<td>foo</td></tr></tbody></table> bar
+<td>foo</td>
+</tr>
+</table>
+<p>bar</p>
<table>
-<tbody>
<tr>
-<td>baz</td></tr></tbody></table><b>quux</b>
+<td>baz</td>
+</tr>
+</table>
+<p><b>quux</b></p>
!! end
!! test
Parsoid: Default to a newline after tables in new content (bug 51219)
!! options
parsoid=html2wt
+!! html
+<table><tbody>
+<tr><td>foo</td></tr></tbody></table> bar
+<table><tbody>
+<tr><td>baz</td></tr></tbody></table><b>quux</b>
!! wikitext
{|
|foo
@@ -5702,23 +6319,18 @@ parsoid=html2wt
|baz
|}
'''quux'''
-!! html
-<table><tbody>
-<tr><td>foo</td></tr></tbody></table> bar
-<table><tbody>
-<tr><td>baz</td></tr></tbody></table><b>quux</b>
!! end
!! test
Parsoid: newline inducing block nodes don't suppress <nowiki>
!! options
parsoid=html2wt
+!! html
+ a<h1>foo</h1>
!! wikitext
<nowiki> </nowiki>a
= foo =
-!! html
- a<h1>foo</h1>
!! end
!! test
@@ -5823,6 +6435,27 @@ parsoid=html2wt
|}
!! end
+!!test
+Testing serialization after deletion of table cells
+!!options
+parsoid={
+ "modes": ["wt2wt", "selser"],
+ "changes": [
+ ["#x", "remove"]
+ ]
+}
+!!wikitext
+{|
+!h1 !!h2 !!h3
+| id="x" |c1 {{!}}{{!}}{{!}}c2 |||c3
+|}
+!! wikitext/edited
+{|
+!h1 !!h2 !!h3
+|c2 |||c3
+|}
+!!end
+
###
### Internal links
###
@@ -5953,9 +6586,11 @@ Bug 43661: Piped links with identical prefixes
Link with HTML entity in suffix / tail
!! wikitext
[[Main Page]]&quot;, [[Main Page]]&#97;
-!! html
+!! html/php
<p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>&quot;, <a href="/wiki/Main_Page" title="Main Page">Main Page</a>&#97;
</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page">Main Page</a><span typeof="mw:Entity" data-parsoid='{"src":"&amp;quot;","srcContent":"\""}'>"</span>, <a rel="mw:WikiLink" href="./Main_Page" title="Main Page">Main Page</a><span typeof="mw:Entity" data-parsoid='{"src":"&amp;#97;","srcContent":"a"}'>a</span></p>
!! end
!! test
@@ -5990,10 +6625,13 @@ Piped link with extlink-like text
!! wikitext
[[Main Page|[bar]]]
[[Main Page|This is a [bar]]]
-!! html
+!! html/php
<p><a href="/wiki/Main_Page" title="Main Page">[bar]</a>
<a href="/wiki/Main_Page" title="Main Page">This is a [bar]</a>
</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page" data-parsoid='{"stx":"piped"}'>[bar]</a>
+<a rel="mw:WikiLink" href="./Main_Page" title="Main Page" data-parsoid='{"stx":"piped"}'>This is a [bar]</a></p>
!! end
!! test
@@ -6058,11 +6696,10 @@ Namespace takes precedence over interwiki link (bug 51680)
Link to namespace preferred over interwiki with correct rel attribute
!! options
parsoid=html2wt,html2html
+!! html
+<p><a rel="mw:WikiLink" href="./MemoryAlpha:AlphaTest" title="MemoryAlpha:AlphaTest">MemoryAlpha:AlphaTest</a></p>
!! wikitext
[[MemoryAlpha:AlphaTest]]
-!! html
-<p><a rel="mw:WikiLink" href="./MemoryAlpha:AlphaTest" title="MemoryAlpha:AlphaTest">MemoryAlpha:AlphaTest</a>
-</p>
!! end
!! test
@@ -6213,7 +6850,7 @@ Link containing double-single-quotes '' in text embedded in italics (bug 4598 sa
!! test
Link with double quotes in title part (literal) and alternate part (interpreted)
!! wikitext
-[[File:Denys Savchenko ''Pentecoste''.jpg]]
+[[File:Denys_Savchenko_''Pentecoste''.jpg]]
[[''Pentecoste'']]
@@ -6227,7 +6864,7 @@ Link with double quotes in title part (literal) and alternate part (interpreted)
</p><p><a href="/index.php?title=%27%27Pentecoste%27%27&amp;action=edit&amp;redlink=1" class="new" title="''Pentecoste'' (page does not exist)"><i>Pentecoste</i></a>
</p>
!! html/parsoid
-<meta typeof="mw:Placeholder"/>
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:Denys_Savchenko_''Pentecoste''.jpg"><img resource="./File:Denys_Savchenko_''Pentecoste''.jpg" src="./Special:FilePath/Denys_Savchenko_''Pentecoste''.jpg" height="220" width="220"/></a></span></p>
<p><a rel="mw:WikiLink" href="''Pentecoste''" title="''Pentecoste''">''Pentecoste''</a></p>
<p><a rel="mw:WikiLink" href="''Pentecoste''" title="''Pentecoste''">Pentecoste</a></p>
<p><a rel="mw:WikiLink" href="''Pentecoste''" title="''Pentecoste''"><i>Pentecoste</i></a></p>
@@ -6237,15 +6874,20 @@ Link with double quotes in title part (literal) and alternate part (interpreted)
Broken image links with HTML captions (bug 39700)
!! wikitext
[[File:Nonexistent|<script></script>]]
-[[File:Nonexistent|100px|<script></script>]]
+[[File:Nonexistent|100x100px|<script></script>]]
[[File:Nonexistent|&lt;]]
[[File:Nonexistent|a<i>b</i>c]]
-!! html
+!! html/php
<p><a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;script&gt;&lt;/script&gt;</a>
<a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;script&gt;&lt;/script&gt;</a>
<a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;</a>
<a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">abc</a>
</p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"&lt;script>&lt;/script>"}'><a href="./File:Nonexistent"><img resource="./File:Nonexistent" src="./Special:FilePath/Nonexistent" height="220" width="220"/></a></span>
+<span typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"&lt;script>&lt;/script>"}'><a href="./File:Nonexistent" data-parsoid='{"a":{"href":"./File:Nonexistent"},"sa":{}}'><img resource="./File:Nonexistent" src="./Special:FilePath/Nonexistent" height="100" width="100"/></a></span>
+<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"&amp;lt;"}'><a href="./File:Nonexistent"><img resource="./File:Nonexistent" src="./Special:FilePath/Nonexistent" height="220" width="220"/></a></span>
+<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"a&lt;i>b&lt;/i>c"}'><a href="./File:Nonexistent"><img resource="./File:Nonexistent" src="./Special:FilePath/Nonexistent" height="220" width="220"/></a></span></p>
!! end
!! test
@@ -6483,7 +7125,7 @@ title=[[User:test/123]]
<p><a href="#a">b</a>
</p>
!! html/parsoid
-<p data-parsoid='{}'><a rel="mw:WikiLink" href="../User:Test/123#a" data-parsoid='{"stx":"piped","a":{"href":"../User:Test/123#a"},"sa":{"href":"#a"}}'>b</a></p>
+<p><a rel="mw:WikiLink" href="../User:Test/123#a" data-parsoid='{"stx":"piped","a":{"href":"../User:Test/123#a"},"sa":{"href":"#a"}}'>b</a></p>
!! end
!! test
@@ -6503,7 +7145,7 @@ parsoid
!! wikitext
{{echo|Some [[Fool]]}}s
!! html
-<p data-parsoid='{}'><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]"}},"i":0}},"s"]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some </span><a rel="mw:WikiLink" href="./Fool" title="Fool" about="#mwt1" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a></p>
+<p><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]"}},"i":0}},"s"]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some </span><a rel="mw:WikiLink" href="./Fool" title="Fool" about="#mwt1" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a></p>
!! end
!! test
@@ -6513,7 +7155,7 @@ parsoid
!! wikitext
{{echo|Some [[Fool]]s are '''bold and foolish'''}}
!! html
-<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]s are &#39;&#39;&#39;bold and foolish&#39;&#39;&#39;"}},"i":0}}]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some <a rel="mw:WikiLink" href="./Fool" title="Fool" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a> are <b data-parsoid="{}">bold and foolish</b></p>
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]s are &#39;&#39;&#39;bold and foolish&#39;&#39;&#39;"}},"i":0}}]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some <a rel="mw:WikiLink" href="./Fool" title="Fool" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a> are <b>bold and foolish</b></p>
!! end
!! article
@@ -6562,10 +7204,10 @@ mótmælenda[[söfnuður|söfnuðir]]xxx
Parsoid link trail escaping
!! options
parsoid=html2wt,html2html
-!! wikitext
-[[apple]]<nowiki/>s
!! html
<p><a rel="mw:WikiLink" href="Apple" title="Apple">apple</a>s</p>
+!! wikitext
+[[apple]]<nowiki/>s
!! end
!! test
@@ -6573,10 +7215,10 @@ Parsoid link prefix escaping
!! options
language=is
parsoid=html2wt,html2html
-!! wikitext
-Aðrir mótmælenda<nowiki/>[[söfnuður]]
!! html
<p>Aðrir mótmælenda<a rel="mw:WikiLink" href="Söfnuður" title="Söfnuður">söfnuður</a></p>
+!! wikitext
+Aðrir mótmælenda<nowiki/>[[söfnuður]]
!! end
!! test
@@ -6624,20 +7266,28 @@ Link with angle bracket after anchor
!! test
Inline interwiki link
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
[[MeatBall:SoftSecurity]]
-!! html
+!! html/php
<p><a href="http://www.usemod.com/cgi-bin/mb.pl?SoftSecurity" class="extiw" title="meatball:SoftSecurity">MeatBall:SoftSecurity</a>
</p>
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?SoftSecurity" title="meatball:SoftSecurity">MeatBall:SoftSecurity</a></p>
!! end
!! test
Inline interwiki link with empty title (bug 2372)
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
[[MeatBall:]]
-!! html
+!! html/php
<p><a href="http://www.usemod.com/cgi-bin/mb.pl" class="extiw" title="meatball:">MeatBall:</a>
</p>
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?" title="meatball:">MeatBall:</a></p>
!! end
!! test
@@ -6666,6 +7316,10 @@ Interwiki link with fragment (bug 2130)
!! end
# Ideally the wikipedia: prefix here should be proto-relative too
+# [CSA]: this is kind of a bogus test, as the PHP parser test doesn't
+# define the 'en' prefix, and originally the test used 'wikipedia',
+# which isn't a localinterwiki prefix hence the links to the 'en:Foo'
+# article.
!! test
Different interwiki prefixes mapping to the same URL
!! wikitext
@@ -6683,19 +7337,19 @@ Different interwiki prefixes mapping to the same URL
[[ wikiPEdia :Foo]]
!! html/parsoid
-<p><a rel="mw:ExtLink" href="//en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"//en.wikipedia.org/wiki/Foo"},"sa":{"href":":en:Foo"},"isIW":true}'>en:Foo</a></p>
+<p><a rel="mw:ExtLink" href="//en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"//en.wikipedia.org/wiki/Foo"},"sa":{"href":":en:Foo"},"isIW":true}' title="en:Foo">en:Foo</a></p>
-<p><a rel="mw:ExtLink" href="//en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"piped","a":{"href":"//en.wikipedia.org/wiki/Foo"},"sa":{"href":":en:Foo"},"isIW":true}'>Foo</a></p>
+<p><a rel="mw:ExtLink" href="//en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"piped","a":{"href":"//en.wikipedia.org/wiki/Foo"},"sa":{"href":":en:Foo"},"isIW":true}' title="en:Foo">Foo</a></p>
-<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"wikipedia:Foo"},"isIW":true}'>wikipedia:Foo</a></p>
+<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"wikipedia:Foo"},"isIW":true}' title="wikipedia:Foo">wikipedia:Foo</a></p>
-<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"piped","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":":wikipedia:Foo"},"isIW":true}'>Foo</a></p>
+<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"piped","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":":wikipedia:Foo"},"isIW":true}' title="wikipedia:Foo">Foo</a></p>
-<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/en:Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/en:Foo"},"sa":{"href":"wikipedia:en:Foo"},"isIW":true}'>wikipedia:en:Foo</a></p>
+<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/en:Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/en:Foo"},"sa":{"href":"wikipedia:en:Foo"},"isIW":true}' title="wikipedia:en:Foo">wikipedia:en:Foo</a></p>
-<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/en:Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/en:Foo"},"sa":{"href":":wikipedia:en:Foo"},"isIW":true}'>wikipedia:en:Foo</a></p>
+<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/en:Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/en:Foo"},"sa":{"href":":wikipedia:en:Foo"},"isIW":true}' title="wikipedia:en:Foo">wikipedia:en:Foo</a></p>
-<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":" wikiPEdia :Foo"},"isIW":true}'> wikiPEdia :Foo</a></p>
+<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":" wikiPEdia :Foo"},"isIW":true}' title="wikipedia:Foo"> wikiPEdia :Foo</a></p>
!! end
!! test
@@ -6707,60 +7361,97 @@ Interwiki links that cannot be represented in wiki syntax
[http://de.wikipedia.org/wiki/Foo?action=history has query]
[http://de.wikipedia.org/wiki/#foo is just fragment]
+!! html/php
+<p><a href="http://www.usemod.com/cgi-bin/mb.pl?ok" class="extiw" title="meatball:ok">meatball:ok</a>
+<a href="http://www.usemod.com/cgi-bin/mb.pl?ok#foo" class="extiw" title="meatball:ok">ok with fragment</a>
+<a href="http://www.usemod.com/cgi-bin/mb.pl?ok_as_well%3F" class="extiw" title="meatball:ok as well?">ok ending with ? mark</a>
+<a rel="nofollow" class="external text" href="http://de.wikipedia.org/wiki/Foo?action=history">has query</a>
+<a rel="nofollow" class="external text" href="http://de.wikipedia.org/wiki/#foo">is just fragment</a>
+</p>
!! html/parsoid
-<p><a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?ok">meatball:ok</a>
-<a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?ok#foo">ok with fragment</a>
-<a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?ok_as_well?">ok ending with ? mark</a>
+<p><a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?ok" title="meatball:ok">meatball:ok</a>
+<a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?ok#foo" title="meatball:ok">ok with fragment</a>
+<a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?ok_as_well?" title="meatball:ok as well?">ok ending with ? mark</a>
<a rel="mw:ExtLink" href="http://de.wikipedia.org/wiki/Foo?action=history">has query</a>
<a rel="mw:ExtLink" href="http://de.wikipedia.org/wiki/#foo">is just fragment</a></p>
!! end
!! test
Interwiki links: trail
-!! options
-parsoid
!! wikitext
[[wikipedia:Foo|Ba]]r
-!! html
-<p data-parsoid='{}'><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"piped","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"wikipedia:Foo"},"isIW":true,"tail":"r"}'>Bar</a></p>
+!! html/php
+<p><a href="http://en.wikipedia.org/wiki/Foo" class="extiw" title="wikipedia:Foo">Bar</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"piped","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"wikipedia:Foo"},"isIW":true,"tail":"r"}' title="wikipedia:Foo">Bar</a></p>
!! end
!! test
Local interwiki link
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
[[local:Template:Foo]]
-!! html
+!! html/php
<p><a href="/wiki/Template:Foo" title="Template:Foo">local:Template:Foo</a>
</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Template:Foo" title="Template:Foo">local:Template:Foo</a></p>
!! end
+# Parsoid does not mark self-links, by design.
!! test
Local interwiki link: self-link to current page
!! options
title=[[Main Page]]
+parsoid=wt2html,wt2wt,html2html
!! wikitext
[[local:Main Page]]
-!! html
+!! html/php
<p><strong class="selflink">local:Main Page</strong>
</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page">local:Main Page</a></p>
!! end
!! test
Local interwiki link: prefix only (bug 64167)
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
[[local:]]
-!! html
+!! html/php
<p><a href="/wiki/Main_Page" title="Main Page">local:</a>
</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page">local:</a></p>
!! end
!! test
Local interwiki link: with additional interwiki prefix (bug 61357)
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
[[local:meatball:Hello]]
-!! html
+!! html/php
<p><a href="http://www.usemod.com/cgi-bin/mb.pl?Hello" class="extiw" title="meatball:Hello">local:meatball:Hello</a>
</p>
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?Hello" title="meatball:Hello">local:meatball:Hello</a></p>
+!! end
+
+!! test
+Multiple local interwiki link prefixes
+!! wikitext
+[[local:local:local:local:mi:local:Foo]]
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! html/php
+<p><a href="/wiki/Foo" title="Foo">local:local:local:local:mi:local:Foo</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Foo" title="Foo">local:local:local:local:mi:local:Foo</a></p>
!! end
###
@@ -6770,6 +7461,8 @@ Local interwiki link: with additional interwiki prefix (bug 61357)
!! test
Interlanguage link
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
Blah blah blah
[[zh:Chinese]]
@@ -6777,12 +7470,14 @@ Blah blah blah
<p>Blah blah blah
</p>
!! html/parsoid
-<p>Blah blah blah
-<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
+<p>Blah blah blah</p>
+<link rel="mw:PageProp/Language" href="http://zh.wikipedia.org/wiki/Chinese"/>
!! end
!! test
Interlanguage link with spacing
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
Blah blah blah
[[ zh : Chinese ]]
@@ -6790,12 +7485,14 @@ Blah blah blah
<p>Blah blah blah
</p>
!! html/parsoid
-<p>Blah blah blah
-<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
+<p>Blah blah blah</p>
+<link rel="mw:PageProp/Language" href="http://zh.wikipedia.org/wiki/Chinese"/>
!! end
!! test
Double interlanguage link
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
Blah blah blah
[[es:Spanish]]
@@ -6804,24 +7501,30 @@ Blah blah blah
<p>Blah blah blah
</p>
!! html/parsoid
-<p>Blah blah blah
-<link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/Spanish"/>
-<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
+<p>Blah blah blah</p>
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Spanish"/>
+<link rel="mw:PageProp/Language" href="http://zh.wikipedia.org/wiki/Chinese"/>
!! end
!! test
Interlanguage link variations
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
Blah blah blah
[[ es :Spanish]]
[[ ZH :Chinese]]
+[[es:Foo_bar]]
+[[es:Foo bar]]
!! html/php
<p>Blah blah blah
</p>
!! html/parsoid
-<p>Blah blah blah
-<link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/Spanish" data-parsoid='{"stx":"simple","a":{"href":"//es.wikipedia.org/wiki/Spanish"},"sa":{"href":" es :Spanish"}}'/>
-<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese" data-parsoid='{"stx":"simple","a":{"href":"//zh.wikipedia.org/wiki/Chinese"},"sa":{"href":" ZH :Chinese"}}'/>
+<p>Blah blah blah</p>
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Spanish" />
+<link rel="mw:PageProp/Language" href="http://zh.wikipedia.org/wiki/Chinese" />
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Foo_bar" />
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Foo_bar" />
!! end
!! test
@@ -6835,8 +7538,8 @@ Blah blah blah
<p>Blah blah blah
</p>
!! html/parsoid
-<p>Blah blah blah
-<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
+<p>Blah blah blah</p>
+<link rel="mw:PageProp/Language" href="http://zh.wikipedia.org/wiki/Chinese"/>
!! end
!! test
@@ -6851,9 +7554,9 @@ Blah blah blah
<p>Blah blah blah
</p>
!! html/parsoid
-<p>Blah blah blah
-<link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/Spanish"/>
-<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
+<p>Blah blah blah</p>
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Spanish"/>
+<link rel="mw:PageProp/Language" href="http://zh.wikipedia.org/wiki/Chinese"/>
!! end
!! test
@@ -6865,8 +7568,8 @@ Blah blah blah
<p>Blah blah blah
</p>
!! html/parsoid
-<p>Blah blah blah
-<link rel="mw:PageProp/Language" title="Multilingual" href="//wikisource.org/wiki/Article"/></p>
+<p>Blah blah blah</p>
+<link rel="mw:PageProp/Language" title="Multilingual" href="http://wikisource.org/wiki/Article"/>
!! end
!! test
@@ -6884,84 +7587,119 @@ language=ln
Parsoid bug 53221: Wikilinks should be properly entity-escaped
!! options
parsoid=html2wt
+!! html
+<p>He&amp;nbsp;llo <a href="Foo" rel="mw:WikiLink">He&amp;nbsp;llo</a></p>
+<p>He&amp;nbsp;llo <a href="He&amp;nbsp;llo" rel="mw:WikiLink">He&amp;nbsp;llo</a></p>
!! wikitext
He&amp;nbsp;llo [[Foo|He&amp;nbsp;llo]]
He&amp;nbsp;llo [[He&amp;nbsp;llo]]
-!! html
-<p>He&amp;nbsp;llo <a href="Foo" rel="mw:WikiLink">He&amp;nbsp;llo</a></p>
-<p>He&amp;nbsp;llo <a href="He&amp;nbsp;llo" rel="mw:WikiLink">He&amp;nbsp;llo</a></p>
!! end
!! test
Parsoid: handle constructor well
-!! options
-parsoid
!! wikitext
[[constructor]]
[[constructor:foo]]
-!! html
+!! html/php
+<p><a href="/index.php?title=Constructor&amp;action=edit&amp;redlink=1" class="new" title="Constructor (page does not exist)">constructor</a>
+</p><p><a href="/index.php?title=Constructor:foo&amp;action=edit&amp;redlink=1" class="new" title="Constructor:foo (page does not exist)">constructor:foo</a>
+</p>
+!! html/parsoid
<p><a rel="mw:WikiLink" href="./Constructor" title="Constructor" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Constructor&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor&quot;}}">constructor</a></p>
<p><a rel="mw:WikiLink" href="./Foo" title="Foo" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Foo&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor:foo&quot;}}">constructor:foo</a></p>
!! end
+!! article
+ko:
+!! text
+Test.
+!! endarticle
+
+# Note that `ko` isn't a known interlanguage prefix
!! test
Parsoid: recognize interlanguage links without a target page
!! options
-parsoid
+ill
!! wikitext
+[[es:]]
+
[[ko:]]
-!! html
-<p><link rel="mw:PageProp/Language" href="http://ko.wikipedia.org/wiki/"></p>
+!! html/php
+es:
+!! html/parsoid
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/"/>
+
+<p><a rel="mw:WikiLink" href="./Ko:" title="Ko:">ko:</a></p>
!! end
+# Note that `ko` isn't a known interwiki prefix
!! test
Parsoid: recognize interwiki links without a target page
!! options
-parsoid
+parsoid=wt2html,wt2wt,html2html
!! wikitext
+[[:es:]]
+
[[:ko:]]
-!! html
-<p><a rel="mw:ExtLink" href="//ko.wikipedia.org/wiki/">ko:</a></p>
+!! html/php
+<p><a href="http://es.wikipedia.org/wiki/" class="extiw" title="es:">es:</a>
+</p><p><a href="/wiki/Ko:" title="Ko:">ko:</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://es.wikipedia.org/wiki/" title="es:">es:</a></p>
+<p><a rel="mw:WikiLink" href="./Ko:" title="Ko:">ko:</a></p>
!! end
!! test
-Parsoid: Bug #45209, handle interwiki links pointing to the current wiki as plain wiki links
-!! options
-parsoid
+Handle interwiki links pointing to the current wiki as plain wiki links (bug 45209)
!! wikitext
-[[en:Foo]]
-!! html
-<p><a rel="mw:WikiLink" href="./Foo" title="Foo" data-parsoid='{"stx":"simple","a":{"href":"./Foo"},"sa":{"href":"en:Foo"}}'>Foo</a></p>
+[[mi:Foo]]
+!! html/php
+<p><a href="/wiki/Foo" title="Foo">mi:Foo</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Foo" title="Foo" data-parsoid='{"stx":"simple","a":{"href":"./Foo"},"sa":{"href":"mi:Foo"}}'>mi:Foo</a></p>
!! end
!! test
Interlanguage link with preceding local interwiki link (bug 68085)
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
Blah blah blah
[[local:es:Spanish]]
-!! html
+!! html/php
<p>Blah blah blah
<a href="http://es.wikipedia.org/wiki/Spanish" class="extiw" title="es:Spanish">local:es:Spanish</a>
</p>
+!! html/parsoid
+<p>Blah blah blah
+<a rel="mw:ExtLink" href="http://es.wikipedia.org/wiki/Spanish" title="es:Spanish">local:es:Spanish</a></p>
!! end
!! test
Looks like an interlanguage link, but is actually a local interwiki
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
Blah blah blah
[[mi:Template:Foo]]
-!! html
+!! html/php
<p>Blah blah blah
<a href="/wiki/Template:Foo" title="Template:Foo">mi:Template:Foo</a>
</p>
+!! html/parsoid
+<p>Blah blah blah
+<a rel="mw:WikiLink" href="Template:Foo" title="Template:Foo">mi:Template:Foo</a></p>
!! end
###
### Redirects, Parsoid-only
###
+
!! test
1. Simple redirect to page
!! options
@@ -6972,17 +7710,20 @@ parsoid
<link rel="mw:PageProp/redirect" href="./Main_Page">
!! end
-# Only wt2html and html2html since "Main_Page" will serialize to "Main Page"
!! test
2. Other redirect variants
-!! options
-parsoid=wt2html,wt2wt
!! wikitext
#REDIRECT [[Main_Page]]
+!! html/parsoid
+<link rel="mw:PageProp/redirect" href="./Main_Page" data-parsoid='{"src":"#REDIRECT ","a":{"href":"./Main_Page"},"sa":{"href":"Main_Page"}}'/>
+!! end
+
+!! test
+3. Other redirect variants
+!! wikitext
#REDIRECT [[<nowiki>[[Bar]]</nowiki>]]
-!! html
-<link rel="mw:PageProp/redirect" href="./Main_Page">
-<link rel="mw:PageProp/redirect" href="./%5B%5BBar%5D%5D">
+!! html/parsoid
+<link rel="mw:PageProp/redirect" href="./%5B%5BBar%5D%5D" data-parsoid='{"src":"#REDIRECT ","a":{"href":"./%5B%5BBar%5D%5D"},"sa":{"href":"&lt;nowiki>[[Bar]]&lt;/nowiki>"}}'/>
!! end
!! test
@@ -7039,7 +7780,7 @@ parsoid=wt2html
!! test
Redirect to category
!! options
-parsoid=wt2html
+parsoid=wt2wt,wt2html
!! wikitext
#REDIRECT [[Category:Foo]]
!! html
@@ -7059,11 +7800,11 @@ parsoid=wt2html
!! test
Redirect to category page
!! options
-parsoid=wt2html,html2html
+parsoid
!! wikitext
#REDIRECT [[:Category:Foo]]
!! html
-<p><a rel="mw:WikiLink" href="Category:Foo" title="Category:Foo">Category:Foo</a></p>
+<link rel="mw:PageProp/redirect" href="Category:Foo" title="Category:Foo"/>
!! end
!! test
@@ -7093,7 +7834,7 @@ parsoid
!! wikitext
#REDIRECT [[en:File:Wiki.png]]
!! html
-<link rel="mw:PageProp/redirect" href="File:Wiki.png">
+<link rel="mw:PageProp/redirect" href="./File:Wiki.png">
!! end
!! test
@@ -7103,7 +7844,7 @@ parsoid
!! wikitext
#REDIRECT [[meatball:File:Wiki.png]]
!! html
-<link rel="mw:PageProp/redirect" href="File:Wiki.png">
+<link rel="mw:PageProp/redirect" href="./File:Wiki.png">
!! end
!! test
@@ -7118,14 +7859,26 @@ language=is
!! end
!! test
+Redirect syntax under text isn't considered a redirect
+!! wikitext
+some text
+#redirect [[Main Page]]
+!! html/parsoid
+<p>some text</p>
+<ol data-parsoid='{}'><li data-parsoid='{}'>redirect <a rel="mw:WikiLink" href="./Main_Page" title="Main Page" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page"},"sa":{"href":"Main Page"}}'>Main Page</a></li></ol>
+!! end
+
+# FIXME: Should hoist the redirect to the top of the page and ensure there
+# is only one.
+!! test
New redirect
!! options
parsoid=html2wt
+!! html
+<p>Foo<link rel="mw:PageProp/redirect" href="./Foo"></p>
!! wikitext
Foo
#REDIRECT [[Foo]]
-!! html
-<p>Foo<link rel="mw:PageProp/redirect" href="./Foo"></p>
!! end
##
@@ -7151,9 +7904,6 @@ Broken br tag sanitization
!! end
# TODO: Fix html2html mode (bug 51055)!
-# This </br> handling was added as part of bug 50831; but it
-# differs from how PHP+tidy handles this. We should investigate
-# this.
!! test
Parsoid: Broken br tag recognition
!! options
@@ -7162,12 +7912,9 @@ parsoid=wt2html
</br>
<br/ >
-!! html/php+tidy
-<p>&lt;/br&gt;</p>
+!! html+tidy
+<p><br /></p>
<p><br /></p>
-!! html/parsoid
-<p><br></p>
-<p><br/></p>
!! end
!! test
@@ -7192,6 +7939,8 @@ Failing to transform badly formed HTML into correct XHTML
</p>
!!end
+## FIXME: Is Parsoid's acceptance of self-closing html-tags
+## a feature or a bug? See https://phabricator.wikimedia.org/T76962
!! test
Handling html with a div self-closing tag
!! wikitext
@@ -7201,7 +7950,7 @@ Handling html with a div self-closing tag
<div title=bar />
<div title=bar/>
<div title=bar/ >
-!! html
+!! html/php
<p>&lt;div title /&gt;
&lt;div title/&gt;
</p>
@@ -7212,6 +7961,13 @@ Handling html with a div self-closing tag
<div title="bar/"></div>
</div>
+!! html/parsoid
+<div title="" data-parsoid='{"stx":"html","selfClose":true}'></div>
+<div title="" data-parsoid='{"stx":"html","selfClose":true}'></div>
+<div title="" data-parsoid='{"stx":"html","selfClose":true,"brokenHTMLTag":true}'></div>
+<div title="bar" data-parsoid='{"stx":"html","selfClose":true}'></div>
+<div title="bar" data-parsoid='{"stx":"html","selfClose":true}'></div>
+<div title="bar/" data-parsoid='{"stx":"html","autoInsertedEnd":true}'></div>
!! end
!! test
@@ -7234,7 +7990,7 @@ Handling html with a br self-closing tag
!! html/parsoid
<p><br title="" />
<br title="" />
-<br />
+<br title="" />
<br title="bar" />
<br title="bar" />
<br title="bar/" />
@@ -7248,11 +8004,12 @@ Horizontal ruler (should it add that extra space?)
<hr >
foo <hr
> bar
-!! html
+!! html+tidy
<hr />
<hr />
-foo <hr /> bar
-
+<p>foo</p>
+<hr />
+<p>bar</p>
!! end
!! test
@@ -7462,6 +8219,16 @@ Nested lists 8 (multiple nesting transitions)
!! end
!! test
+Nested lists 9 (extension interaction)
+!! options
+parsoid
+!! wikitext
+*<references />
+!! html/parsoid
+<ul><li data-parsoid='{}'><ol class="references" typeof="mw:Extension/references" about="#mwt2" data-parsoid='{}' data-mw='{"name":"references","attrs":{}}'></ol></li></ul>
+!! end
+
+!! test
1. Lists with start-of-line-transparent tokens before bullets: Comments
!! wikitext
*foo
@@ -7718,6 +8485,8 @@ Unbalanced closing non-block tags don't break a list
!! test
Unclosed formatting tags that straddle lists are closed and reopened
(php parser relies on Tidy to fix up)
+!! options
+parsoid=wt2html,wt2wt,html2html
!! wikitext
# <s> a
# b </s>
@@ -7727,19 +8496,13 @@ Unclosed formatting tags that straddle lists are closed and reopened
<li><s>b</s></li>
</ol>
!! html/parsoid
-<ol>
-<li> <s> a </s>
-</li>
-<li> <s> b </s>
-</li>
-</ol>
+<ol><li> <s> a</s></li>
+<li><s> b </s></li></ol>
!! end
-# Parsoid fails this test, but it might be tricky to support properly.
# See bug 68395.
!!test
-List embedded in a non-block tag
-(Ugly Parsoid output -- worth fixing; PHP parser relies on Tidy)
+1. List embedded in a formatting tag
!! wikitext
<small>
* foo
@@ -7756,6 +8519,49 @@ List embedded in a non-block tag
</small>
!!end
+## Ugly Parsoid output here
+## Not sure what the right output is.
+!!test
+2. List embedded in a formatting tag
+!! wikitext
+<small>
+*a
+*b</small>
+!! html/php+tidy
+<ul>
+<li><small>a</small></li>
+<li><small>b</small></li>
+</ul>
+!! html/parsoid
+<small></small>
+<ul><small>
+<li>a</li>
+</small>
+<li><small>b</small></li>
+</ul>
+!!end
+
+# Ugly Parsoid and PHP parser output here
+# Not sure if we want to make this a test!
+#
+## !!test
+## 3. Unclosed formatting tags in list elements
+## !! wikitext
+## *<small>a
+## *<small>b
+## !! html/php+tidy
+## <ul>
+## <li><small>a</small></li>
+## <li><small><small>b</small></small></li>
+## </ul>
+## !! html/parsoid
+## <ul>
+## <li><small>a</small></li>
+## <small>
+## <li><small>b</small></li>
+## </small></ul>
+## !!end
+
# This is a bug in the PHP parser + tidy combination.
# (The </tr> tag gets parsed as text and html-escaped by PHP,
# and then fostered out of the table by tidy.)
@@ -7769,14 +8575,7 @@ parsoid=wt2html,wt2wt
<td>foo</td>
</tr>
</table>
-!! html/php+tidy
-<p>&lt;/tr&gt;</p>
-<table>
-<tr>
-<td>foo</td>
-</tr>
-</table>
-!! html/parsoid
+!! html+tidy
<table>
<tr>
<td>foo</td>
@@ -8360,6 +9159,23 @@ Aoeu
</p>
!! end
+# From plwiki:PLOS_ONE
+!! test
+Parsoid: Page property magic word with magic word contents
+!! wikitext
+{{DISPLAYTITLE:''{{PAGENAME}}''}}
+!! html/parsoid
+<meta property="mw:PageProp/displaytitle" content="Main Page" about="#mwt2" typeof="mw:ExpandedAttrs" data-mw='{"attribs":[[{"txt":"content"},{"html":"&lt;i data-parsoid=\"{&amp;quot;dsr&amp;quot;:[15,31,2,2]}\">&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[]],&amp;quot;dsr&amp;quot;:[17,29,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;PAGENAME&amp;quot;,&amp;quot;function&amp;quot;:&amp;quot;pagename&amp;quot;},&amp;quot;params&amp;quot;:{},&amp;quot;i&amp;quot;:0}}]}\">Main Page&lt;/span>&lt;/i>"}]]}'/>
+!! end
+
+!! test
+Parsoid: Template-generated DISPLAYTITLE
+!! wikitext
+{{{{echo|DISPLAYTITLE}}:Foo}}
+!! html/parsoid
+<meta property="mw:PageProp/displaytitle" content="Foo" about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"dsr":[0,29,null,null],"pi":[[]]}' data-mw='{"parts":[{"template":{"target":{"wt":"{{echo|DISPLAYTITLE}}:Foo"},"params":{},"i":0}}]}'/>
+!! end
+
!! test
Namespace 1 {{ns:1}}
!! wikitext
@@ -8490,10 +9306,10 @@ hi+world%3F%21
Magic Word: prioritize type info over data-parsoid
!! options
parsoid=html2wt
+!! html
+<meta property="mw:PageProp/forcetoc" data-parsoid='{"magicSrc":"__NOTOC__"}'/>
!! wikitext
__FORCETOC__
-!! html
-<meta property="mw:PageProp/forcetoc" data-parsoid='{"src":"__NOTOC__","magicSrc":"__NOTOC__"}'/>
!! end
!! test
@@ -8516,7 +9332,7 @@ language=de
!! wikitext
__NOEDITSECTION__
!! html
-<meta property="mw:PageProp/noeditsection" data-parsoid='{"src":"__NOEDITSECTION__","magicSrc":"__NOEDITSECTION__"}'/>
+<meta property="mw:PageProp/noeditsection" data-parsoid='{"magicSrc":"__NOEDITSECTION__"}'/>
!! end
###
@@ -8541,6 +9357,28 @@ RFC 822
!! end
!! test
+Magic links: RFC (bug 65278)
+!! wikitext
+This is RFC 822 but thisRFC 822 is not RFC 822linked.
+!! html
+<p>This is <a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc822">RFC 822</a> but thisRFC 822 is not RFC 822linked.
+</p>
+!! end
+
+!! test
+Magic links: RFC (w/ non-newline whitespace, bug 28950/29025)
+!! wikitext
+RFC &nbsp;&#160;&#0160;&#xA0;&#Xa0; 822
+RFC
+822
+!! html
+<p><a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc822">RFC 822</a>
+RFC
+822
+</p>
+!! end
+
+!! test
Magic links: ISBN (bug 1937)
!! wikitext
ISBN 0-306-40615-2
@@ -8550,6 +9388,34 @@ ISBN 0-306-40615-2
!! end
!! test
+Magic links: ISBN (bug 65278)
+!! wikitext
+This is ISBN 978-0-316-09811-3 but thisISBN 978-0-316-09811-3 is not ISBN 978-0-316-09811-3linked.
+!! html/php
+<p>This is <a href="/wiki/Special:BookSources/9780316098113" class="internal mw-magiclink-isbn">ISBN 978-0-316-09811-3</a> but thisISBN 978-0-316-09811-3 is not ISBN 978-0-316-09811-3linked.
+</p>
+!! html/parsoid
+<p>This is <a href="./Special:BookSources/9780316098113" rel="mw:ExtLink">ISBN 978-0-316-09811-3</a> but thisISBN 978-0-316-09811-3 is not ISBN 978-0-316-09811-3linked.</p>
+!! end
+
+!! test
+Magic links: ISBN (w/ non-newline whitespace, bug 28950/29025)
+!! wikitext
+ISBN &nbsp;&#160;&#0160;&#xA0;&#Xa0; 978&nbsp;0&#160;316&#0160;09811&#xA0;3
+ISBN
+9780316098113
+ISBN 978
+0316098113
+!! html
+<p><a href="/wiki/Special:BookSources/9780316098113" class="internal mw-magiclink-isbn">ISBN 978 0 316 09811 3</a>
+ISBN
+9780316098113
+ISBN 978
+0316098113
+</p>
+!! end
+
+!! test
Magic links: PMID incorrectly converts space to underscore
!! wikitext
PMID 1234
@@ -8558,6 +9424,28 @@ PMID 1234
</p>
!! end
+!! test
+Magic links: PMID (bug 65278)
+!! wikitext
+This is PMID 1234 but thisPMID 1234 is not PMID 1234linked.
+!! html
+<p>This is <a class="external mw-magiclink-pmid" rel="nofollow" href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract">PMID 1234</a> but thisPMID 1234 is not PMID 1234linked.
+</p>
+!! end
+
+!! test
+Magic links: PMID (w/ non-newline whitespace, bug 28950/29025)
+!! wikitext
+PMID &nbsp;&#160;&#0160;&#xA0;&#Xa0; 1234
+PMID
+1234
+!! html
+<p><a class="external mw-magiclink-pmid" rel="nofollow" href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract">PMID 1234</a>
+PMID
+1234
+</p>
+!! end
+
###
### Templates
####
@@ -8783,8 +9671,7 @@ Template with complex template as argument
!! test
Template with thumb image (with link in description)
!! wikitext
-{{paramtest|
- param =[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]}}
+{{paramtest|param =[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]}}
!! html/php
This is a test template with parameter <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Noimage.png" class="new" title="File:Noimage.png">File:Noimage.png</a> <div class="thumbcaption"><a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">link</a> <a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">caption</a></div></div></div>
@@ -8795,6 +9682,8 @@ This is a test template with parameter <div class="thumb tright"><div class="thu
<div class="thumbcaption"><a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">link</a> <a href="/index.php?title=No_link&amp;action=edit&amp;redlink=1" class="new" title="No link (page does not exist)">caption</a></div>
</div>
</div>
+!! html/parsoid
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"paramtest","href":"./Template:Paramtest"},"params":{"param":{"wt":"[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]"}},"i":0}}]}'>This is a test template with parameter </p><figure class="mw-default-size" typeof="mw:Error mw:Image/Thumb" about="#mwt1" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:Noimage.png" ><img resource="./File:Noimage.png" src="./Special:FilePath/Noimage.png" height="220" width="220"/></a><figcaption><a rel="mw:WikiLink" href="./No_link" title="No link">link</a> <a rel="mw:WikiLink" href="./No_link" title="No link">caption</a></figcaption></figure>
!! end
!! article
@@ -8853,15 +9742,6 @@ Template parameter as link source
</p>
!! end
-!!test
-Template-generated attribute string (k='v')
-!! wikitext
-<span {{attr_str|id|v1}}>bar</span>
-!! html
-<p><span id="v1">bar</span>
-</p>
-!!end
-
!!article
Template:paramtest2
!! text
@@ -9237,19 +10117,15 @@ some
<h3><span class="mw-headline" id="here">here</span></h3>
!! html/parsoid
-<!-- comment --><meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"&lt;noinclude>"}'/><!-- comment --><meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"&lt;/noinclude>"}'/><!-- comment -->
-<h2 data-parsoid='{}'> hu </h2>
+<!-- comment --><meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"&lt;noinclude>"}'/><!-- comment --><meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"&lt;/noinclude>"}'/><!-- comment --><h2> hu </h2>
<meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"&lt;noinclude>"}'/>
+<p>some</p>
+<meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"&lt;/noinclude>"}'/><ul><li> stuff</li>
+<li> here</li></ul>
-<p data-parsoid='{}'>some</p>
-<meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"&lt;/noinclude>"}'/>
-<ul data-parsoid='{}'>
-<li data-parsoid='{}'> stuff</li>
-
-<li data-parsoid='{}'> here</li></ul>
+<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"&lt;includeonly>can have stuff&lt;/includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><h3> here </h3>
-<h3 data-parsoid='{}'> here </h3>
!! end
# TODO: test with DOM fragment reuse!
@@ -9270,25 +10146,17 @@ c}}d
b}}
!! html
-a<span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"b
-<table></table>c"}},"i":0}}]}'>b</span>
-<table about="#mwt1"></table><span about="#mwt1">c</span>d
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":["a",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"b&lt;table>&lt;/table>c"}},"i":0}},"d"]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>ab</p><table about="#mwt1" data-parsoid='{"stx":"html"}'></table><p about="#mwt1">cd</p>
+<p about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":["a",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"b\n&lt;table>&lt;/table>\nc"}},"i":0}},"d"]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>ab</p><span about="#mwt2">
+</span><table about="#mwt2" data-parsoid='{"stx":"html"}'></table><span about="#mwt2">
+</span><p about="#mwt2">cd</p>
-<p about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":["a",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"b\n<table></table>\nc"}},"i":0}},"d"]}'>ab</p><span about="#mwt2">
-</span>
-<table about="#mwt2"></table><span about="#mwt2">
-</span>
-<p about="#mwt2">cd</p>
-
+<p about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n\n&lt;table>&lt;/table>\n\nb"}},"i":0}}]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>a</p><span about="#mwt3">
-<p about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n\n<table></table>\n\nb"}},"i":0}}]}'>a</p><span about="#mwt3">
-
-</span>
-<table about="#mwt3"></table><span about="#mwt3">
+</span><table about="#mwt3" data-parsoid='{"stx":"html"}'></table><span about="#mwt3">
-</span>
-<p about="#mwt3">b</p>
+</span><p about="#mwt3">b</p>
!! end
!! test
@@ -9405,11 +10273,9 @@ parsoid=wt2html,wt2wt
|foo
|}
!!html/parsoid
-<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":""}},"i":0}}]}'></span>
-<table width="100%">
-<tbody>
-<tr>
-<td>foo</td></tr></tbody></table>
+<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":""}},"i":0}}]}'></span><table width="100%">
+<tbody><tr><td>foo</td></tr>
+</tbody></table>
!!end
!!test
@@ -9421,7 +10287,7 @@ parsoid=wt2html,wt2wt
|c
|}
!!html/parsoid
-<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"&lt;includeonly>a&lt;/includeonly>"'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><table about="#mwt2" typeof="mw:ExpandedAttrs" data-mw='{"attribs":[[{"txt":"{{{b}}}","html":"&lt;span about=\"#mwt1\" typeof=\"mw:Param\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[31,38,null,null],&amp;quot;src&amp;quot;:&amp;quot;{{{b}}}&amp;quot;}\">{{{b}}}&lt;/span>"},{"html":""}]]}' data-parsoid='{"a":{"{{{b}}}":null},"sa":{"{{{b}}}":""}}'>
+<meta typeof="mw:Includes/IncludeOnly"/><meta typeof="mw:Includes/IncludeOnly/End"/><table about="#mwt2" typeof="mw:ExpandedAttrs" data-mw='{"attribs":[[{"txt":"{{{b}}}","html":"&lt;span about=\"#mwt1\" typeof=\"mw:Param\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[31,38,null,null],&amp;quot;src&amp;quot;:&amp;quot;{{{b}}}&amp;quot;}\">{{{b}}}&lt;/span>"},{"html":""}]]}' data-parsoid='{"a":{"{{{b}}}":null},"sa":{"{{{b}}}":""}}'>
<tbody><tr><td>c</td></tr>
</tbody></table>
@@ -9592,7 +10458,7 @@ Templates: Correctly encapsulate templates producing </p> tag without a correspo
b</p>}}
!! html/parsoid
<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\nb&lt;/p>"}},"i":0}}]}'>a
-b</p><p></p>
+b</p>
!!end
!!test
@@ -9718,6 +10584,9 @@ Templates: HTML Tag: 6. Generation of end piece of HTML attr value
!!end
+# SSS FIXME: While it is great we added support for all this,
+# do we want to make this part of the spec? Maybe we want to
+# deprecate this kind of usage in the future?
!!test
Templates: HTML Tag: 7. Generation of partial attribute key string
!! wikitext
@@ -9727,6 +10596,79 @@ Templates: HTML Tag: 7. Generation of partial attribute key string
!!end
+!! test
+Templates: HTML Tag: 8. Template-generated attribute (k=v)
+!! wikitext
+<div {{echo|1=id="v1"}}>bar</div>
+!! html
+<div id="v1">bar</div>
+
+!!end
+
+!! test
+Templates: HTML Tag: 9. Multiple template-generated attributes
+!! wikitext
+<div {{echo|1=id="v1" title="foo"}}>bar</div>
+!! html
+<div id="v1" title="foo">bar</div>
+
+!!end
+
+!! test
+Templates: Support for templates generating attributes and content
+!! wikitext
+{| {{mixed_attr_content_template}}
+|-
+|bar
+|}
+!! html/php
+<table style="color:red;" title="T48811">
+
+<tr>
+<td>foo
+</td></tr>
+<tr>
+<td>bar
+</td></tr></table>
+
+!! html/parsoid
+<table style="color:red;" title="T48811" about="#mwt1" typeof="mw:Transclusion mw:ExpandedAttrs" data-mw='{"parts":["{| ",{"template":{"target":{"wt":"mixed_attr_content_template","href":"./Template:Mixed_attr_content_template"},"params":{},"i":0}},"\n|-\n|bar\n|}"]}'>
+<tbody><tr>
+<td>foo</td></tr>
+<tr>
+<td>bar</td></tr>
+</tbody></table>
+!!end
+
+!! test
+1. Entities and nowikis inside templated attributes should be handled correctly
+!! wikitext
+<div {{echo|style{{=}}"background:&#35;f9f9f9;"}}>foo</div>
+!! html/php
+<div style="background:#f9f9f9;">foo</div>
+
+!! html/parsoid
+<div style="background:#f9f9f9;" about="#mwt3" typeof="mw:ExpandedAttrs" data-parsoid='{"stx":"html"}' data-mw='{"attribs":[[{"txt":"style","html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[5,49,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;style{{=}}\\&amp;quot;background:&amp;amp;#35;f9f9f9;\\&amp;quot;&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">style&lt;/span>&lt;span typeof=\"mw:Nowiki\" about=\"#mwt1\" data-parsoid=\"{}\">=&lt;/span>&lt;span about=\"#mwt1\" data-parsoid=\"{}\">\"background:&lt;/span>&lt;span typeof=\"mw:Entity\" about=\"#mwt1\" data-parsoid=\"{&amp;quot;src&amp;quot;:&amp;quot;&amp;amp;#35;&amp;quot;,&amp;quot;srcContent&amp;quot;:&amp;quot;#&amp;quot;}\">#&lt;/span>&lt;span about=\"#mwt1\" data-parsoid=\"{}\">f9f9f9;\"&lt;/span>"},{"html":""}]]}'>foo</div>
+!! end
+
+!! test
+2. Entities and nowikis inside templated attributes should be handled correctly
+!! wikitext
+{|
+|{{table_attribs_3}}
+|}
+!! html/php
+<table>
+<tr>
+<td style="background:#f9f9f9;">Foo
+</td></tr></table>
+
+!! html/parsoid
+<table>
+<tbody><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td style="background:#f9f9f9;" typeof="mw:Transclusion" about="#mwt1" data-parsoid='{"autoInsertedEnd":true,"pi":[[]]}' data-mw='{"parts":["|",{"template":{"target":{"wt":"table_attribs_3","href":"./Template:Table_attribs_3"},"params":{},"i":0}}]}'>Foo</td></tr>
+</tbody></table>
+!! end
+
!!test
Templates: HTML Tables: 1. Generating start of a HTML table
!! wikitext
@@ -10700,26 +11642,26 @@ parsoid=wt2html
Parsoid: Escape nowiki with trailing space in tags
!! options
parsoid=html2wt
+!! html
+<p>&lt;nowiki &gt; foo &lt/nowiki ></p>
+<p>a&lt;nowiki /&gt;b</p>
+<p>c&lt;nowiki/ &gt;d</p>
!! wikitext
&lt;nowiki &gt; foo &lt;/nowiki &gt;
a&lt;nowiki /&gt;b
c&lt;nowiki/ &gt;d
-!! html
-<p>&lt;nowiki &gt; foo &lt/nowiki ></p>
-<p>a&lt;nowiki /&gt;b</p>
-<p>c&lt;nowiki/ &gt;d</p>
!! end
!! test
Parsoid: Escape weird noWikI capitalizations
!! options
parsoid=html2wt
-!! wikitext
-&lt;noWikI &gt; foo &lt;/NoWikI &gt;
!! html
<p>&lt;noWikI &gt; foo &lt/NoWikI ></p>
+!! wikitext
+&lt;noWikI &gt; foo &lt;/NoWikI &gt;
!! end
###
@@ -10841,8 +11783,7 @@ parsoid=wt2html,wt2wt,html2html
<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span>
-</p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -10853,8 +11794,7 @@ Simple image (using File: namespace, now canonical)
<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span>
-</p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -10865,7 +11805,7 @@ Right-aligned image
<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
!! end
!! test
@@ -10876,7 +11816,7 @@ Image with caption
<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption text</figcaption></figure>
!! end
!! test
@@ -10887,7 +11827,7 @@ Image with caption, bug 53312 #1
<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption page stuff"><img alt="Caption page stuff" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption page stuff</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption page stuff</figcaption></figure>
!! end
!! test
@@ -10898,7 +11838,7 @@ Image with caption, bug 53312 #2
<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption page="><img alt="Caption page=" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption page=</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption page=</figcaption></figure>
!! end
!! test
@@ -10909,7 +11849,7 @@ Image with caption, bug 53312 #3
<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption page=stuff"><img alt="Caption page=stuff" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption page=stuff</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption page=stuff</figcaption></figure>
!! end
!! test
@@ -10925,13 +11865,22 @@ thumbsize=220
<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Caption <a href="/index.php?title=Link1&amp;action=edit&amp;redlink=1" class="new" title="Link1 (page does not exist)">Link1</a> [[]] <a href="/index.php?title=Link2&amp;action=edit&amp;redlink=1" class="new" title="Link2 (page does not exist)">Link2</a></div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption [[Link1]]\n[[]]\n[[Link2]]\n"}],"dsr":[0,59,2,2]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"dsr":[2,null,null,null]}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption data-parsoid='{"dsr":[null,57,null,null]}'>Caption <a rel="mw:WikiLink" href="./Link1" title="Link1" data-parsoid='{"stx":"simple","a":{"href":"./Link1"},"sa":{"href":"Link1"},"dsr":[32,41,2,2]}'>Link1</a>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption [[Link1]]\n[[]]\n[[Link2]]\n"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>Caption <a rel="mw:WikiLink" href="./Link1" title="Link1" data-parsoid='{"stx":"simple","a":{"href":"./Link1"},"sa":{"href":"Link1"}}'>Link1</a>
[[]]
-<a rel="mw:WikiLink" href="./Link2" title="Link2" data-parsoid='{"stx":"simple","a":{"href":"./Link2"},"sa":{"href":"Link2"},"dsr":[47,56,2,2]}'>Link2</a>
+<a rel="mw:WikiLink" href="./Link2" title="Link2" data-parsoid='{"stx":"simple","a":{"href":"./Link2"},"sa":{"href":"Link2"}}'>Link2</a>
</figcaption></figure>
!! end
!! test
+Titles in unlinked images (T23454)
+!! wikitext
+[[File:Foobar.jpg|link=|stuff]]
+!! html/php
+<p><img alt="stuff" src="http://example.com/images/3/3a/Foobar.jpg" title="stuff" width="1941" height="220" />
+</p>
+!! end
+
+!! test
Link with empty target
!! wikitext
[[]]
@@ -10941,6 +11890,17 @@ Link with empty target
!! end
!! test
+Image with link trail
+!! wikitext
+Linktrails should not work for images: [[File:Foobar.jpg]]s
+!! html/php
+<p>Linktrails should not work for images: <a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>s
+</p>
+!! html/parsoid
+<p>Linktrails should not work for images: <span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span>s</p>
+!! end
+
+!! test
Image with empty attribute
!! options
parsoid=wt2html,wt2wt,html2html
@@ -10950,7 +11910,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption text</figcaption></figure>
!! end
!! test
@@ -10961,7 +11921,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:139px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" width="137" height="16" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/206px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/274px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is a caption</div></div></div>
!! html/parsoid
-<figure typeof="mw:Image/Thumb mw:ExpandedAttrs" data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[24,38,null,null]}\">137px&lt;/span>"}]]}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
+<figure typeof="mw:Image/Thumb mw:ExpandedAttrs" about="#mwt2" data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[24,38,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">137px&lt;/span>"}]]}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
!! end
!! test
@@ -10972,7 +11932,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:139px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/137px-Foobar.jpg" width="137" height="16" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/206px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/274px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is a caption</div></div></div>
!! html/parsoid
-<figure typeof="mw:Image/Thumb mw:ExpandedAttrs" data-mw='{"attribs":[["thumbnail",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;thumb&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[18,32,null,null]}\">thumb&lt;/span>"}],["width",{"html":"&lt;span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[33,47,null,null]}\">137px&lt;/span>"}]]}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
+<figure typeof="mw:Image/Thumb mw:ExpandedAttrs" about="#mwt3" data-mw='{"attribs":[["thumbnail",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[18,32,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;thumb&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">thumb&lt;/span>"}],["width",{"html":"&lt;span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[33,47,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">137px&lt;/span>"}]]}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
!! end
!! test
@@ -10983,7 +11943,7 @@ parsoid=wt2html,wt2wt,html2html
<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" width="50" height="6" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/75px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/100px-Foobar.jpg 2x" /></a>
</p>
!! html/parsoid
-<p><span typeof="mw:Image mw:ExpandedAttrs" about="#mwt2" data-mw='{"attribs":[["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;50px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[18,31,null,null]}\">50px&lt;/span>"}]]}' data-parsoid='{"optList":[{"ck":"width","ak":"{{echo|50px}}"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+<p><span typeof="mw:Image mw:ExpandedAttrs" about="#mwt2" data-parsoid='{"optList":[{"ck":"width","ak":"{{echo|50px}}"}]}' data-mw='{"attribs":[["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]],&amp;quot;dsr&amp;quot;:[18,31,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;50px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">50px&lt;/span>"}]]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></span></p>
!! end
## Parsoid does not provide editing support for images where templates produce multiple image attributes.
@@ -10996,10 +11956,9 @@ Image with multiple attributes from the same template
<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption text"><img alt="Caption text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image mw:Placeholder"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image mw:Placeholder"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption text</figcaption></figure>
!! end
-# Parsoid's output here is broken (incorrect p-wrapping); see bug 64901.
!! test
Image with link tails
!! options
@@ -11028,9 +11987,9 @@ thumbsize=220
</div>
<p>456</p>
!! html/parsoid
-<p>123<span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span>456</p>
-123<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></figure>456
-123<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220"></a></figure>456
+<p>123<span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span>456</p>
+<p>123</p><figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure><p>456</p>
+<p>123</p><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a></figure><p>456</p>
!! end
!! test
@@ -11041,7 +12000,7 @@ Image with multiple captions -- only last one is accepted
<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption3 - accepted"><img alt="Caption3 - accepted" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption3 - accepted</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Caption3 - accepted</figcaption></figure>
!! end
!! test
@@ -11052,7 +12011,7 @@ Image with multiple widths -- use last
<p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" width="300" height="34" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/450px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/600px-Foobar.jpg 2x" /></a>
</p>
!! html/parsoid
-<p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="34" width="300"/></a></span></p>
+<p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="34" width="300"/></a></span></p>
!! end
!! test
@@ -11068,8 +12027,8 @@ thumbsize=220
<p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" style="vertical-align: middle" /></a>
</p>
!! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
-<p><span class="mw-default-size mw-valign-middle" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<p><span class="mw-default-size mw-valign-middle" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11084,9 +12043,9 @@ Image with width attribute at different positions
<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption"><img alt="Caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a></div>
!! html/parsoid
-<figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
-<figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
-<figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
+<figure class="mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>Caption</figcaption></figure>
+<figure class="mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>Caption</figcaption></figure>
+<figure class="mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>Caption</figcaption></figure>
!! end
# a sad bit of backward-compatibility
@@ -11102,7 +12061,7 @@ parsoid=wt2html,wt2wt,html2html
<a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/177px-Foobar.jpg" width="177" height="20" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/265px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/353px-Foobar.jpg 2x" /></a>
</p>
!! html/parsoid
-<p><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="2" width="20"/></a></span><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="20" width="177"/></a></span></p>
+<p><span typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="2" width="20"/></a></span> <span typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="20" width="177"/></a></span></p>
!! end
!! test
@@ -11113,7 +12072,7 @@ Image with link parameter, wiki target
<p><a href="/wiki/Main_Page" title="Main Page"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
# parsoid bug 49293 (part 1)
@@ -11125,7 +12084,7 @@ Image with link parameter, URL target
<p><a href="http://example.com/" rel="nofollow"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
# parsoid bug 49293 (part 2)
@@ -11137,7 +12096,7 @@ Image with link parameter, protocol-less URL target
<p><a href="//example.com/" rel="nofollow"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><a href="//example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="//example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11192,7 +12151,7 @@ Image with empty link parameter
<p><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" />
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image"><span><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></span></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><span><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></span></span></p>
!! end
!! test
@@ -11203,7 +12162,7 @@ Image with link parameter (wiki target) and unnamed parameter
<p><a href="/wiki/Main_Page" title="Title"><img alt="Title" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"Title"}'><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"Title"}'><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11214,7 +12173,7 @@ Image with link parameter (URL target) and unnamed parameter
<p><a href="http://example.com/" title="Title" rel="nofollow"><img alt="Title" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"Title"}'><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"Title"}'><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11228,7 +12187,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="http://example.com/"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>Title</figcaption></figure>
!! end
!! test
@@ -11241,7 +12200,7 @@ thumbsize=220
<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/File:Foobar.jpg"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
!! end
!! test
@@ -11255,7 +12214,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/Main_Page" title="Main Page"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
!! end
!! test
@@ -11269,7 +12228,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="http://example.com"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="http://example.com"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="http://example.com"><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
!! end
!! test
@@ -11283,7 +12242,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:137px;"><img alt="" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><span><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></span><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><span><img resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></span><figcaption>Title</figcaption></figure>
!! end
!! test
@@ -11297,7 +12256,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:137px;"><a href="/wiki/Main_Page" title="Main Page"><img alt="alttext" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" class="thumbimage" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Title</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="Main_Page"><img alt="alttext" resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'><a href="Main_Page"><img alt="alttext" resource="./File:Foobar.jpg" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></a><figcaption>Title</figcaption></figure>
!! end
!! test
@@ -11310,7 +12269,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tleft"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a> <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page" title="Main Page">Main Page</a></figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page" title="Main Page">Main Page</a></figcaption></figure>
!! end
!! test
@@ -11323,7 +12282,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tleft"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Altitude" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a> <div class="thumbcaption">This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img alt="Altitude" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page" title="Main Page">Main Page</a></figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img alt="Altitude" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>This is a test image <a rel="mw:WikiLink" href="Main_Page" title="Main Page">Main Page</a></figcaption></figure>
!! end
!! test
@@ -11339,8 +12298,19 @@ parsoid=wt2html,wt2wt,html2html
</p><p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="testing bold in alt" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw="{&quot;caption&quot;:&quot;testing '''bold''' in alt&quot;}"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
-<p><span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img alt="testing bold in alt" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw="{&quot;caption&quot;:&quot;testing '''bold''' in alt&quot;}"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img alt="testing bold in alt" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
+!! end
+
+!! test
+Alt image option should handle most kinds of wikitext without barfing
+!! wikitext
+[[Image:Foobar.jpg|thumb|This is the image caption|alt=This is a [[link]] and a {{echo|''bold template''}}.]]
+!! html/php
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="This is a link and a bold template." src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is the image caption</div></div></div>
+
+!! html/parsoid
+<figure class="mw-default-size" typeof="mw:Image/Thumb mw:ExpandedAttrs" about="#mwt2" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"This is the image caption"},{"ck":"alt","ak":"alt=This is a [[link]] and a {{echo|&#39;&#39;bold template&#39;&#39;}}."}]}' data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["alt",{"html":"alt=This is a &lt;a rel=\"mw:WikiLink\" href=\"./Link\" title=\"Link\" data-parsoid=\"{&amp;quot;stx&amp;quot;:&amp;quot;simple&amp;quot;,&amp;quot;a&amp;quot;:{&amp;quot;href&amp;quot;:&amp;quot;./Link&amp;quot;},&amp;quot;sa&amp;quot;:{&amp;quot;href&amp;quot;:&amp;quot;link&amp;quot;},&amp;quot;dsr&amp;quot;:[65,73,2,2]}\">link&lt;/a> and a &lt;i about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[80,106,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;&#39;&#39;bold template&#39;&#39;&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\">bold template&lt;/i>."}]]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img alt="This is a link and a bold template." resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"alt":"This is a link and a bold template.","resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"alt":"alt=This is a [[link]] and a {{echo|&#39;&#39;bold template&#39;&#39;}}.","resource":"Image:Foobar.jpg"}}'/></a><figcaption>This is the image caption</figcaption></figure>
!! end
###################
@@ -11364,9 +12334,9 @@ parsoid=wt2html,wt2wt,html2html
</p><p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a></span></p>
-<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a></span></p>
-<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a></span></p>
!! end
!! test
@@ -11383,7 +12353,9 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a> <div class="thumbcaption">caption</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
!! end
!! test
@@ -11400,7 +12372,9 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
!! end
###################
@@ -11427,8 +12401,8 @@ parsoid=wt2html,wt2wt,html2html
</p><p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="2000" height="227" class="thumbborder" /></a>
</p>
!! html/parsoid
-<p><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="227" width="2000"/></a></span></p>
-<p><span class="mw-image-border" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="227" width="2000"/></a></span></p>
+<p><span typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="227" width="2000"/></a></span></p>
+<p><span class="mw-image-border" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="227" width="2000"/></a></span></p>
!! end
!! test
@@ -11444,8 +12418,8 @@ parsoid=wt2html,wt2wt,html2html
</p><p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/1000px-Foobar.jpg" width="1000" height="113" class="thumbborder" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/1500px-Foobar.jpg 1.5x, http://example.com/images/3/3a/Foobar.jpg 2x" /></a>
</p>
!! html/parsoid
-<p><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="113" width="1000"/></a></span></p>
-<p><span class="mw-image-border" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="113" width="1000"/></a></span></p>
+<p><span typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="113" width="1000"/></a></span></p>
+<p><span class="mw-image-border" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="113" width="1000"/></a></span></p>
!! end
!! test
@@ -11458,7 +12432,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:52px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" width="50" height="6" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/75px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/100px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div></div></div></div>
!! html/parsoid
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="6" width="50"/></a></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></figure>
!! end
!! test
@@ -11474,8 +12448,8 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:2002px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="Foobar.svg" src="http://example.com/images/thumb/f/ff/Foobar.svg/2000px-Foobar.svg.png" width="2000" height="1500" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/3000px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/4000px-Foobar.svg.png 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div></div></div></div>
!! html/parsoid
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure>
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" height="1500" width="2000"/></a></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" data-file-width="240" data-file-height="180" data-file-type="drawing" height="1500" width="2000"/></a></figure>
!! end
!! test
@@ -11488,7 +12462,7 @@ parsoid=wt2html,wt2wt,html2html
<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" width="50" height="6" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/75px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/100px-Foobar.jpg 2x" /></a>
</p>
!! html/parsoid
-<p><span typeof="mw:Image/Frameless"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="6" width="50"/></a></span></p>
+<p><span typeof="mw:Image/Frameless"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></span></p>
!! end
!! test
@@ -11504,8 +12478,8 @@ parsoid=wt2html,wt2wt,html2html
</p><p><a href="/wiki/File:Foobar.svg" class="image"><img alt="Foobar.svg" src="http://example.com/images/thumb/f/ff/Foobar.svg/2000px-Foobar.svg.png" width="2000" height="1500" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/3000px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/4000px-Foobar.svg.png 2x" /></a>
</p>
!! html/parsoid
-<p><span typeof="mw:Image/Frameless"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
-<p><span typeof="mw:Image/Frameless"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" height="1500" width="2000"/></a></span></p>
+<p><span typeof="mw:Image/Frameless"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
+<p><span typeof="mw:Image/Frameless"><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" data-file-width="240" data-file-height="180" data-file-type="drawing" height="1500" width="2000"/></a></span></p>
!! end
!! test
@@ -11527,7 +12501,10 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:1943px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="thumbimage" /></a> <div class="thumbcaption"></div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure><figure typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure><figure typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure><figure typeof="mw:Image/Frame"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></figure>
+<figure class="mw-default-size" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
+<figure typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
+<figure typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
+<figure typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure>
!! end
###################
@@ -11560,7 +12537,7 @@ Frameless image caption with a free URL
<p><a href="/wiki/File:Foobar.jpg" class="image" title="http://example.com"><img alt="http://example.com" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"http://example.com"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"http://example.com"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11573,7 +12550,7 @@ thumbsize=220
<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
!! end
!! test
@@ -11587,7 +12564,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Alteration" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img alt="Alteration" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img alt="Alteration" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption><a rel="mw:ExtLink" href="http://example.com">http://example.com</a></figcaption></figure>
!! end
!! test
@@ -11599,7 +12576,7 @@ SVG thumbnails with no language set
<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" height="165" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" data-file-width="240" data-file-height="180" data-file-type="drawing" height="165" width="220"/></a><figcaption>caption</figcaption></figure>
!! end
!! test
@@ -11612,7 +12589,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=File:Foobar.svg&amp;lang=de" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/langde-180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/langde-270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/langde-360px-Foobar.svg.png 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" lang="de" height="165" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" lang="de" data-file-width="240" data-file-height="180" data-file-type="drawing" height="165" width="220"/></a><figcaption>caption</figcaption></figure>
!! end
!! test
@@ -11625,7 +12602,7 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.svg" class="image"><img alt="" src="http://example.com/images/thumb/f/ff/Foobar.svg/180px-Foobar.svg.png" width="180" height="135" class="thumbimage" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/270px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.svg" class="internal" title="Enlarge"></a></div>lang=invalid.language.code</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" height="165" width="220"/></a><figcaption>lang=invalid.language.code</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" data-file-width="240" data-file-height="180" data-file-type="drawing" height="165" width="220"/></a><figcaption>lang=invalid.language.code</figcaption></figure>
!! end
!! test
@@ -11636,7 +12613,7 @@ BUG 1887: A ISBN with a thumbnail
<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div><a href="/wiki/Special:BookSources/1235467890" class="internal mw-magiclink-isbn">ISBN 1235467890</a></div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption><a href="Special:BookSources/1235467890" rel="mw:ExtLink">ISBN 1235467890</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption><a href="Special:BookSources/1235467890" rel="mw:ExtLink">ISBN 1235467890</a></figcaption></figure>
!! end
!! test
@@ -11647,7 +12624,7 @@ BUG 1887: A RFC with a thumbnail
<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is <a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>This is <a href="//tools.ietf.org/html/rfc12354" rel="mw:ExtLink">RFC 12354</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>This is <a href="//tools.ietf.org/html/rfc12354" rel="mw:ExtLink">RFC 12354</a></figcaption></figure>
!! end
!! test
@@ -11658,7 +12635,7 @@ BUG 1887: A mailto link with a thumbnail
<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>Please <a rel="nofollow" class="external free" href="mailto:nobody@example.com">mailto:nobody@example.com</a></div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>Please <a rel="mw:ExtLink" href="mailto:nobody@example.com">mailto:nobody@example.com</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>Please <a rel="mw:ExtLink" href="mailto:nobody@example.com">mailto:nobody@example.com</a></figcaption></figure>
!! end
# Pending resolution to bug 368
@@ -11670,7 +12647,7 @@ BUG 648: Frameless image caption with a link
<p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a link in it"><img alt="text with a link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[link]] in it"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[link]] in it"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11681,7 +12658,7 @@ BUG 648: Frameless image caption with a link (suffix)
<p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a linkfoo in it"><img alt="text with a linkfoo in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[link]]foo in it"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[link]]foo in it"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11692,7 +12669,7 @@ BUG 648: Frameless image caption with an interwiki link
<p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a MeatBall:Link in it"><img alt="text with a MeatBall:Link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[MeatBall:Link]] in it"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[MeatBall:Link]] in it"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11703,7 +12680,7 @@ BUG 648: Frameless image caption with a piped interwiki link
<p><a href="/wiki/File:Foobar.jpg" class="image" title="text with a link in it"><img alt="text with a link in it" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[MeatBall:Link|link]] in it"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"text with a [[MeatBall:Link|link]] in it"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11714,7 +12691,7 @@ Escape HTML special chars in image alt text
<p><a href="/wiki/File:Foobar.jpg" class="image" title="&amp; &lt; &gt; &quot;"><img alt="&amp; &lt; &gt; &quot;" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&amp; &lt; > \""}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&amp; &lt; > \""}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11725,7 +12702,7 @@ BUG 499: Alt text should have &#1234;, not &amp;1234;
<p><a href="/wiki/File:Foobar.jpg" class="image" title="♀"><img alt="♀" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&amp;#9792;"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&amp;#9792;"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11749,7 +12726,7 @@ Image caption containing another image
<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is a caption with another <a href="/wiki/File:Thumb.png" class="image" title="image"><img alt="image" src="http://example.com/images/e/ea/Thumb.png" width="135" height="135" /></a> inside it!</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>This is a caption with another <span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"image"}'><a href="File:Thumb.png"><img resource="./File:Thumb.png" src="//example.com/images/e/ea/Thumb.png" height="135" width="135"/></a></span> inside it!</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>This is a caption with another <span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"image"}'><a href="./File:Thumb.png"><img resource="./File:Thumb.png" src="//example.com/images/e/ea/Thumb.png" data-file-width="135" data-file-height="135" data-file-type="bitmap" height="135" width="135"/></a></span> inside it!</figcaption></figure>
!! end
!! test
@@ -11761,7 +12738,7 @@ Image: caption containing a newline
<p><a href="/wiki/File:Foobar.jpg" class="image" title="This *is some text"><img alt="This *is some text" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"This\n*is some text"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"This\n*is some text"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!!end
!!test
@@ -11773,7 +12750,7 @@ Image: caption containing leading space
<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>bar</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption> bar</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption> bar</figcaption></figure>
!!end
!! test
@@ -11792,7 +12769,7 @@ and some more text.]]
<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is an example image thumbnail caption with a table <table> <tr> <th> Foo </th> <th> Bar </th></tr> <tr> <td> Foo1 </td> <td> Bar1 </td></tr></table> and some more text.</div></div></div>
!! html/parsoid
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"/></a><figcaption>This is an example image thumbnail caption with a table
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>This is an example image thumbnail caption with a table
<table>
<tbody>
<tr><th>Foo </th><th>Bar</th></tr>
@@ -11809,7 +12786,7 @@ Bug 3090: External links other than http: in image captions
<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This caption has <a rel="nofollow" class="external text" href="irc://example.net">irc</a> and <a rel="nofollow" class="external text" href="https://example.com">Secure</a> ext links in it.</div></div></div>
!! html/parsoid
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"/></a><figcaption>This caption has <a rel="mw:ExtLink" href="irc://example.net">irc</a> and <a rel="mw:ExtLink" href="https://example.com">Secure</a> ext links in it.</figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>This caption has <a rel="mw:ExtLink" href="irc://example.net">irc</a> and <a rel="mw:ExtLink" href="https://example.com">Secure</a> ext links in it.</figcaption></figure>
!! end
!! test
@@ -11822,7 +12799,7 @@ parsoid=wt2html,wt2wt,html2html
<p><a href="/wiki/File:Foobar.jpg" class="image" title="a"><img alt="a" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" class="b" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size b" typeof="mw:Image" data-mw='{"caption":"a"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+<p><span class="mw-default-size b" typeof="mw:Image" data-mw='{"caption":"a"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -11836,7 +12813,7 @@ language=es
<div class="floatleft"><a href="/wiki/Foo" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image"><a href="./Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image"><a href="./Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
!! end
!! test
@@ -11851,7 +12828,7 @@ language=es
<div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/Foo" title="Foo"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/Archivo:Foobar.jpg" class="internal" title="Aumentar"></a></div>caption</div></div></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./Foo"><img resource="./Archivo:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
!! end
!! test
@@ -11865,7 +12842,7 @@ parsoid=wt2html,wt2wt,html2html
<p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="extra thumbborder" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a>
</p>
!! html/parsoid
-<p><span class="mw-default-size mw-image-border extra" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a></span></p>
+<p><span class="mw-default-size mw-image-border extra" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a></span></p>
!! end
# Note that 'right' is the default alignment, despite the misspelled 'righ' below
@@ -11886,7 +12863,9 @@ parsoid=wt2html,wt2wt,html2html
<div class="thumb tleft"><div class="thumbinner" style="width:222px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" width="220" height="25" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/330px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/440px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>caption</div></div></div>
!! html/parsoid
-<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
!! end
!! article
@@ -11895,11 +12874,13 @@ File:Barfoo.jpg
#REDIRECT [[File:Barfoo.jpg]]
!! endarticle
+# FIXME: Parsoid should run this test -- but we'd need to teach the
+# mockAPI about the redirected Barfoo.jpg image.
!! test
Redirected image
!! wikitext
[[Image:Barfoo.jpg]]
-!! html
+!! html/php
<p><a href="/wiki/File:Barfoo.jpg" title="File:Barfoo.jpg">File:Barfoo.jpg</a>
</p>
!! end
@@ -11909,10 +12890,12 @@ Missing image with uploads disabled
!! options
wgEnableUploads=0
!! wikitext
-[[Image:Foobaz.jpg]]
-!! html
+[[File:Foobaz.jpg]]
+!! html/php
<p><a href="/wiki/File:Foobaz.jpg" title="File:Foobaz.jpg">File:Foobaz.jpg</a>
</p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:Foobaz.jpg"><img resource="./File:Foobaz.jpg" src="./Special:FilePath/Foobaz.jpg" height="220" width="220"/></a></span></p>
!! end
# Parsoid-specific testing for images
@@ -11927,12 +12910,7 @@ Parsoid-specific image handling - simple image with size and middle alignment
!! wikitext
[[File:Foobar.jpg|middle|50px]]
!! html/parsoid
-<p><span class="mw-valign-middle" typeof="mw:Image">
-<a href="File:Foobar.jpg">
-<img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50">
-</a>
-</span>
-</p>
+<p><span class="mw-valign-middle" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></span></p>
!! end
!! test
@@ -11943,12 +12921,7 @@ parsoid=wt2wt,wt2html,html2html
!! wikitext
[[Image:Foobar.jpg|middle|50px]]
!! html/parsoid
-<p><span class="mw-valign-middle" typeof="mw:Image">
-<a href="File:Foobar.jpg">
-<img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50">
-</a>
-</span>
-</p>
+<p><span class="mw-valign-middle" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></span></p>
!! end
!! test
@@ -11957,7 +12930,7 @@ Parsoid-specific image handling - simple image with size and middle alignment
!! wikitext
[[File:Foobar.jpg|50px|middle]]
!! html/parsoid
-<p><span class="mw-valign-middle" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"middle","ak":"middle"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+<p><span class="mw-valign-middle" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"middle","ak":"middle"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
!! end
!! test
@@ -11968,12 +12941,7 @@ parsoid=wt2html,wt2wt,html2html
!! wikitext
[[Image:Foobar.jpg|50px|middle]]
!! html/parsoid
-<p><span class="mw-valign-middle" typeof="mw:Image">
-<a href="File:Foobar.jpg">
-<img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50">
-</a>
-</span>
-</p>
+<p><span class="mw-valign-middle" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a></span></p>
!! end
!! test
@@ -11981,7 +12949,7 @@ Parsoid-specific image handling - simple image with both sizes, a baseline align
!! wikitext
[[File:Foobar.jpg|500x10px|baseline|caption]]
!! html/parsoid
-<p><span class="mw-valign-baseline" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"500x10px"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption"}],"size":"500x10"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/89px-Foobar.jpg" height="10" width="89" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"10","width":"89"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+<p><span class="mw-valign-baseline" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"500x10px"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption"}],"size":"500x10"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/89px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="10" width="89" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"10","width":"89"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
!! end
!! test
@@ -11989,7 +12957,7 @@ Parsoid-specific image handling - simple image with border and size spec
!! wikitext
[[File:Foobar.jpg|50px|border|caption]]
!! html/parsoid
-<p><span class="mw-image-border" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+<p><span class="mw-image-border" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
!! end
!! test
@@ -11997,12 +12965,7 @@ Parsoid-specific image handling - thumbnail with halign, valign, and caption
!! wikitext
[[File:Foobar.jpg|left|baseline|thumb|caption content]]
!! html/parsoid
-<figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb">
-<a href="File:Foobar.jpg">
-<img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220" />
-</a>
-<figcaption>caption content</figcaption>
-</figure>
+<figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption content</figcaption></figure>
!! end
!! test
@@ -12011,7 +12974,7 @@ Parsoid-specific image handling - thumbnail with halign, valign, and caption
!! wikitext
[[File:Foobar.jpg|thumb|left|baseline|caption content]]
!! html/parsoid
-<figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"left","ak":"left"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption content"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption content</figcaption></figure>
+<figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"left","ak":"left"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption content"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption content</figcaption></figure>
!! end
!! test
@@ -12019,12 +12982,7 @@ Parsoid-specific image handling - thumbnail with specific size, halign, valign,
!! wikitext
[[Image:Foobar.jpg|right|middle|thumb|50x50px|caption]]
!! html/parsoid
-<figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb">
-<a href="File:Foobar.jpg">
-<img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" />
-</a>
-<figcaption>caption</figcaption>
-</figure>
+<figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a><figcaption>caption</figcaption></figure>
!! end
!! test
@@ -12033,7 +12991,7 @@ valign, and caption (existing content)
!! wikitext
[[File:Foobar.jpg|thumb|50x50px|right|middle|caption]]
!! html/parsoid
-<figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"50x50px"},{"ck":"right","ak":"right"},{"ck":"middle","ak":"middle"},{"ck":"caption","ak":"caption"}],"size":"50x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"50x50px"},{"ck":"right","ak":"right"},{"ck":"middle","ak":"middle"},{"ck":"caption","ak":"caption"}],"size":"50x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
!! end
!! test
@@ -12044,12 +13002,7 @@ parsoid=wt2html,wt2wt,html2html
!! wikitext
[[File:Foobar.jpg|frame|500x50px|caption]]
!! html/parsoid
-<figure typeof="mw:Image/Frame">
-<a href="File:Foobar.jpg">
-<img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941" />
-</a>
-<figcaption>caption</figcaption>
-</figure>
+<figure typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
!! end
!! test
@@ -12060,12 +13013,7 @@ parsoid=wt2html,wt2wt,html2html
!! wikitext
[[File:Foobar.jpg|left|baseline|frame|500x50px|caption]]
!! html/parsoid
-<figure class="mw-halign-left mw-valign-baseline" typeof="mw:Image/Frame">
-<a href="File:Foobar.jpg">
-<img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941" />
-</a>
-<figcaption>caption</figcaption>
-</figure>
+<figure class="mw-halign-left mw-valign-baseline" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>caption</figcaption></figure>
!! end
!! test
@@ -12073,7 +13021,7 @@ Parsoid-specific image handling - frameless image with specific size, border, an
!! wikitext
[[File:Foobar.jpg|frameless|442x50px|border|caption]]
!! html/parsoid
-<p><span class="mw-image-border" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"frameless","ak":"frameless"},{"ck":"width","ak":"442x50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}],"size":"442x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" height="50" width="442" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"50","width":"442"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+<p><span class="mw-image-border" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"frameless","ak":"frameless"},{"ck":"width","ak":"442x50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}],"size":"442x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="50" width="442" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"50","width":"442"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
!! end
!! test
@@ -12081,10 +13029,7 @@ Parsoid-specific image handling - simple image with a formatted caption
!! wikitext
[[File:Foobar.jpg|<table><tr><td>a</td><td>b</td></tr><tr><td>c</td></tr></table>]]
!! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&lt;table>&lt;tr>&lt;td>a&lt;/td>&lt;td>b&lt;/td>&lt;/tr>&lt;tr>&lt;td>c&lt;/td>&lt;/tr>&lt;/table>"}'>
-<a href="File:Foobar.jpg">
-<img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941">
-</a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&lt;table>&lt;tr>&lt;td>a&lt;/td>&lt;td>b&lt;/td>&lt;/tr>&lt;tr>&lt;td>c&lt;/td>&lt;/tr>&lt;/table>"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!! end
!! test
@@ -12092,7 +13037,7 @@ Parsoid-specific image handling - caption with a template in it
!! wikitext
[[File:Foobar.jpg|thumb|200x23px|This caption has a {{echo|transclusion}} in it.]]
!! html/parsoid
-<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>This caption has a <span about="#mwt1" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;transclusion&quot;}},&quot;i&quot;:0}}]}">transclusion</span> in it.</figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"></a><figcaption>This caption has a <span about="#mwt1" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;transclusion&quot;}},&quot;i&quot;:0}}]}">transclusion</span> in it.</figcaption></figure>
!! end
!! test
@@ -12105,7 +13050,7 @@ foo
bar
!! html/parsoid
<p>foo</p>
-<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"></a><figcaption>This caption has a <center>unbalanced tag in it.</center></figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>This caption has a <center>unbalanced tag in it.</center></figcaption></figure>
<p>bar</p>
!! end
@@ -12116,7 +13061,7 @@ parsoid=wt2html,wt2wt
!! wikitext
[[File:Foobar.jpg|thumb|]]
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption></figcaption></figure>
!! end
# empty captions don't get serialized unless we're in the "round trip" case
@@ -12126,9 +13071,10 @@ Parsoid-specific image handling - empty caption (2)
parsoid=html2wt
!! html/parsoid
<figure class="mw-default-size" typeof="mw:Image/Thumb">
- <a href="File:Foobar.jpg">
+ <a href="./File:Foobar.jpg">
<img resource="./File:Foobar.jpg"
src="//example.com/images/3/3a/Foobar.jpg"
+ data-file-width="1941" data-file-height="220" data-file-type="bitmap"
height="25" width="220"/>
</a>
<figcaption></figcaption>
@@ -12142,7 +13088,7 @@ Parsoid-specific image handling - whitespace caption
!! wikitext
[[File:Foobar.jpg|thumb| ]]
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption> </figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption> </figcaption></figure>
!! end
!! test
@@ -12153,7 +13099,7 @@ foo
bar
!! html/parsoid
<p>foo
-<span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" lang="de" height="180" width="240"/></a></span>
+<span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" lang="de" data-file-width="240" data-file-height="180" data-file-type="drawing" height="180" width="240"/></a></span>
bar</p>
!! end
@@ -12189,7 +13135,12 @@ subpage title=[[Subpage test]]
</p>
!! end
-# TODO: make this PHP-parser compatible!
+!! article
+Subpage test/1/2/subpage
+!! text
+blah
+!! endarticle
+
!! test
Relative subpage noslash link
!! options
@@ -12199,8 +13150,12 @@ subpage title=[[Subpage test/1/2/3/4]]
[[../../subpage/]]
[[../../subpage]]
-!! html
-<p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage/" title="Subpage test/1/2/subpage/">subpage</a></p>
+!! html/php
+<p><a href="/wiki/Subpage_test/1/2/subpage" title="Subpage test/1/2/subpage">subpage</a>
+</p><p><a href="/wiki/Subpage_test/1/2/subpage" title="Subpage test/1/2/subpage">Subpage test/1/2/subpage</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage" title="Subpage test/1/2/subpage">subpage</a></p>
<p><a rel="mw:WikiLink" href="Subpage_test/1/2/subpage" title="Subpage test/1/2/subpage">Subpage_test/1/2/subpage</a></p>
!! end
@@ -12273,8 +13228,28 @@ Render invalid page names as plain text (bug 51090)
[[foo&lt;bar]]
</p>
!!html/parsoid
-<p>[[./../foo|bar]][[foo�|bar]][[foo/.|bar]][[foo/..|bar]][[foo~~~bar]][[foo>bar]][[foo[bar]][[.]][[..]][[foo././bar]]</p>
-<p>[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"./../foo"}},"i":0}}]}'>./../foo</span>|bar]][[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo/."}},"i":0}}]}'>foo/.</span>|bar]][[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo/.."}},"i":0}}]}'>foo/..</span>|bar]][[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo~~~~bar"}},"i":0}}]}'>foo~~~~bar</span>]][[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo>bar"}},"i":0}}]}'>foo>bar</span>]][[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo././bar"}},"i":0}}]}'>foo././bar</span>]][[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo{bar"}},"i":0}}]}'>foo{bar</span>]][[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo}bar"}},"i":0}}]}'>foo}bar</span>]][[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo[bar"}},"i":0}}]}'>foo[bar</span>]][[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo]bar"}},"i":0}}]}'>foo]bar</span>]][[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo&lt;bar"}},"i":0}}]}'>foo&lt;bar</span>]]</p>
+<p>[[./../foo|bar]]
+[[foo�|bar]]
+[[foo/.|bar]]
+[[foo/..|bar]]
+[[foo~~~bar]]
+[[foo>bar]]
+[[foo[bar]]
+[[.]]
+[[..]]
+[[foo././bar]]</p>
+
+<p>[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"./../foo"}},"i":0}}]}'>./../foo</span>|bar]]
+[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo/."}},"i":0}}]}'>foo/.</span>|bar]]
+[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo/.."}},"i":0}}]}'>foo/..</span>|bar]]
+[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo~~~~bar"}},"i":0}}]}'>foo~~~~bar</span>]]
+[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo>bar"}},"i":0}}]}'>foo>bar</span>]]
+[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo././bar"}},"i":0}}]}'>foo././bar</span>]]
+[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo{bar"}},"i":0}}]}'>foo{bar</span>]]
+[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo}bar"}},"i":0}}]}'>foo}bar</span>]]
+[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo[bar"}},"i":0}}]}'>foo[bar</span>]]
+[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo]bar"}},"i":0}}]}'>foo]bar</span>]]
+[[<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo&lt;bar"}},"i":0}}]}'>foo&lt;bar</span>]]</p>
!!end
!! test
@@ -12496,8 +13471,8 @@ parsoid
[[:File:Foo.png|Bar]]
!! html
<p>
-<a rel="mw:WikiLink" href="File:Foo.png" title="File:Foo.png">File:Foo.png</a>
-<a rel="mw:WikiLink" href="File:Foo.png" title="File:Foo.png">Bar</a>
+<a rel="mw:WikiLink" href="./File:Foo.png" title="File:Foo.png">File:Foo.png</a>
+<a rel="mw:WikiLink" href="./File:Foo.png" title="File:Foo.png">Bar</a>
</p>
!! end
@@ -12514,15 +13489,31 @@ parsoid
!! end
!! test
-Parsoid: Defaultsort
+Normalize hrefs properly before testing for invalid link targets (bug 70894)
!! options
-parsoid
+parsoid=html2wt
+!! html
+<link rel="mw:PageProp/Category" href="./Category:Toxine_bactérienne"/>
+!! wikitext
+[[Category:Toxine bactérienne]]
+!! end
+
+!! test
+Parsoid: Defaultsort
!! wikitext
{{DEFAULTSORT:Foo}}
-!! html
+!! html/parsoid
<meta property="mw:PageProp/categorydefaultsort" content="Foo"/>
!! end
+!! test
+Parsoid: Defaultsort (template-generated)
+!! wikitext
+{{{{echo|DEFAULTSORT}}:Foo}}
+!! html/parsoid
+<meta property="mw:PageProp/categorydefaultsort" content="Foo" about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"dsr":[0,28,null,null],"pi":[[]]}' data-mw='{"parts":[{"template":{"target":{"wt":"{{echo|DEFAULTSORT}}:Foo"},"params":{},"i":0}}]}'/>
+!! end
+
###
### Inter-language links
###
@@ -12537,9 +13528,9 @@ ill
!! html/php
es:Alimento fr:Nourriture zh:食品
!! html/parsoid
-<p><link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/Alimento"/>
-<link rel="mw:PageProp/Language" href="//fr.wikipedia.org/wiki/Nourriture"/>
-<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/食品"/></p>
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Alimento"/>
+<link rel="mw:PageProp/Language" href="http://fr.wikipedia.org/wiki/Nourriture"/>
+<link rel="mw:PageProp/Language" href="http://zh.wikipedia.org/wiki/食品"/>
!! end
!! test
@@ -12554,10 +13545,10 @@ ill
!! html/php
es:1 fr:1
!! html/parsoid
-<p><link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/1"/>
-<link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/2"/>
-<link rel="mw:PageProp/Language" href="//fr.wikipedia.org/wiki/1"/>
-<link rel="mw:PageProp/Language" href="//fr.wikipedia.org/wiki/2"/></p>
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/1"/>
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/2"/>
+<link rel="mw:PageProp/Language" href="http://fr.wikipedia.org/wiki/1"/>
+<link rel="mw:PageProp/Language" href="http://fr.wikipedia.org/wiki/2"/>
!! end
###
@@ -12631,6 +13622,31 @@ Some text
!! end
+!! test
+TOC anchors don't collide
+!! wikitext
+__FORCETOC__
+== Headline 2 ==
+== Headline ==
+== Headline 2 ==
+== Headline ==
+!! html
+<div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#Headline_2"><span class="tocnumber">1</span> <span class="toctext">Headline 2</span></a></li>
+<li class="toclevel-1 tocsection-2"><a href="#Headline"><span class="tocnumber">2</span> <span class="toctext">Headline</span></a></li>
+<li class="toclevel-1 tocsection-3"><a href="#Headline_2_2"><span class="tocnumber">3</span> <span class="toctext">Headline 2</span></a></li>
+<li class="toclevel-1 tocsection-4"><a href="#Headline_3"><span class="tocnumber">4</span> <span class="toctext">Headline</span></a></li>
+</ul>
+</div>
+
+<h2><span class="mw-headline" id="Headline_2">Headline 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Headline 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="Headline">Headline</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Headline">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="Headline_2_2">Headline 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Headline 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="Headline_3">Headline</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=4" title="Edit section: Headline">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+
+!! end
+
# perl -e 'print "="x$_," Level $_ heading","="x$_,"\n" for 1..10'
!! test
Handling of sections up to level 6 and beyond
@@ -12690,7 +13706,7 @@ Handling of sections up to level 6 and beyond
!! end
!! test
-TOC regression (bug 9764)
+TOC regression (T11764)
!! wikitext
== title 1 ==
=== title 1.1 ===
@@ -12862,7 +13878,7 @@ Link inside a section heading
!! end
!! test
-TOC regression (bug 12077)
+TOC regression (T14077)
!! wikitext
__TOC__
== title 1 ==
@@ -12889,10 +13905,12 @@ __TOC__
!! test
BUG 1219 URL next to image (good)
!! wikitext
-http://example.com [[Image:foobar.jpg]]
-!! html
+http://example.com [[File:Foobar.jpg]]
+!! html/php
<p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a> <a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://example.com">http://example.com</a> <span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!!end
!! test
@@ -13115,10 +14133,12 @@ c3-->
!! test
BUG 1219 URL next to image (broken)
!! wikitext
-http://example.com[[Image:foobar.jpg]]
-!! html
+http://example.com[[File:Foobar.jpg]]
+!! html/php
<p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://example.com">http://example.com</a><span class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
!!end
!! test
@@ -13237,15 +14257,14 @@ parsoid
</tbody></table>
!! end
-# The PHP parser escapes the opening brace to &#123; for some reason, so
-# disabled this test for it.
!! test
div with braces in attribute value
-!! options
-parsoid
!! wikitext
<div title="{}">Foo</div>
-!! html
+!! html/php
+<div title="&#123;}">Foo</div>
+
+!! html/parsoid
<div title="{}">Foo</div>
!! end
@@ -13254,17 +14273,19 @@ parsoid
# 'div with empty attribute value, space before equals'), but strips the
# attribute completely if the space is missing. We hope that not much content
# depends on this, so are implementing the behavior below in Parsoid for
-# consistencies' sake. Disabled for the PHP parser.
+# consistencies' sake.
# FIXME: fix this behavior in the PHP parser?
!! test
div with empty attribute value, no space before equals
!! options
-parsoid
+parsoid=wt2html,html2html
!! wikitext
<div class=>HTML rocks</div>
-!! html
-<div class="">HTML rocks</div>
+!! html/php
+<div>HTML rocks</div>
+!! html/parsoid
+<div class="">HTML rocks</div>
!! end
!! test
@@ -13482,16 +14503,17 @@ Media link with text
!! end
# FIXME: this is still bad HTML tag nesting
+# FIXME: doBlockLevels won't wrap this in a paragraph because it contains a div
!! test
Media link with nasty text
-fixme: doBlockLevels won't wrap this in a paragraph because it contains a div
!! wikitext
[[Media:Foobar.jpg|Safe Link<div style=display:none>" onmouseover="alert(document.cookie)" onfoo="</div>]]
!! html
<a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Safe Link&lt;div style="display:none"&gt;" onmouseover="alert(document.cookie)" onfoo="&lt;/div&gt;</a>
!! html+tidy
-<p><a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Safe Link&lt;div style="display:none"&gt;" onmouseover="alert(document.cookie)" onfoo="&lt;/div&gt;</a></p>
+<p><a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Safe Link</a></p>
+<div style="display:none">" onmouseover="alert(document.cookie)" onfoo="</div>
!! end
!! test
@@ -13506,19 +14528,23 @@ Media link to nonexistent file (bug 1702)
!! test
Image link to nonexistent file (bug 1850 - good)
!! wikitext
-[[Image:No such.jpg]]
-!! html
+[[File:No_such.jpg]]
+!! html/php
<p><a href="/index.php?title=Special:Upload&amp;wpDestFile=No_such.jpg" class="new" title="File:No such.jpg">File:No such.jpg</a>
</p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:No_such.jpg"><img resource="./File:No_such.jpg" src="./Special:FilePath/No_such.jpg" height="220" width="220"/></a></span></p>
!! end
!! test
:Image link to nonexistent file (bug 1850 - bad)
!! wikitext
[[:Image:No such.jpg]]
-!! html
+!! html/php
<p><a href="/index.php?title=File:No_such.jpg&amp;action=edit&amp;redlink=1" class="new" title="File:No such.jpg (page does not exist)">Image:No such.jpg</a>
</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./File:No_such.jpg" title="File:No such.jpg">Image:No such.jpg</a></p>
!! end
@@ -13685,7 +14711,7 @@ Bug 2304: HTML attribute safety (dangerous template; 2309)
<div title=""></div>
!! html/parsoid
-<div title='" onmouseover="alert(document.cookie)' about="#mwt2" typeof="mw:ExpandedAttrs" data-mw='{"attribs":[[{"txt":"title"},{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;dangerous attribute&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Dangerous_attribute&amp;quot;},&amp;quot;params&amp;quot;:{},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[]],&amp;quot;dsr&amp;quot;:[12,35,null,null]}\">\" onmouseover=\"alert(document.cookie)&lt;/span>"}]]}' data-parsoid='{"stx":"html","a":{"title":"\" onmouseover=\"alert(document.cookie)"},"sa":{"title":"{{dangerous attribute}}"}}'></div>
+<div title='" onmouseover="alert(document.cookie)' about="#mwt2" typeof="mw:ExpandedAttrs" data-parsoid='{"stx":"html","a":{"title":"\" onmouseover=\"alert(document.cookie)"},"sa":{"title":"{{dangerous attribute}}"}}' data-mw='{"attribs":[[{"txt":"title"},{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=\"{&amp;quot;pi&amp;quot;:[[]],&amp;quot;dsr&amp;quot;:[12,35,null,null]}\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;dangerous attribute&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Dangerous_attribute&amp;quot;},&amp;quot;params&amp;quot;:{},&amp;quot;i&amp;quot;:0}}]}\">\" onmouseover=\"alert(document.cookie)&lt;/span>"}]]}'></div>
!! end
!! test
@@ -14005,9 +15031,12 @@ Expansion of multi-line templates in attribute values (bug 6255 sanity check)
!! wikitext
<div style="background:
#00FF00">-</div>
-!! html
+!! html/php
<div style="background: #00FF00">-</div>
+!! html/parsoid
+<div style="background:
+#00FF00">-</div>
!! end
!! test
@@ -14245,6 +15274,10 @@ Nested template calls
###
### Sanitizer
###
+
+# HTML+Tidy effectively strips out the empty tags completely
+# But since Parsoid doesn't it wraps the <s></s> tags in p-tags
+# which Tidy would have done for the PHP parser had there been content inside it.
!! test
Sanitizer: Closing of open tags
!! wikitext
@@ -14252,6 +15285,8 @@ Sanitizer: Closing of open tags
!! html
<s></s><table></table>
+!! html/parsoid
+<p><s></s></p><table></table>
!! end
!! test
@@ -14290,16 +15325,19 @@ Sanitizer: Escaping of spaces, multibyte characters, colons & other stuff in id=
</p>
!! end
+# In HTML5, the restrictions are that id must contain at least one character,
+# and must not contain any space characters.
!! test
Sanitizer: Validating the contents of the id attribute (bug 4515)
!! options
disabled
!! wikitext
-<br id=9 />
+<br id="" /><br id="a space" />
!! html
-Something, but definitely not <br id="9" />...
+Something ...
!! end
+# In HTML5, id must be unique amongst all the ids in the element's home subtree.
!! test
Sanitizer: Validating id attribute uniqueness (bug 4515, bug 6301)
!! options
@@ -14397,7 +15435,6 @@ Punctuation: CSS ! important (bug 11874; with space after)
!!end
-
!! test
HTML bullet list, closed tags (bug 5497)
!! wikitext
@@ -14405,29 +15442,36 @@ HTML bullet list, closed tags (bug 5497)
<li>One</li>
<li>Two</li>
</ul>
-!! html
+!! html/php
<ul>
<li>One</li>
<li>Two</li>
</ul>
+!! html/parsoid
+<ul data-parsoid='{"stx":"html"}'>
+<li data-parsoid='{"stx":"html"}'>One</li>
+<li data-parsoid='{"stx":"html"}'>Two</li>
+</ul>
+
!! end
!! test
HTML bullet list, unclosed tags (bug 5497)
-!! options
-disabled
!! wikitext
<ul>
<li>One
<li>Two
</ul>
-!! html
+!! html/php+tidy
<ul>
-<li>One
-</li>
-<li>Two
-</li>
+<li>One</li>
+<li>Two</li>
+</ul>
+!! html/parsoid
+<ul data-parsoid='{"stx":"html"}'>
+<li data-parsoid='{"stx":"html","autoInsertedEnd":true}'>One</li>
+<li data-parsoid='{"stx":"html","autoInsertedEnd":true}'>Two</li>
</ul>
!! end
@@ -14439,29 +15483,37 @@ HTML ordered list, closed tags (bug 5497)
<li>One</li>
<li>Two</li>
</ol>
-!! html
+!! html/php
<ol>
<li>One</li>
<li>Two</li>
</ol>
+!! html/parsoid
+<ol data-parsoid='{"stx":"html"}'>
+<li data-parsoid='{"stx":"html"}'>One</li>
+<li data-parsoid='{"stx":"html"}'>Two</li>
+</ol>
+
!! end
!! test
HTML ordered list, unclosed tags (bug 5497)
!! options
-disabled
!! wikitext
<ol>
<li>One
<li>Two
</ol>
-!! html
+!! html/php+tidy
<ol>
-<li>One
-</li>
-<li>Two
-</li>
+<li>One</li>
+<li>Two</li>
+</ol>
+!! html/parsoid
+<ol data-parsoid='{"stx":"html"}'>
+<li data-parsoid='{"stx":"html","autoInsertedEnd":true}'>One</li>
+<li data-parsoid='{"stx":"html","autoInsertedEnd":true}'>Two</li>
</ol>
!! end
@@ -14493,8 +15545,6 @@ HTML nested bullet list, closed tags (bug 5497)
!! test
HTML nested bullet list, open tags (bug 5497)
-!! options
-disabled
!! wikitext
<ul>
<li>One
@@ -14504,7 +15554,17 @@ disabled
<li>Sub-two
</ul>
</ul>
-!! html
+!! html/php+tidy
+<ul>
+<li>One</li>
+<li>Two:
+<ul>
+<li>Sub-one</li>
+<li>Sub-two</li>
+</ul>
+</li>
+</ul>
+!! html/parsoid
<ul>
<li>One
</li>
@@ -14547,8 +15607,6 @@ HTML nested ordered list, closed tags (bug 5497)
!! test
HTML nested ordered list, open tags (bug 5497)
-!! options
-disabled
!! wikitext
<ol>
<li>One
@@ -14558,7 +15616,17 @@ disabled
<li>Sub-two
</ol>
</ol>
-!! html
+!! html/php
+<ol>
+<li>One
+<li>Two:
+<ol>
+<li>Sub-one
+<li>Sub-two
+</ol>
+</ol>
+
+!! html/parsoid
<ol>
<li>One
</li>
@@ -14659,6 +15727,7 @@ http://<div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
<li class="toclevel-1 tocsection-1"><a href="#onmouseover.3D"><span class="tocnumber">1</span> <span class="toctext">onmouseover=</span></a></li>
</ul>
</div>
+<p></p>
!! end
!! test
@@ -14798,32 +15867,38 @@ Fuzz testing: Parser25 (bug 6055)
Fuzz testing: URL adjacent extension (with space, clean)
!! wikitext
http://example.com <nowiki>junk</nowiki>
-!! html
+!! html/php
<p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a> junk
</p>
-!!end
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url"}'>http://example.com</a> <span typeof="mw:Nowiki">junk</span></p>
+!! end
!!test
Fuzz testing: URL adjacent extension (no space, dirty; nowiki)
!! wikitext
http://example.com<nowiki>junk</nowiki>
-!! html
+!! html/php
<p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>junk
</p>
-!!end
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url"}'>http://example.com</a><span typeof="mw:Nowiki">junk</span></p>
+!! end
!!test
Fuzz testing: URL adjacent extension (no space, dirty; pre)
!! wikitext
http://example.com<pre>junk</pre>
-!! html
+!! html/php
<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a><pre>junk</pre>
-!! html+tidy
+!! html/php+tidy
<p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a></p>
<pre>
junk
</pre>
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url"}'>http://example.com</a></p><pre data-parsoid='{"stx":"html"}'>junk</pre>
!!end
!!test
@@ -14834,7 +15909,7 @@ Fuzz testing: image with bogus manual thumbnail
<div class="thumb tright"><div class="thumbinner" style="width:182px;">Error creating thumbnail: <div class="thumbcaption"></div></div></div>
!! html/parsoid
-<meta typeof="mw:Placeholder" data-parsoid='{"src":"[[Image:foobar.jpg|thumbnail= ]]","optList":[{"ck":"manualthumb","ak":"thumbnail= "}],"dsr":[0,32,null,null]}'/>
+<figure class="mw-default-size" typeof="mw:Error mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"manualthumb","ak":"thumbnail= "}],"dsr":[0,32,2,2]}' data-mw='{"errors":[{"key":"missing-thumbnail","message":"This thumbnail does not exist.","params":{"name":""}}],"thumb":""}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{},"dsr":[2,30,null,null]}'><img resource="./File:Foobar.jpg" src="./Special:FilePath/" height="220" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"220"},"sa":{"resource":"Image:foobar.jpg"}}'/></a></figure>
!!end
!! test
@@ -14912,15 +15987,19 @@ New wiki paragraph
</p>
!! end
+# FIXME: The current php output is documented
+# and desired output is the parsoid target.
!! test
Inline HTML vs wiki block nesting
-!! options
-disabled
!! wikitext
<b>Bold paragraph
New wiki paragraph
-!! html
+!! html/php
+<p><b>Bold paragraph
+</p><p>New wiki paragraph</b>
+</p>
+!! html/parsoid
<p><b>Bold paragraph</b>
</p><p>New wiki paragraph
</p>
@@ -15913,6 +16992,17 @@ Special:Search page linking.
!! end
!! test
+{{!}} is a magic word
+!! wikitext
+{{!}} is a magic word there and {{!}} is still a magic word here
+!! html/php
+<p>| is a magic word there and | is still a magic word here
+</p>
+!! html/parsoid
+<p><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"!","href":"./Template:!"},"params":{},"i":0}}]}' data-parsoid='{"pi":[[]]}'>|</span> is a magic word there and <span about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"!","href":"./Template:!"},"params":{},"i":0}}]}' data-parsoid='{"pi":[[]]}'>|</span> is still a magic word here</p>
+!! end
+
+!! test
Say the magic word
!! options
title=[[Parser test]]
@@ -16025,8 +17115,8 @@ image4 |300px| centre
Gallery (with options)
!! wikitext
<gallery widths='70px' heights='40px' perrow='2' caption='Foo [[Main Page]]' >
-File:Nonexistant.jpg|caption
-File:Nonexistant.jpg
+File:Nonexistent.jpg|caption
+File:Nonexistent.jpg
image:foobar.jpg|some '''caption''' [[Main Page]]
image:foobar.jpg
image:foobar.jpg|Blabla|alt=This is a foo-bar.|blabla.
@@ -16035,31 +17125,31 @@ image:foobar.jpg|Blabla|alt=This is a foo-bar.|blabla.
<ul class="gallery mw-gallery-traditional" style="max-width: 226px;_width: 226px;">
<li class='gallerycaption'>Foo <a href="/wiki/Main_Page" title="Main Page">Main Page</a></li>
<li class="gallerybox" style="width: 105px"><div style="width: 105px">
- <div class="thumb" style="height: 70px;">Nonexistant.jpg</div>
+ <div class="thumb" style="height: 70px;">Nonexistent.jpg</div>
<div class="gallerytext">
<p>caption
</p>
</div>
</div></li>
<li class="gallerybox" style="width: 105px"><div style="width: 105px">
- <div class="thumb" style="height: 70px;">Nonexistant.jpg</div>
+ <div class="thumb" style="height: 70px;">Nonexistent.jpg</div>
<div class="gallerytext">
</div>
</div></li>
<li class="gallerybox" style="width: 105px"><div style="width: 105px">
- <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" /></a></div></div>
+ <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/105px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/140px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
<p>some <b>caption</b> <a href="/wiki/Main_Page" title="Main Page">Main Page</a>
</p>
</div>
</div></li>
<li class="gallerybox" style="width: 105px"><div style="width: 105px">
- <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" /></a></div></div>
+ <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/105px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/140px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
</div>
</div></li>
<li class="gallerybox" style="width: 105px"><div style="width: 105px">
- <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="This is a foo-bar." src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" /></a></div></div>
+ <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="This is a foo-bar." src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/105px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/140px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
<p>Blabla|blabla.
</p>
@@ -16080,17 +17170,17 @@ image:foobar.jpg|link=Main Page#section|caption
!! html
<ul class="gallery mw-gallery-traditional">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Main_Page"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Main_Page"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Main_Page#section"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Main_Page#section"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Main_Page#section"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Main_Page#section"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
<p>caption
</p>
@@ -16110,14 +17200,14 @@ File:foobar.jpg|{{Test|unamedParam|alt=param}}|alt=galleryalt
!! html
<ul class="gallery mw-gallery-traditional">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
<p><a href="/wiki/File:Foobar.jpg" class="image" title="desc"><img alt="inneralt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/20px-Foobar.jpg" width="20" height="2" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/30px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/40px-Foobar.jpg 2x" /></a>
</p>
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
<p>This is a test template
</p>
@@ -16131,30 +17221,30 @@ File:foobar.jpg|{{Test|unamedParam|alt=param}}|alt=galleryalt
gallery (with showfilename option)
!! wikitext
<gallery showfilename>
-File:Nonexistant.jpg|caption
-File:Nonexistant.jpg
+File:Nonexistent.jpg|caption
+File:Nonexistent.jpg
image:foobar.jpg|some '''caption''' [[Main Page]]
File:Foobar.jpg
</gallery>
!! html
<ul class="gallery mw-gallery-traditional">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="height: 150px;">Nonexistant.jpg</div>
+ <div class="thumb" style="height: 150px;">Nonexistent.jpg</div>
<div class="gallerytext">
-<p><a href="/wiki/File:Nonexistant.jpg" title="File:Nonexistant.jpg">Nonexistant.jpg</a><br />
+<p><a href="/wiki/File:Nonexistent.jpg" title="File:Nonexistent.jpg">Nonexistent.jpg</a><br />
caption
</p>
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="height: 150px;">Nonexistant.jpg</div>
+ <div class="thumb" style="height: 150px;">Nonexistent.jpg</div>
<div class="gallerytext">
-<p><a href="/wiki/File:Nonexistant.jpg" title="File:Nonexistant.jpg">Nonexistant.jpg</a><br />
+<p><a href="/wiki/File:Nonexistent.jpg" title="File:Nonexistent.jpg">Nonexistent.jpg</a><br />
</p>
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
<p><a href="/wiki/File:Foobar.jpg" title="File:Foobar.jpg">Foobar.jpg</a><br />
some <b>caption</b> <a href="/wiki/Main_Page" title="Main Page">Main Page</a>
@@ -16162,7 +17252,7 @@ some <b>caption</b> <a href="/wiki/Main_Page" title="Main Page">Main Page</a>
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
<p><a href="/wiki/File:Foobar.jpg" title="File:Foobar.jpg">Foobar.jpg</a><br />
</p>
@@ -16176,30 +17266,30 @@ some <b>caption</b> <a href="/wiki/Main_Page" title="Main Page">Main Page</a>
Gallery (with namespace-less filenames)
!! wikitext
<gallery>
-File:Nonexistant.jpg
-Nonexistant.jpg
+File:Nonexistent.jpg
+Nonexistent.jpg
image:foobar.jpg
foobar.jpg
</gallery>
!! html
<ul class="gallery mw-gallery-traditional">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="height: 150px;">Nonexistant.jpg</div>
+ <div class="thumb" style="height: 150px;">Nonexistent.jpg</div>
<div class="gallerytext">
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="height: 150px;">Nonexistant.jpg</div>
+ <div class="thumb" style="height: 150px;">Nonexistent.jpg</div>
<div class="gallerytext">
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
</div>
</div></li>
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
</div>
</div></li>
@@ -16267,6 +17357,8 @@ ISBN 978-0-1234-56&#x20;789
</p>
!! html+tidy
<p><a href="/wiki/Special:BookSources/9780123456" class="internal mw-magiclink-isbn">ISBN 978-0-1234-56</a> 789</p>
+!! html/parsoid
+<p><a href="./Special:BookSources/9780123456" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 978-0-1234-56</a><span typeof="mw:Entity" data-parsoid='{"src":"&amp;#x20;","srcContent":" "}'> </span>789</p>
!! end
!! test
@@ -16282,24 +17374,37 @@ ISBN
Double ISBN
!! wikitext
ISBN ISBN 1234567890
-!! html
+!! html/php
<p>ISBN <a href="/wiki/Special:BookSources/1234567890" class="internal mw-magiclink-isbn">ISBN 1234567890</a>
</p>
+!! html/parsoid
+<p>ISBN <a href="./Special:BookSources/1234567890" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 1234567890</a></p>
!! end
!! test
ISBN with an X
!! wikitext
ISBN 3-462-04561-X
-!! html
+ISBN 080442957X
+ISBN 978080442957X
+!! html/php
<p><a href="/wiki/Special:BookSources/346204561X" class="internal mw-magiclink-isbn">ISBN 3-462-04561-X</a>
+<a href="/wiki/Special:BookSources/080442957X" class="internal mw-magiclink-isbn">ISBN 080442957X</a>
+<a href="/wiki/Special:BookSources/978080442957X" class="internal mw-magiclink-isbn">ISBN 978080442957X</a>
</p>
+!! html/parsoid
+<p><a href="./Special:BookSources/346204561X" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 3-462-04561-X</a>
+<a href="./Special:BookSources/080442957X" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 080442957X</a>
+<a href="./Special:BookSources/978080442957X" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 978080442957X</a></p>
!! end
!! test
ISBN with empty prefix (parsoid test)
!! wikitext
ISBN 1234567890
+!! html/php
+<p><a href="/wiki/Special:BookSources/1234567890" class="internal mw-magiclink-isbn">ISBN 1234567890</a>
+</p>
!! html/parsoid
<p><a href="Special:BookSources/1234567890" rel="mw:ExtLink">ISBN 1234567890</a></p>
!! end
@@ -16308,9 +17413,11 @@ ISBN 1234567890
Bug 22905: <abbr> followed by ISBN followed by </a>
!! wikitext
<abbr>(fr)</abbr> ISBN 2753300917 [http://www.example.com example.com]
-!! html
+!! html/php
<p><abbr>(fr)</abbr> <a href="/wiki/Special:BookSources/2753300917" class="internal mw-magiclink-isbn">ISBN 2753300917</a> <a rel="nofollow" class="external text" href="http://www.example.com">example.com</a>
</p>
+!! html/parsoid
+<p><abbr data-parsoid='{"stx":"html"}'>(fr)</abbr> <a href="./Special:BookSources/2753300917" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 2753300917</a> <a rel="mw:ExtLink" href="http://www.example.com">example.com</a></p>
!! end
!! test
@@ -16402,9 +17509,11 @@ Image with page parameter
djvu
!! wikitext
[[File:LoremIpsum.djvu|page=2]]
-!! html
+!! html/php
<p><a href="/index.php?title=File:LoremIpsum.djvu&amp;page=2" class="image"><img alt="LoremIpsum.djvu" src="http://example.com/images/thumb/5/5f/LoremIpsum.djvu/page2-2480px-LoremIpsum.djvu.jpg" width="2480" height="3508" srcset="http://example.com/images/thumb/5/5f/LoremIpsum.djvu/page2-3720px-LoremIpsum.djvu.jpg 1.5x, http://example.com/images/thumb/5/5f/LoremIpsum.djvu/page2-4960px-LoremIpsum.djvu.jpg 2x" /></a>
</p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"page","ak":"page=2"}]}'><a href="./File:LoremIpsum.djvu" data-parsoid='{"a":{"href":"./File:LoremIpsum.djvu"},"sa":{}}'><img resource="./File:LoremIpsum.djvu" src="//example.com/images/5/5f/LoremIpsum.djvu" data-file-width="2480" data-file-height="3508" data-file-type="bitmap" height="3508" width="2480" data-parsoid='{"a":{"resource":"./File:LoremIpsum.djvu","height":"3508","width":"2480"},"sa":{"resource":"File:LoremIpsum.djvu"}}'/></a></span></p>
!! end
!! test
@@ -16416,35 +17525,16 @@ Another italics / bold test
</pre>
!!end
-# Note the results may be incorrect, as parserTest output included this:
-# XML error: Mismatched tag at byte 6120:
-# ...<dd> </dt></dl> </dd...
+# FIXME: The php output seems broken. It's interleaving some open/close tags.
!! test
dt/dd/dl test
-!! options
-disabled
!! wikitext
:;;;::
-!! html
-<dl>
-<dd><dl>
-<dt><dl>
-<dt><dl>
-<dt><dl>
-<dd><dl>
-<dd>
-</dd>
-</dl>
-</dd>
-</dl>
-</dt>
-</dl>
-</dt>
-</dl>
-</dt>
-</dl>
-</dd>
-</dl>
+!! html/php
+<dl><dd><dl><dt><dl><dt><dl><dt><dl><dd><dl><dd></dt></dl></dd></dl></dd></dl></dd></dl></dd></dl></dd></dl>
+
+!! html/parsoid
+<dl><dd><dl><dt><dl><dt><dl><dt><dl><dd><dl><dd></dd></dl></dd></dl></dt></dl></dt></dl></dt></dl></dd></dl>
!!end
@@ -16458,7 +17548,7 @@ Images with the "|" character in the comment
<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>An <a rel="nofollow" class="external text" href="http://test/?param1=%7Cleft%7C&amp;param2=%7Cx">external</a> URL</div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>An <a rel="mw:ExtLink" href="http://test/?param1=|left|&amp;param2=|x">external</a> URL</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>An <a rel="mw:ExtLink" href="http://test/?param1=|left|&amp;param2=|x">external</a> URL</figcaption></figure>
!! end
!! test
@@ -16538,7 +17628,7 @@ subpage title=[[Subpage test/L1/L2/L3]]
!! wikitext
[[../../////]]
!! html
-<p><a href="/index.php?title=Subpage_test/L1////&amp;action=edit&amp;redlink=1" class="new" title="Subpage test/L1//// (page does not exist)">///</a>
+<p><a href="/index.php?title=Subpage_test/L1&amp;action=edit&amp;redlink=1" class="new" title="Subpage test/L1 (page does not exist)">Subpage test/L1</a>
</p>
!! end
@@ -16587,7 +17677,7 @@ Definition list code coverage
; title : def
; title : def
;title: def
-!! html
+!! html/php
<dl><dt> title &#160;</dt>
<dd> def</dd>
<dt> title&#160;</dt>
@@ -16595,6 +17685,10 @@ Definition list code coverage
<dt>title</dt>
<dd> def</dd></dl>
+!! html/parsoid
+<dl><dt> title <span typeof="mw:Placeholder"> </span></dt><dd> def</dd>
+<dt> title<span typeof="mw:Placeholder"> </span></dt><dd> def</dd>
+<dt>title</dt><dd> def</dd></dl>
!! end
!! test
@@ -17051,7 +18145,7 @@ language=sr variant=sr-ec
!! wikitext
== -{Naslov}- ==
!! html
-<h2><span class="mw-headline" id="-.7BNaslov.7D-">Naslov</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Уредите одељак „Naslov“">уреди</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="-.7BNaslov.7D-">Naslov</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Уреди одељак „Naslov“">уреди</a><span class="mw-editsection-bracket">]</span></span></h2>
!! end
@@ -17277,45 +18371,51 @@ language=sr variant=sr-ec
</p>
!! end
-# This test is currently broken in the PHP parser (bug 52661)
+# FIXME: This test is currently broken in the PHP parser (bug 52661)
!! test
Don't break image parsing if language converter markup is in the caption.
!! options
language=sr
-disabled
!! wikitext
[[File:Foobar.jpg|-{R|caption}-]]
-!! html
+!! html/parsoid
<p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
</p>
!! end
-# This test is currently broken in the PHP parser (bug 52661)
+# FIXME: This test is currently broken in the PHP parser (bug 52661)
!! test
Don't break list handling if language converter markup is in the item.
!! options
language=zh variant=zh-cn
-disabled
!! wikitext
;-{zh-cn:AAA;zh-tw:BBB}-
-!! html
+!! html/php
+<dl><dt><span class="error">在手动语言转换规则中检测到错误</span></dd></dl>
+
+!! html/parsoid
<dl><dt>AAA
</dt></dl>
-
!! end
-# This test is currently broken in the PHP parser (bug 52661)
+# FIXME: This test is currently broken in the PHP parser (bug 52661)
!! test
Don't break table handling if language converter markup is in the cell.
!! options
language=sr variant=sr-ec
-disabled
!! wikitext
{|
|-
| -{R|B}-
|}
-!! html
+!! html/php
+<table>
+
+<tr>
+<td>Б}-
+</td></tr></table>
+
+!! html/parsoid
<table>
<tr>
@@ -17534,12 +18634,13 @@ Line two
!! test
Nesting tags, paragraphs on lines which begin with <div>
-!! options
-disabled
!! wikitext
<div></div><strong>A
B</strong>
-!! html
+!! html/php+tidy
+<p><strong>A</strong></p>
+<p><strong>B</strong></p>
+!! html/parsoid
<div></div>
<p><strong>A
B</strong>
@@ -17941,27 +19042,35 @@ comment
<a href="/index.php?title=ABC3D%25_%2B%2B&amp;action=edit&amp;redlink=1" class="new" title="ABC3D% ++ (page does not exist)">ABC3D% ++</a> <a href="/index.php?title=ABC3D%25_%2B%2B&amp;action=edit&amp;redlink=1" class="new" title="ABC3D% ++ (page does not exist)">+%20</a>
!! end
+# Parsoid doesn't support this yet: see bug 73581
+# but it *should* omit the 'src' attribute if the image is bad.
+# PHP side of tests was disabled in
+# mediawiki/core:6bd31e7d95161a6e88fa86df60871051da997c3c
+# because of issues in the PHP parserTests infrastructure
+# (but the output below is indeed what the PHP side emits)
!! test
Bad images - basic functionality
-!! options
-disabled
!! wikitext
[[File:Bad.jpg]]
-!! html
+!! DISABLED/html/php
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"bad-image","message":"This image is blacklisted in this context."}]}'><a href="./File:Bad.jpg"><img resource="./File:Bad.jpg" height="220" width="220"/></a></span></p>
!! end
!! test
Bad images - bug 16039: text after bad image disappears
-!! options
-disabled
!! wikitext
Foo bar
[[File:Bad.jpg]]
Bar foo
-!! html
+!! DISABLED/html/php
<p>Foo bar
</p><p>Bar foo
</p>
+!! html/parsoid
+<p>Foo bar
+<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"bad-image","message":"This image is blacklisted in this context."}]}'><a href="./File:Bad.jpg"><img resource="./File:Bad.jpg" height="220" width="220"/></a></span>
+Bar foo</p>
!! end
!! test
@@ -18097,6 +19206,82 @@ this is not the the title
!! end
!! test
+Page status indicators: Empty name is invalid
+!! options
+showindicators
+!! wikitext
+<indicator name=" "></indicator>
+<indicator></indicator>
+!! html
+<p><span class="error"><strong>Error:</strong> Page status indicators' <code>name</code> attribute must not be empty.</span>
+<span class="error"><strong>Error:</strong> Page status indicators' <code>name</code> attribute must not be empty.</span>
+</p>
+!! end
+
+!! test
+Page status indicators: Weird syntaxes that are okay
+!! options
+showindicators
+!! wikitext
+<indicator name="empty" />
+<indicator name></indicator>
+!! html
+empty=
+name=
+<p><br />
+</p>
+!! end
+
+!! test
+Page status indicators: Torture test
+!! options
+showindicators
+!! wikitext
+<indicator name="01">hello world</indicator>
+<indicator name="02">[[Main Page]]</indicator>
+<indicator name="03">[[File:Foobar.jpg|25px|link=]]</indicator>
+<indicator name="04">[[File:Foobar.jpg|25px]]</indicator>
+<indicator name="05">* foo
+* bar</indicator>
+<indicator name="06"><nowiki>foo</nowiki></indicator>
+<indicator name="07"> Preformatted</indicator>
+<indicator name="08"><div>Broken tag</indicator>
+<indicator name="09">{| class=wikitable
+| cell
+|}</indicator>
+<indicator name="10">Two
+
+paragraphs</indicator>
+!! html
+01=hello world
+02=<a href="/wiki/Main_Page" title="Main Page">Main Page</a>
+03=<img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/25px-Foobar.jpg" width="25" height="3" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/38px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg 2x" />
+04=<a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/25px-Foobar.jpg" width="25" height="3" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/38px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg 2x" /></a>
+05=<ul><li> foo</li>
+<li> bar</li></ul>
+
+06=foo
+07=<pre>Preformatted
+</pre>
+08=<div>Broken tag</div>
+
+09=<table class="wikitable">
+<tr>
+<td> cell
+</td></tr></table>
+
+10=<p>Two
+</p><p>paragraphs
+</p>
+<p><br />
+</p><p><br />
+</p><p><br />
+</p><p><br />
+</p><p><br />
+</p>
+!! end
+
+!! test
preload: check <noinclude> and <includeonly>
!! options
preload
@@ -18138,18 +19323,22 @@ preload
!! test
Play a bit with r67090 and bug 3158
-!! options
-disabled
!! wikitext
<div style="width:50% !important">&nbsp;</div>
<div style="width:50%&nbsp;!important">&nbsp;</div>
<div style="width:50%&#160;!important">&nbsp;</div>
<div style="border : solid;">&nbsp;</div>
-!! html
-<div style="width:50% !important">&nbsp;</div>
-<div style="width:50% !important">&nbsp;</div>
-<div style="width:50% !important">&nbsp;</div>
-<div style="border&#160;: solid;">&nbsp;</div>
+!! html/php
+<div style="width:50% !important">&#160;</div>
+<div style="width:50% !important">&#160;</div>
+<div style="width:50% !important">&#160;</div>
+<div style="border&#160;: solid;">&#160;</div>
+
+!! html/parsoid
+<div style="width:50% !important" data-parsoid='{"stx":"html"}'><span typeof="mw:Entity" data-parsoid='{"srcContent":" "}'> </span></div>
+<div style="width:50% !important" data-parsoid='{"stx":"html","a":{"style":"width:50% !important"},"sa":{"style":"width:50%&amp;nbsp;!important"}}'><span typeof="mw:Entity" data-parsoid='{"srcContent":" "}'> </span></div>
+<div style="width:50% !important" data-parsoid='{"stx":"html","a":{"style":"width:50% !important"},"sa":{"style":"width:50%&amp;#160;!important"}}'><span typeof="mw:Entity" data-parsoid='{"srcContent":" "}'> </span></div>
+<div style="border : solid;" data-parsoid='{"stx":"html"}'><span typeof="mw:Entity" data-parsoid='{"srcContent":" "}'> </span></div>
!! end
@@ -18170,14 +19359,16 @@ percent-encoding and + signs in internal links (Bug 26410)
!! wikitext
[[User:+%]] [[Page+title%]]
[[%+]] [[%+|%20]] [[%+ ]] [[%+r]]
-[[%]] [[+]] [[image:%+abc%39|foo|[[bar]]]]
+[[%]] [[+]] [[File:%+abc%39|foo|[[bar]]]]
[[%33%45]] [[%33%45+]]
-!! html
+!! html/php
<p><a href="/index.php?title=User:%2B%25&amp;action=edit&amp;redlink=1" class="new" title="User:+% (page does not exist)">User:+%</a> <a href="/index.php?title=Page%2Btitle%25&amp;action=edit&amp;redlink=1" class="new" title="Page+title% (page does not exist)">Page+title%</a>
<a href="/index.php?title=%25%2B&amp;action=edit&amp;redlink=1" class="new" title="%+ (page does not exist)">%+</a> <a href="/index.php?title=%25%2B&amp;action=edit&amp;redlink=1" class="new" title="%+ (page does not exist)">%20</a> <a href="/index.php?title=%25%2B&amp;action=edit&amp;redlink=1" class="new" title="%+ (page does not exist)">%+ </a> <a href="/index.php?title=%25%2Br&amp;action=edit&amp;redlink=1" class="new" title="%+r (page does not exist)">%+r</a>
<a href="/index.php?title=%25&amp;action=edit&amp;redlink=1" class="new" title="% (page does not exist)">%</a> <a href="/index.php?title=%2B&amp;action=edit&amp;redlink=1" class="new" title="+ (page does not exist)">+</a> <a href="/index.php?title=Special:Upload&amp;wpDestFile=%25%2Babc9" class="new" title="File:%+abc9">bar</a>
<a href="/index.php?title=3E&amp;action=edit&amp;redlink=1" class="new" title="3E (page does not exist)">3E</a> <a href="/index.php?title=3E%2B&amp;action=edit&amp;redlink=1" class="new" title="3E+ (page does not exist)">3E+</a>
</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="User:+%" title="User:+%">User:+%</a> <a rel="mw:WikiLink" href="Page+title%" title="Page+title%">Page+title%</a> <a rel="mw:WikiLink" href="%+" title="%+">%+</a> <a rel="mw:WikiLink" href="%+" title="%+">%20</a> <a rel="mw:WikiLink" href="%+" title="%+">%+ </a> <a rel="mw:WikiLink" href="%+r" title="%+r">%+r</a> <a rel="mw:WikiLink" href="%" title="%">%</a> <a rel="mw:WikiLink" href="+" title="+">+</a> <span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"[[bar]]"}'><a href="./File:%+abc9"><img resource="./File:%25+abc9" src="./Special:FilePath/%+abc9" height="220" width="220"/></a></span> <a rel="mw:WikiLink" href="3E" title="3E">3E</a> <a rel="mw:WikiLink" href="3E+" title="3E+">3E+</a></p>
!! end
!! test
@@ -18185,13 +19376,15 @@ Special characters in embedded file links (bug 27679)
!! wikitext
[[File:Contains & ampersand.jpg]]
[[File:Does not exist.jpg|Title with & ampersand]]
-!! html
+!! html/php
<p><a href="/index.php?title=Special:Upload&amp;wpDestFile=Contains_%26_ampersand.jpg" class="new" title="File:Contains &amp; ampersand.jpg">File:Contains &amp; ampersand.jpg</a>
<a href="/index.php?title=Special:Upload&amp;wpDestFile=Does_not_exist.jpg" class="new" title="File:Does not exist.jpg">Title with &amp; ampersand</a>
</p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:Contains_&amp;_ampersand.jpg"><img resource="./File:Contains_&amp;_ampersand.jpg" src="./Special:FilePath/Contains_&amp;_ampersand.jpg" height="220" width="220"/></a></span>
+<span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}],"caption":"Title with &amp; ampersand"}'><a href="./File:Does_not_exist.jpg"><img resource="./File:Does_not_exist.jpg" src="./Special:FilePath/Does_not_exist.jpg" height="220" width="220"/></a></span></p>
!! end
-
!! test
Confirm that 'apos' named character reference doesn't make it to output (not legal in HTML 4)
!! wikitext
@@ -18383,6 +19576,7 @@ __TOC__
<h2><span class="mw-headline" id="Quote"><blockquote>Quote</blockquote></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&amp;action=edit&amp;section=1" title="Edit section: Quote">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
!! html+tidy
+<p></p>
<div id="toc" class="toc">
<div id="toctitle">
<h2>Contents</h2>
@@ -18391,6 +19585,7 @@ __TOC__
<li class="toclevel-1 tocsection-1"><a href="#Quote"><span class="tocnumber">1</span> <span class="toctext">Quote</span></a></li>
</ul>
</div>
+<p></p>
<h2><span class="mw-headline" id="Quote"></span></h2>
<blockquote>
<p><span class="mw-headline" id="Quote">Quote</span></p>
@@ -18439,6 +19634,7 @@ __TOC__
<h2><span class="mw-headline" id="Foo_Bar_2"><i>Foo</i> <blockquote>Bar</blockquote></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
!! html+tidy
+<p></p>
<div id="toc" class="toc">
<div id="toctitle">
<h2>Contents</h2>
@@ -18448,6 +19644,7 @@ __TOC__
<li class="toclevel-1 tocsection-2"><a href="#Foo_Bar_2"><span class="tocnumber">2</span> <span class="toctext"><i>Foo</i> Bar</span></a></li>
</ul>
</div>
+<p></p>
<h2><span class="mw-headline" id="Foo_Bar"><i>Foo</i> <b>Bar</b></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
<h2><span class="mw-headline" id="Foo_Bar_2"><i>Foo</i></span></h2>
<blockquote>
@@ -18508,6 +19705,53 @@ __TOC__
!! end
+!! test
+Bug 72884: bdi element in ToC
+!! wikitext
+__TOC__
+== <bdi>test</bdi> ==
+!! html
+<div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#test"><span class="tocnumber">1</span> <span class="toctext"><bdi>test</bdi></span></a></li>
+</ul>
+</div>
+
+<h2><span class="mw-headline" id="test"><bdi>test</bdi></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: test">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+
+!! end
+
+# Note that the html output does not have the <p></p>, but the
+# html+tidy output *does*. This is because the empty <p></p> is
+# removed by the sanitizer, but only when tidy is *not* enabled (!).
+!! test
+Empty <p> tag in TOC, removed by Sanitizer (T92892)
+!! wikitext
+__TOC__
+== x ==
+!! html
+<div id="toc" class="toc"><div id="toctitle"><h2>Contents</h2></div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#x"><span class="tocnumber">1</span> <span class="toctext">x</span></a></li>
+</ul>
+</div>
+
+<h2><span class="mw-headline" id="x">x</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: x">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+
+!! html+tidy
+<p></p>
+<div id="toc" class="toc">
+<div id="toctitle">
+<h2>Contents</h2>
+</div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#x"><span class="tocnumber">1</span> <span class="toctext">x</span></a></li>
+</ul>
+</div>
+<p></p>
+<h2><span class="mw-headline" id="x">x</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: x">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+!! end
+
!! article
MediaWiki:Bug32057
!! text
@@ -18677,7 +19921,7 @@ File:foobar.jpg|caption|alt=galleryalt|link=InterWikiLink
!! html
<ul class="gallery mw-gallery-traditional">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/InterWikiLink"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/InterWikiLink"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
<p>caption
</p>
@@ -18696,7 +19940,7 @@ File:foobar.jpg|caption|alt=galleryalt|link=http://www.example.org
!! html
<ul class="gallery mw-gallery-traditional">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="http://www.example.org"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="http://www.example.org"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
<p>caption
</p>
@@ -18715,7 +19959,7 @@ File:foobar.jpg|caption|alt=galleryalt|link=" onclick="alert('malicious javascri
!! html
<ul class="gallery mw-gallery-traditional">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/%22_onclick%3D%22alert(%27malicious_javascript_code!%27);"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/%22_onclick%3D%22alert(%27malicious_javascript_code!%27);"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
<p>caption
</p>
@@ -18734,7 +19978,7 @@ File:foobar.jpg|link=<
!! html
<ul class="gallery mw-gallery-traditional">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
- <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+ <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
</div>
</div></li>
@@ -18858,13 +20102,13 @@ parsoid=wt2html,wt2wt
#### Parsoid-specific functionality tests
#### -----------------------------------------------------------------
-# Bug 63642: Formatting elt fixup is cleaned up.
+# Bug 63642/66749: Formatting elt fixup around images is cleaned up.
# We know wt2wt will fail, but we expect selser to pass.
# Due to the nature of our testing, wt2wt and selser tests will enter the
# blacklist and we'll catch selser regressions based on changes to the
# blacklist entries for selser tests.
!! test
-Bad treebuilder fixup of formatting elt is cleaned up
+1. Bad treebuilder fixup of formatting elt is cleaned up
!! options
parsoid=wt2html,wt2wt
!! wikitext
@@ -18877,12 +20121,28 @@ parsoid=wt2html,wt2wt
!! html/parsoid
<table>
<tbody><tr><td>
-<p><small></small></p>
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption><small>Test</small></figcaption></figure>
-<p></p></td></tr>
+<small>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a><figcaption>Test</figcaption></figure>
+</small>
+</td></tr>
</tbody></table>
!! end
+!! test
+2. Bad treebuilder fixup of formatting elt is cleaned up
+!! options
+parsoid=wt2html,wt2wt
+!! wikitext
+'''foo[[File:Foobar.jpg|thumb|caption]]bar'''
+
+<small>[[Image:Foobar.jpg|right|300px]]</small>
+!! html/parsoid
+<p><b>foo</b></p>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption><b>caption</b></figcaption></figure>
+<p><b>bar</b></p>
+<small><figure class="mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="34" width="300"/></a></figure></small>
+!! end
+
#### ----------------------------------------------------------------
#### Parsoid-only testing of Parsoid's impl of <ref> and <references>
#### tags. Parsoid's output for these tags differs from that of the
@@ -18897,10 +20157,16 @@ parsoid
A <ref>foo</ref>
B <ref name="x">foo</ref>
C <ref name="y" />
+<references />
!! html
-<p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span>
-B <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"name":"x"}}' id="cite_ref-x-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-2">[2]</a></span>
-C <span about="#mwt3" class="reference" data-mw='{"name":"ref","attrs":{"name":"y"}}' id="cite_ref-y-3-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-y-3">[3]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span>
+B <span about="#mwt4" class="reference" id="cite_ref-x_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-2"},"attrs":{"name":"x"}}'><a href="#cite_note-x-2">[2]</a></span>
+C <span about="#mwt6" class="reference" id="cite_ref-y_3-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"y"}}'><a href="#cite_note-y-3">[3]</a></span></p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-x-2" id="cite_note-x-2"><span rel="mw:referencedBy"><a href="#cite_ref-x_2-0">↑</a></span> <span id="mw-reference-text-cite_note-x-2" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-y-3" id="cite_note-y-3"><span rel="mw:referencedBy"><a href="#cite_ref-y_3-0">↑</a></span> <span id="mw-reference-text-cite_note-y-3" class="mw-reference-text"></span></li>
+</ol>
!!end
!!test
@@ -18910,9 +20176,13 @@ parsoid
!! wikitext
A <ref name="x">foo</ref>
B <ref name="x" />
+<references />
!! html
-<p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"name":"x"}}' id="cite_ref-x-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-1">[1]</a></span>
-B <span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{"name":"x"}}' id="cite_ref-x-1-1" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-1">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-x_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-1"},"attrs":{"name":"x"}}'><a href="#cite_note-x-1">[1]</a></span>
+B <span about="#mwt4" class="reference" id="cite_ref-x_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="#cite_note-x-1">[1]</a></span></p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-x-1" id="cite_note-x-1"><span rel="mw:referencedBy">↑ <a href="#cite_ref-x_1-0">1.0</a> <a href="#cite_ref-x_1-1">1.1</a></span> <span id="mw-reference-text-cite_note-x-1" class="mw-reference-text">foo</span></li>
+</ol>
!!end
!!test
@@ -18923,21 +20193,29 @@ parsoid
A <ref name="x">foo</ref>
B <ref name=" x " />
C <ref name= x />
+<references />
!! html
-<p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"name":"x"}}' id="cite_ref-x-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-1">[1]</a></span>
-B <span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{"name":"x"}}' id="cite_ref-x-1-1" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-1">[1]</a></span>
-C <span about="#mwt3" class="reference" data-mw='{"name":"ref","attrs":{"name":"x"}}' id="cite_ref-x-1-2" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-x-1">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-x_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-1"},"attrs":{"name":"x"}}'><a href="#cite_note-x-1">[1]</a></span>
+B <span about="#mwt4" class="reference" id="cite_ref-x_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="#cite_note-x-1">[1]</a></span>
+C <span about="#mwt6" class="reference" id="cite_ref-x_1-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="#cite_note-x-1">[1]</a></span></p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-x-1" id="cite_note-x-1"><span rel="mw:referencedBy">↑ <a href="#cite_ref-x_1-0">1.0</a> <a href="#cite_ref-x_1-1">1.1</a> <a href="#cite_ref-x_1-2">1.2</a></span> <span id="mw-reference-text-cite_note-x-1" class="mw-reference-text">foo</span></li>
+</ol>
!!end
+# NOTE: constructor is a predefined property in JS and constructor as a ref-name can clash with it if not handled properly)
!!test
Ref: 4. 'constructor' should be accepted as a valid ref-name
-(NOTE: constructor is a predefined property in JS and constructor as a ref-name can clash with it if not handled properly)
!!options
parsoid
!! wikitext
A <ref name="constructor">foo</ref>
+<references />
!! html
-<p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"name":"constructor"}}' id="cite_ref-constructor-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-constructor-1">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-constructor_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-constructor-1"},"attrs":{"name":"constructor"}}'><a href="#cite_note-constructor-1">[1]</a></span></p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-constructor-1" id="cite_note-constructor-1"><span rel="mw:referencedBy"><a href="#cite_ref-constructor_1-0">↑</a></span> <span id="mw-reference-text-cite_note-constructor-1" class="mw-reference-text">foo</span></li>
+</ol>
!!end
!!test
@@ -18951,11 +20229,11 @@ A <ref>
<references />
!! html
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"This is a &lt;b data-parsoid=&#39;{\"dsr\":[19,40,3,3]}&#39;>&lt;a rel=\"mw:WikiLink\" href=\"./Bolded_link\" title=\"Bolded link\" data-parsoid=&#39;{\"stx\":\"simple\",\"a\":{\"href\":\"./Bolded_link\"},\"sa\":{\"href\":\"bolded link\"},\"dsr\":[22,37,2,2]}&#39;>bolded link&lt;/a>&lt;/b> and this is a &lt;span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"transclusion\"}},\"i\":0}}]}&#39; data-parsoid=&#39;{\"pi\":[[{\"k\":\"1\",\"spc\":[\"\",\"\",\"\",\"\"]}]],\"dsr\":[55,76,null,null]}&#39;>transclusion&lt;/span>\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span></p>
-<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> This is a <b><a rel="mw:WikiLink" href="./Bolded_link" title="Bolded link">bolded link</a></b> and this is a <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
-</li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">This is a <b><a rel="mw:WikiLink" href="Bolded_link" title="Bolded link">bolded link</a></b> and this is a <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
+</span></li>
</ol>
!!end
@@ -18972,13 +20250,13 @@ A <ref>
<references />
!! html
-<p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo\n bar\n baz\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span></p>
-<ol class="references" typeof="mw:Extension/references" about="#mwt3" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo
bar
baz
-</li>
+</span></li>
</ol>
!!end
@@ -19002,10 +20280,10 @@ booz
<references />
!! html
-<p>A <span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo\n\nbar\n\n\nbaz\n\n\n\nbooz\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span></p>
-<ol about="#mwt2" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo
bar
@@ -19015,7 +20293,7 @@ baz
booz
-</li>
+</span></li>
</ol>
!!end
@@ -19028,9 +20306,9 @@ A <ref> foo {{echo|</ref> B C}}
<references />
!! html
-<p>A <span class="reference" data-mw="{&quot;name&quot;:&quot;ref&quot;,&quot;body&quot;:{&quot;html&quot;:&quot;foo <span typeof=\&quot;mw:Nowiki\&quot; data-parsoid='{\&quot;src\&quot;:\&quot;{{\&quot;,\&quot;dsr\&quot;:[12,14,0,0]}'>{{</span>echo|&quot;},&quot;attrs&quot;:{}}" id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> B C<span typeof="mw:Nowiki">}}</span></p>
-<ol class="references" typeof="mw:Extension/references" data-mw="{&quot;name&quot;:&quot;references&quot;,&quot;attrs&quot;:{}}">
-<li id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo <span typeof="mw:Nowiki">{{</span>echo|</li>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span> B C<span typeof="mw:Nowiki">}}</span></p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo <span typeof="mw:Nowiki" data-parsoid='{"src":"{{","dsr":[12,14,0,0]}'>{{</span>echo|</span></li>
</ol>
!!end
@@ -19042,9 +20320,9 @@ parsoid
A <ref> foo <!--</ref> B C
<references />
!! html
-<p>A <span class="reference" data-mw='{"name":"ref","body":{"html":"foo &lt;!---->"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> B C</p>
-<ol class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'>
-<li id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo </li>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span> B C</p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo <!----></span></li>
</ol>
!!end
@@ -19057,11 +20335,11 @@ A <ref> <b> foo </ref> B C
<references />
!! html
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"&lt;b data-parsoid=&#39;{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[8,16,3,0]}&#39;> foo &lt;/b>"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref> &lt;b> foo &lt;/ref>"}'><a href="#cite_note-1">[1]</a></span> B C</p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span> B C</p>
-<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> <b data-parsoid='{"stx":"html","autoInsertedEnd":true}'> foo </b></li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"><b data-parsoid='{"stx":"html","autoInsertedEnd":true}'> foo </b></span></li>
</ol>
!!end
@@ -19072,9 +20350,14 @@ parsoid
!! wikitext
A <ref>foo</ref> B
C <ref>bar</ref> D
+<references />
!! html
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo&lt;/ref>"}'><a href="#cite_note-1">[1]</a></span> B
-C <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>bar&lt;/ref>"}'><a href="#cite_note-2">[2]</a></span> D</p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span> B
+C <span about="#mwt4" class="reference" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="#cite_note-2">[2]</a></span> D</p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2">↑</a></span> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
+</ol>
!!end
!!test
@@ -19088,15 +20371,18 @@ b<!--the newline at the end of this line stays inside the p-tag--> <ref />
<ref />
c
+<references />
!! html
<p><!--the newline at the end of this line moves out of the p-tag-->a</p>
-<p>b<!--the newline at the end of this line stays inside the p-tag--> <span about="#mwt1" class="reference" data-mw='{"name":"ref","attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span>
-<span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-2">[2]</a></span></p>
-
+<p>b<!--the newline at the end of this line stays inside the p-tag--> <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{}}'><a href="#cite_note-1">[1]</a></span>
+<span about="#mwt4" class="reference" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{}}'><a href="#cite_note-2">[2]</a></span></p>
<p>c</p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"></span></li>
+<li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2">↑</a></span> <span id="mw-reference-text-cite_note-2" class="mw-reference-text"></span></li></ol>
!!end
!!test
@@ -19107,9 +20393,15 @@ parsoid
<ref>foo</ref> A
<ref>bar
</ref> B
+<references />
!! html
-<p><span about="#mwt1" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> A
-<span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"bar\n"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-2">[2]</a></span> B</p>
+<p><span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span> A
+<span about="#mwt4" class="reference" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="#cite_note-2">[2]</a></span> B</p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2">↑</a></span> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar
+</span></li>
+</ol>
!!end
!!test
@@ -19121,10 +20413,10 @@ parsoid
<references />
!! html
-<p><span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo &amp;lt;ref>bar&amp;lt;/ref> baz"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo &lt;ref>bar&lt;/ref> baz&lt;/ref>"}'><a href="#cite_note-1">[1]</a></span></p>
-
-<ol class="references" typeof="mw:Extension/references" about="#mwt5" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo &lt;ref>bar&lt;/ref> baz</li>
+<p><span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span>
+</p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo &lt;ref>bar&lt;/ref> baz</span></li>
</ol>
!!end
@@ -19138,10 +20430,10 @@ B1 <ref name="b" /> B2 <ref name="b">bar</ref>
<references />
!! html
-<p>A1 <span about="#mwt3" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"name":"a"}}' id="cite_ref-a-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-a-1">[1]</a></span> A2 <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"name":"a"}}' id="cite_ref-a-1-1" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-a-1">[1]</a></span>
-B1 <span about="#mwt7" class="reference" data-mw='{"name":"ref","attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-b-2">[2]</a></span> B2 <span about="#mwt8" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"name":"b"}}' id="cite_ref-b-2-1" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-b-2">[2]</a></span></p>
+<p>A1 <span about="#mwt3" class="reference" id="cite_ref-a_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a-1"},"attrs":{"name":"a"}}'><a href="#cite_note-a-1">[1]</a></span> A2 <span about="#mwt4" class="reference" id="cite_ref-a_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a"}}'><a href="#cite_note-a-1">[1]</a></span>
+B1 <span about="#mwt7" class="reference" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"b"}}'><a href="#cite_note-b-2">[2]</a></span> B2 <span about="#mwt8" class="reference" id="cite_ref-b_2-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-b-2"},"attrs":{"name":"b"}}'><a href="#cite_note-b-2">[2]</a></span></p>
-<ol about="#mwt10" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-a-1" id="cite_note-a-1"><span rel="mw:referencedBy">↑ <a href="#cite_ref-a-1-0">1.0</a> <a href="#cite_ref-a-1-1">1.1</a></span> foo</li><li about="#cite_note-b-2" id="cite_note-b-2"><span rel="mw:referencedBy">↑ <a href="#cite_ref-b-2-0">2.0</a> <a href="#cite_ref-b-2-1">2.1</a></span> bar</li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-a-1" id="cite_note-a-1"><span rel="mw:referencedBy">↑ <a href="#cite_ref-a_1-0">1.0</a> <a href="#cite_ref-a_1-1">1.1</a></span> <span id="mw-reference-text-cite_note-a-1" class="mw-reference-text">foo</span></li><li about="#cite_note-b-2" id="cite_note-b-2"><span rel="mw:referencedBy">↑ <a href="#cite_ref-b_2-0">2.0</a> <a href="#cite_ref-b_2-1">2.1</a></span> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">bar</span></li>
</ol>
!!end
@@ -19155,10 +20447,78 @@ A <ref >foo</ref >
<references />
!! html
-<p>A <span class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span></p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
+!!end
+
+!!test
+Ref: 17. Generate valid HTML5 id/about attributes
+!!options
+parsoid
+!!wikitext
+<ref name="a b">foo</ref>
+
+<references />
+!!html
+<p><span class="reference" id="cite_ref-a_b_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a_b-1"},"attrs":{"name":"a b"}}'><a href="#cite_note-a_b-1">[1]</a></span>
+</p>
+
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-a_b-1" id="cite_note-a_b-1"><span rel="mw:referencedBy"><a href="#cite_ref-a_b_1-0">↑</a></span> <span id="mw-reference-text-cite_note-a_b-1" class="mw-reference-text">foo</span></li>
+</ol>
+!!end
+
+!!test
+Ref: 18. T58916: Extension attributes should be parsed as plain text
+!!options
+parsoid
+!!wikitext
+<ref name="{{echo|a}}">foo</ref>
+
+<references />
+!!html
+<p><span class="reference" id="cite_ref-.7B.7Becho.7Ca.7D.7D_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-.7B.7Becho.7Ca.7D.7D-1"},"attrs":{"name":"{{echo|a}}"}}'><a href="#cite_note-.7B.7Becho.7Ca.7D.7D-1">[1]</a></span>
+</p>
+
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-.7B.7Becho.7Ca.7D.7D-1" id="cite_note-.7B.7Becho.7Ca.7D.7D-1"><span rel="mw:referencedBy"><a href="#cite_ref-.7B.7Becho.7Ca.7D.7D_1-0">↑</a></span> <span id="mw-reference-text-cite_note-.7B.7Becho.7Ca.7D.7D-1" class="mw-reference-text">foo</span></li>
+</ol>
+!!end
+
+!!test
+Ref: 19. ref-tags with identical name encodings should get identical indexes
+!!options
+parsoid
+!! wikitext
+1 <ref name="a & b">foo</ref> 2 <ref name="a &amp; b" />
+
+<references />
+!! html
+<p>1 <span about="#mwt3" class="reference" id="cite_ref-a_.26_b_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a_.26_b-1"},"attrs":{"name":"a &amp; b"}}'><a href="#cite_note-a_.26_b-1">[1]</a></span> 2 <span about="#mwt4" class="reference" id="cite_ref-a_.26_b_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a &amp;amp; b"}}'><a href="#cite_note-a_.26_b-1">[1]</a></span>
+</p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-a_.26_b-1" id="cite_note-a_.26_b-1"><span rel="mw:referencedBy">↑ <a href="#cite_ref-a_.26_b_1-0">1.0</a> <a href="#cite_ref-a_.26_b_1-1">1.1</a></span> <span id="mw-reference-text-cite_note-a_.26_b-1" class="mw-reference-text">foo</span></li>
+</ol>
+!!end
-<ol class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'>
-<li id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo</li></ol>
+!!test
+Ref: 20. ref-tags with identical names but different content should keep it
+!!options
+parsoid
+!! wikitext
+A <ref name="foo">Foo one</ref>
+B <ref name="foo">Foo two</ref>
+C <ref name="foo" />
+
+<references />
+!! html
+<p>A <span about="#mwt2" class="reference" id="cite_ref-foo_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-foo-1"},"attrs":{"name":"foo"}}'><a href="#cite_note-foo-1">[1]</a></span>
+B <span about="#mwt4" class="reference" id="cite_ref-foo_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"html":"Foo two"},"attrs":{"name":"foo"}}'><a href="#cite_note-foo-1">[1]</a></span>
+C <span about="#mwt6" class="reference" id="cite_ref-foo_1-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"foo"}}'><a href="#cite_note-foo-1">[1]</a></span></p>
+
+<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-foo-1" id="cite_note-foo-1"><span rel="mw:referencedBy">↑ <a href="#cite_ref-foo_1-0">1.0</a> <a href="#cite_ref-foo_1-1">1.1</a> <a href="#cite_ref-foo_1-2">1.2</a></span> <span id="mw-reference-text-cite_note-foo-1" class="mw-reference-text">Foo one</span></li>
+</ol>
!!end
!!test
@@ -19168,7 +20528,7 @@ parsoid
!! wikitext
<references />
!! html
-<ol about="#mwt2" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'></ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt2" data-mw='{"name":"references","attrs":{}}'></ol>
!!end
!!test
@@ -19178,13 +20538,24 @@ parsoid
!! wikitext
A <ref group="a">foo</ref>
B <ref group="b">bar</ref>
+C <ref>baz</ref>
<references group="a" />
+<references />
+<references group="b" />
!! html
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"group":"a"}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[a 1]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"group":"b"}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-2">[b 1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"a"}}'><a href="#cite_note-1">[a 1]</a></span>
+B <span about="#mwt4" class="reference" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{"group":"b"}}'><a href="#cite_note-2">[b 1]</a></span>
+C <span class="reference" id="cite_ref-3" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-3"},"attrs":{}}'><a href="#cite_note-3">[1]</a></span></p>
-<ol about="#mwt6" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{"group":"a"}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo</li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{"group":"a"}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
+</ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-3" id="cite_note-3"><span rel="mw:referencedBy"><a href="#cite_ref-3">↑</a></span> <span id="mw-reference-text-cite_note-3" class="mw-reference-text">baz</span></li>
+</ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt12" data-mw='{"name":"references","attrs":{"group":"b"}}'>
+<li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2">↑</a></span> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
</ol>
!!end
@@ -19201,14 +20572,15 @@ B <ref>bar</ref>
<references />
!! html
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span></p>
-<ol about="#mwt4" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo</li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
</ol>
-<p>B <span about="#mwt6" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-2">[1]</a></span></p>
+<p>B <span about="#mwt6" class="reference" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="#cite_note-2">[1]</a></span></p>
-<ol about="#mwt8" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2-0">↑</a></span> bar</li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2">↑</a></span> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
</ol>
!!end
@@ -19226,15 +20598,15 @@ C <ref>cfoo</ref>
<references />
!! html
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"afoo"},"attrs":{"group":"a"}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[a 1]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bfoo"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"<ref>bfoo</ref>"}'><a href="#cite_note-2">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"a"}}'><a href="#cite_note-1">[a 1]</a></span>
+B <span about="#mwt4" class="reference" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="#cite_note-2">[1]</a></span></p>
-<ol about="#mwt6" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{"group":"a"}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> afoo</li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{"group":"a"}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">afoo</span></li>
</ol>
-<p>C <span about="#mwt8" class="reference" data-mw='{"name":"ref","body":{"html":"cfoo"},"attrs":{}}' id="cite_ref-3-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-3">[2]</a></span></p>
+<p>C <span about="#mwt8" class="reference" id="cite_ref-3" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-3"},"attrs":{}}'><a href="#cite_note-3">[2]</a></span></p>
-<ol about="#mwt10" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2-0">↑</a></span> bfoo</li><li about="#cite_note-3" id="cite_note-3"><span rel="mw:referencedBy"><a href="#cite_ref-3-0">↑</a></span> cfoo</li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2">↑</a></span> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bfoo</span></li><li about="#cite_note-3" id="cite_note-3"><span rel="mw:referencedBy"><a href="#cite_ref-3">↑</a></span> <span id="mw-reference-text-cite_note-3" class="mw-reference-text">cfoo</span></li>
</ol>
!!end
@@ -19251,13 +20623,11 @@ B <ref name="b">bar</ref>
This should just get lost.
</references>
!! html
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{"name":"a"}}' id="cite_ref-a-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"a\" />"}'><a href="#cite_note-a-1">[1]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\">bar&lt;/ref>"}'><a href="#cite_note-b-2">[2]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-a_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a"}}'><a href="#cite_note-a-1">[1]</a></span>
+B <span about="#mwt4" class="reference" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-b-2"},"attrs":{"name":"b"}}'><a href="#cite_note-b-2">[2]</a></span></p>
-<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references>\n&lt;ref name=\"a\">foo&lt;/ref>\nThis should just get lost.\n&lt;/references>"}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"a\">foo&lt;/ref>\nThis should just get lost.","html":"\n&lt;span about=\"#mwt8\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"a\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-a-1\">[1]&lt;/a>&lt;/span>\n"},"attrs":{}}'>
-<li about="#cite_note-a-1" id="cite_note-a-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-a-1-0">↑</a></span> foo</li>
-<li about="#cite_note-b-2" id="cite_note-b-2" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-b-2-0">↑</a></span> bar</li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"a\">foo&lt;/ref>\nThis should just get lost.","html":"\n&lt;span about=\"#mwt8\" class=\"reference\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[59,82,14,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-a-1\"},\"attrs\":{\"name\":\"a\"}}&#39;>&lt;a href=\"#cite_note-a-1\">[1]&lt;/a>&lt;/span>\n"},"attrs":{}}'><li about="#cite_note-a-1" id="cite_note-a-1"><span rel="mw:referencedBy"><a href="#cite_ref-a_1-0">↑</a></span> <span id="mw-reference-text-cite_note-a-1" class="mw-reference-text">foo</span></li><li about="#cite_note-b-2" id="cite_note-b-2"><span rel="mw:referencedBy"><a href="#cite_ref-b_2-0">↑</a></span> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">bar</span></li>
</ol>
!!end
@@ -19268,7 +20638,8 @@ parsoid
!! wikitext
<ref>Foo</ref> {{echo|<references />}}
!! html
-<span about="#mwt3" class="reference" data-mw='{"name":"ref","body":{"html":"Foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span> <ol class="references" typeof="mw:Extension/references mw:Transclusion" about="#mwt4" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;references />"}},"i":0}}]}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> Foo</li></ol>
+<p><span about="#mwt3" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span></p> <ol class="references" typeof="mw:Extension/references mw:Transclusion" about="#mwt4" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;references />"}},"i":0}}]}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">Foo</span></li>
+</ol>
!!end
!! test
@@ -19285,22 +20656,81 @@ B <ref group="X" name="b" />
<ref name="b">foo</ref>
</references>
!! html
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo bar for a"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo bar for a&lt;/ref>"}'><a href="#cite_note-1" data-parsoid="{}">[1]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"group":"X","name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref group=\"X\" name=\"b\" />"}'><a href="#cite_note-b-2" data-parsoid="{}">[X 1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span>
+B <span about="#mwt4" class="reference" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"group":"X","name":"b"}}'><a href="#cite_note-b-2">[X 1]</a></span>
+</p>
-<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-1-0" data-parsoid="{}">↑</a></span> foo bar for a</li></ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo bar for a</span></li>
+</ol>
-<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-parsoid='{"src":"&lt;references group=\"X\">\n&lt;ref name=\"b\">foo&lt;/ref>\n&lt;/references>","group":"X"}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"b\">foo&lt;/ref>","html":"\n&lt;span about=\"#mwt10\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"b\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-b-2\">[X 1]&lt;/a>&lt;/span>\n"},"attrs":{"group":"X"}}'><li about="#cite_note-b-2" id="cite_note-b-2" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-b-2-0" data-parsoid="{}">↑</a></span> foo</li></ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"b\">foo&lt;/ref>","html":"\n&lt;span about=\"#mwt10\" class=\"reference\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[96,119,14,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-b-2\"},\"attrs\":{\"name\":\"b\"}}&#39;>&lt;a href=\"#cite_note-b-2\">[X 1]&lt;/a>&lt;/span>\n"},"attrs":{"group":"X"}}'>
+<li about="#cite_note-b-2" id="cite_note-b-2"><span rel="mw:referencedBy"><a href="#cite_ref-b_2-0">↑</a></span> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">foo</span></li>
+</ol>
!! end
!! test
+References: 8. T88019: Remove <meta>s from templates inside <ref> that's itself inside a template
+!! options
+parsoid
+!! wikitext
+X{{echo|<ref>foo {{echo|<b>bar</b>}} and {{echo|baz}} boo</ref>}}
+<references />
+!! html
+<p>X<span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;ref>foo {{echo|&lt;b>bar&lt;/b>}} and {{echo|baz}} boo&lt;/ref>"}},"i":0}}]}'><a href="#cite_note-1">[1]</a></span></p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt7" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo <b data-parsoid='{"stx":"html"}'>bar</b> and baz boo</span></li>
+</ol>
+!!end
+
+# This test only works in wt2html now as the <references /> are always generated
+# unless selser is active. Once T72722 is fixed, we should add a changes test
+# here to ensure that unrelated changes don't add the new <references /> in
+# wt2wt.
+!! test
+References: 9. Generate missing references list at the end
+!! options
+parsoid
+!! wikitext
+A <ref>foo</ref>
+B <ref group="inexistent">bar</ref>
+!! html
+<p>A <span class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span> B <span class="reference" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{"group":"inexistent"}}'><a href="#cite_note-2">[inexistent 1]</a></span></p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
+</ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{"group":"inexistent"}}'>
+<li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2">↑</a></span> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
+</ol>
+!! end
+
+!! test
+References: 10. New <references/> shouldn't be added for unrelated edits.
+!! options
+parsoid={
+ "modes": ["selser"],
+ "changes": [["#x", "remove"]],
+ "selser": "noauto"
+}
+!! wikitext
+Unrelated text<span id="x"> that's going to disappear</span>.
+A <ref>foo</ref>
+!! wikitext/edited
+Unrelated text.
+A <ref>foo</ref>
+!!end
+
+!! test
Entities in ref name
!! options
parsoid
!! wikitext
<ref name="test &amp; me">hi</ref>
+<references />
!! html
-<p data-parsoid='{}'><span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"hi"},"attrs":{"name":"test &amp; me"}}' id="cite_ref-test &amp; me-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"test &amp;amp; me\">hi&lt;/ref>"}'><a href="#cite_note-test &amp; me-1" data-parsoid="{}">[1]</a></span></p>
+<p><span about="#mwt2" class="reference" id="cite_ref-test_.26_me_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-test_.26_me-1"},"attrs":{"name":"test &amp;amp; me"}}'><a href="#cite_note-test_.26_me-1">[1]</a></span></p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-test_.26_me-1" id="cite_note-test_.26_me-1"><span rel="mw:referencedBy"><a href="#cite_ref-test_.26_me_1-0">↑</a></span> <span id="mw-reference-text-cite_note-test_.26_me-1" class="mw-reference-text">hi</span></li>
+</ol>
!! end
# This test is wt2html only because we're permitting the serializer to produce
@@ -19314,11 +20744,9 @@ a<ref>foo</ref>
<references>
!! html
-<p data-parsoid='{}'>a<span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo&lt;/ref>"}'><a href="#cite_note-1" data-parsoid="{}">[1]</a></span></p>
-
-
-<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-parsoid='{"src":"&lt;references>"}' data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-1-0" data-parsoid="{}">↑</a></span> foo</li></ol>
+<p>a<span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span></p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
!! end
!! test
@@ -19333,6 +20761,85 @@ foo<ol class="references" typeof="mw:Extension/references" about="#mwt2" data-mw
!! end
#### ----------------------------------------------------------------
+#### Parsoid-only testing of Parsoid's impl of LST
+#### Not implemented yet, see
+#### https://www.mediawiki.org/wiki/Parsoid/HTML_based_LST
+#### ----------------------------------------------------------------
+
+!!test
+LST Sections: 1. Simple section start and end
+!! wikitext
+<section begin="2011-05-16" />
+<section end="2014-04-10 (MW 1.23wmf22)" />
+!! html/parsoid
+<p><meta typeof="mw:Extension/LabeledSectionTransclusion/begin" content="2011-05-16"/>
+<meta typeof="mw:Extension/LabeledSectionTransclusion/end" content="2014-04-10 (MW 1.23wmf22)"/></p>
+!! end
+
+#--------- Test stripping of empty nodes in template content ----------
+!!test
+Empty LI and TR nodes should be stripped from template content
+!!wikitext
+{{EmptyLITest}}
+{{EmptyTRTest}}
+!!html/parsoid
+<ul about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"EmptyLITest","href":"./Template:EmptyLITest"},"params":{},"i":0}}]}'>
+<li>a</li>
+<li>b</li>
+</ul>
+<table about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"EmptyTRTest","href":"./Template:EmptyTRTest"},"params":{},"i":0}}]}'>
+<tbody>
+<tr>
+<td>foo</td>
+</tr>
+<tr>
+<td>bar</td>
+</tr>
+</tbody>
+</table>
+!!end
+
+!!test
+Empty LI and TR nodes should not be stripped from top-level content
+!!wikitext
+* a
+*
+* b
+{|
+|-
+|-
+|foo
+|}
+!!html/parsoid
+<ul>
+<li> a</li>
+<li></li>
+<li> b</li>
+</ul>
+<table>
+<tbody>
+<tr></tr>
+<tr>
+<td>foo</td>
+</tr>
+</tbody>
+</table>
+!!end
+
+!!test
+Empty TR nodes should not be stripped if they have any attributes set
+!!wikitext
+{{EmptyTRWithHTMLAttrTest}}
+!!html/parsoid
+<table about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"EmptyTRWithHTMLAttrTest","href":"./Template:EmptyTRWithHTMLAttrTest"},"params":{},"i":0}}]}'>
+<tr align="center"></tr>
+<tr><td>foo</td></tr>
+<tr align="center"></tr>
+<tr><td>bar</td></tr>
+</table>
+!!end
+
+#### ----------------------------------------------------------------
#### The following section of tests are primarily to test
#### wikitext escaping capabilities of Parsoid. Given that
#### escaping can be done any number of ways, the wikitext (input)
@@ -19376,11 +20883,22 @@ parsoid
<p>=foo<i>a</i><span typeof="mw:Nowiki">=</span></p>
!!end
+# New headings and existing headings are handled differently
!! test
Headings: 1. Nested inside html
-(New headings and existing headings are handled differently)
!! options
parsoid=html2wt
+!! html
+<h1>=foo=</h1>
+<h2>=foo=</h2>
+<h3>=foo=</h3>
+
+<h1 data-parsoid=''>=foo=</h1>
+<h2 data-parsoid=''>=foo=</h2>
+<h3 data-parsoid=''>=foo=</h3>
+<h4 data-parsoid=''>=foo=</h4>
+<h5 data-parsoid=''>=foo=</h5>
+<h6 data-parsoid=''>=foo=</h6>
!! wikitext
= =foo= =
@@ -19395,23 +20913,16 @@ parsoid=html2wt
=====<nowiki>=foo=</nowiki>=====
======<nowiki>=foo=</nowiki>======
-!! html
-<h1>=foo=</h1>
-<h2>=foo=</h2>
-<h3>=foo=</h3>
-
-<h1 data-parsoid='{}'>=foo=</h1>
-<h2 data-parsoid='{}'>=foo=</h2>
-<h3 data-parsoid='{}'>=foo=</h3>
-<h4 data-parsoid='{}'>=foo=</h4>
-<h5 data-parsoid='{}'>=foo=</h5>
-<h6 data-parsoid='{}'>=foo=</h6>
!!end
!! test
Headings: 2. Outside heading nest on a single line <h1>foo</h1>*bar
!! options
parsoid=html2wt
+!! html
+<h1>foo</h1>*bar
+<h1>foo</h1>=bar
+<h1>foo</h1>=bar=
!! wikitext
= foo =
<nowiki>*</nowiki>bar
@@ -19421,26 +20932,20 @@ parsoid=html2wt
= foo =
<nowiki>=bar=</nowiki>
-!! html
-<h1>foo</h1>*bar
-<h1>foo</h1>=bar
-<h1>foo</h1>=bar=
!!end
!! test
Headings: 3. Nested inside html with wikitext split by html tags
!! options
-parsoid=html2wt
+parsoid=html2wt,wt2wt
!! wikitext
= ='''bold'''<nowiki>foo=</nowiki> =
-!! html
-<h1>=<b>bold</b><span typeof="mw:Nowiki">foo=</span></h1>
+!! html/parsoid
+<h1>=<b>bold</b>foo=</h1>
!!end
!! test
Headings: 4a. No escaping needed (testing just h1 and h2)
-!! options
-parsoid=html2wt
!! wikitext
= =foo =
@@ -19454,33 +20959,33 @@ parsoid=html2wt
== foo= ==
-= ''=''foo= =
+= = =
-= <nowiki>=</nowiki> =
-!! html
+= ''=''foo= =
+!! html/parsoid
<h1>=foo</h1>
<h1>foo=</h1>
<h1> =foo= </h1>
<h1>=foo= bar</h1>
<h2>=foo</h2>
<h2>foo=</h2>
+<h1>=</h1>
<h1><i>=</i>foo=</h1>
-<h1><span typeof="mw:Nowiki">=</span></h1>
!!end
!! test
Headings: 4b. No escaping needed (inside p-tags)
!! options
parsoid=html2wt
-!! wikitext
-===
-=foo= x
-=foo= <s></s>
!! html
<p>===
=foo= x
=foo= <s></s>
</p>
+!! wikitext
+===
+=foo= x
+=foo= <s></s>
!!end
!! test
@@ -19584,12 +21089,30 @@ parsoid
Headings: 6d. Heading chars in SOL context (No escaping needed)
!! options
parsoid=html2wt
-!! wikitext
-=a=<div>b</div>
!! html
=a=<div>b</div>
+!! wikitext
+=a=<div>b</div>
!!end
+!! test
+Headings: 7. Insert a newline between new content and headings
+!! options
+parsoid=html2wt
+!! html
+<h2>NEW</h2>
+<p>new</p>
+<h2 data-parsoid='{"dsr":[0,5,2,2]}'>A</h2>
+<p data-parsoid='{"dsr":[6,7,0,0]}'>a</p>
+!! wikitext
+== NEW ==
+new
+
+==A==
+a
+
+!! end
+
#### --------------- Lists ---------------
#### 0. Outside nests (*foo, etc.)
#### 1. Nested inside html <ul><li>*foo</li></ul>
@@ -19714,33 +21237,36 @@ Lists: 5. No unnecessary escapes
!! wikitext
* bar <span><nowiki>[[foo]]</nowiki></span>
-*=bar <span><nowiki>[[foo]]</nowiki></span>
+* =bar <span><nowiki>[[foo]]</nowiki></span>
-*[[bar <span><nowiki>[[foo]]</nowiki></span>
+* [[bar <span><nowiki>[[foo]]</nowiki></span>
-*]]bar <span><nowiki>[[foo]]</nowiki></span>
+* ]]bar <span><nowiki>[[foo]]</nowiki></span>
-*=bar <span>foo]]</span>=
+* =bar <span>foo]]</span>=
* <s></s>: a
+
+* ''* foo''
!! html
<ul><li> bar <span>[[foo]]</span></li></ul>
-<ul><li>=bar <span>[[foo]]</span></li></ul>
-<ul><li>[[bar <span>[[foo]]</span></li></ul>
-<ul><li>]]bar <span>[[foo]]</span></li></ul>
-<ul><li>=bar <span>foo]]</span>=</li></ul>
+<ul><li> =bar <span>[[foo]]</span></li></ul>
+<ul><li> [[bar <span>[[foo]]</span></li></ul>
+<ul><li> ]]bar <span>[[foo]]</span></li></ul>
+<ul><li> =bar <span>foo]]</span>=</li></ul>
<ul><li> <s></s>: a</li></ul>
+<ul><li> <i>* foo</i></li></ul>
!!end
!! test
Lists: 6. Escape bullets in SOL position
!! options
-parsoid
-!! wikitext
-<!--cmt--><nowiki>*foo</nowiki>
+parsoid=html2wt
!! html
-<p><!--cmt--><span typeof="mw:Nowiki">*foo</span></p>
+<p><!--cmt-->*foo</p>
+!! wikitext
+<!--cmt--><nowiki>*</nowiki>foo
!!end
!! test
@@ -19754,22 +21280,33 @@ a
</p>
!!end
+!! test
+Lists: 8. Escape colons only if not present in tags
+!! options
+parsoid=html2wt
+!! html
+<dl><dt>a:b<i>c:d</i></dt></dl>
+!! wikitext
+; <nowiki>a:b</nowiki>''c:d''
+!! end
+
#### --------------- HRs ---------------
#### 1. Single line
#### -----------------------------------
!! test
HRs: 1. Single line
-!! options
-parsoid
!! wikitext
----<nowiki>----</nowiki>
----=foo=
----*foo
-!! html
-<hr><span typeof="mw:Nowiki">----</span>
-<hr>=foo=
-<hr>*foo
+!! html+tidy
+<hr />
+<p>----</p>
+<hr />
+<p>=foo=</p>
+<hr />
+<p>*foo</p>
!! end
#### --------------- Tables ---------------
@@ -19833,127 +21370,196 @@ Tables: 1d. No escaping needed
Tables: 2a. Nested in td
!! options
parsoid=html2wt
+!! html/parsoid
+<table><tbody><tr>
+<td>foo|bar</td></tr>
+<tr><td>x<div>a|b</div></td>
+</tbody></table>
!! wikitext
{|
|<nowiki>foo|bar</nowiki>
|-
|x<div><nowiki>a|b</nowiki></div>
|}
-!! html
-<table><tbody><tr>
-<td>foo|bar</td></tr>
-<tr><td>x<div>a|b</div></td>
-</tbody></table>
+!! html/php+tidy
+<table>
+<tr>
+<td>foo|bar</td>
+</tr>
+<tr>
+<td>x
+<div>a|b</div>
+</td>
+</tr>
+</table>
!! end
!! test
Tables: 2b. Nested in td
!! options
-parsoid
+parsoid=html2wt
+!! html/parsoid
+<table><tbody><tr>
+<td>foo||bar</td>
+<td>a<i>b||c</i></td>
+<td>a<i><div>b||c</div></i></td>
+</tr></tbody></table>
!! wikitext
{|
|<nowiki>foo||bar</nowiki>
-|''it''<nowiki>foo||bar</nowiki>
+|a''<nowiki>b||c</nowiki>''
+|a''<div><nowiki>b||c</nowiki></div>''
|}
-!! html
-<table><tbody><tr>
-<td><span typeof="mw:Nowiki">foo||bar</span></td>
-<td><i>it</i><span typeof="mw:Nowiki">foo||bar</span></td></tr></tbody></table>
+!! html/php
+<table>
+<tr>
+<td>foo||bar
+</td>
+<td>a<i>b||c</i>
+</td>
+<td>a<i><div>b||c</div></i>
+</td></tr></table>
+
!! end
!! test
Tables: 2c. Nested in td -- no escaping needed
-!! options
-parsoid
!! wikitext
{|
+
|foo!!bar
|}
-!! html
-<table><tbody><tr><td>foo!!bar
-</td></tr></tbody></table>
+!! html/*
+<table>
+
+<tr>
+<td>foo!!bar
+</td></tr></table>
!! end
!! test
Tables: 3a. Nested in th
-!! options
-parsoid
!! wikitext
{|
+
!foo!bar
|}
-!! html
-<table><tbody><tr><th>foo!bar
-</th></tr></tbody></table>
+!! html/*
+<table>
+
+<tr>
+<th>foo!bar
+</th></tr></table>
!! end
!! test
Tables: 3b. Nested in th
!! options
-parsoid
+parsoid=html2wt
+!! html/parsoid
+<table><tbody>
+<tr><th>foo!!bar</th>
+<th><i>foo|bar</i></th>
+<th><i>foo!!bar</i></th>
+<th><i><span>foo!!bar</span></i></th>
+</tr></tbody></table>
!! wikitext
{|
!<nowiki>foo!!bar</nowiki>
+!''<nowiki>foo|bar</nowiki>''
+!''<nowiki>foo!!bar</nowiki>''
+!''<span><nowiki>foo!!bar</nowiki></span>''
|}
-!! html
+!! html/php
<table>
-<tbody><tr><th><span typeof="mw:Nowiki">foo!!bar</span></th></tr>
-</tbody></table>
+<tr>
+<th>foo!!bar
+</th>
+<th><i>foo|bar</i>
+</th>
+<th><i>foo!!bar</i>
+</th>
+<th><i><span>foo!!bar</span></i>
+</th></tr></table>
+
!! end
!! test
-Tables: 3c. Nested in th -- no escaping needed
+Tables: 3c. Nested in th
!! options
-parsoid
+parsoid=html2wt
+!! html/parsoid
+<table><tbody>
+<tr><th>foo||bar</th>
+<th><span typeof="mw:Nowiki">foo||bar</span></th>
+</tr></tbody></table>
!! wikitext
{|
!<nowiki>foo||bar</nowiki>
+!<nowiki>foo||bar</nowiki>
|}
-!! html
-<table><tbody><tr>
-<th><span typeof="mw:Nowiki">foo||bar</span></th></tr></tbody></table>
+!! html/php
+<table>
+<tr>
+<th>foo||bar
+</th>
+<th>foo||bar
+</th></tr></table>
+
!! end
!! test
Tables: 4a. Escape -
!! options
-parsoid
+parsoid=html2wt
+!! html/*
+<table>
+
+<tr>
+<th>-bar
+</th></tr>
+<tr>
+<td>-bar
+</td></tr></table>
+
!! wikitext
{|
+
!-bar
+
|-
|<nowiki>-bar</nowiki>
|}
-!! html
-<table><tbody>
-<tr><th>-bar</th></tr>
-<tr>
-<td><span typeof="mw:Nowiki">-bar</span></td></tr></tbody></table>
!! end
!! test
Tables: 4b. Escape +
!! options
-parsoid
+parsoid=html2wt
+!! html/*
+<table>
+
+<tr>
+<th>+bar
+</th></tr>
+<tr>
+<td>+bar
+</td></tr></table>
+
!! wikitext
{|
+
!+bar
+
|-
|<nowiki>+bar</nowiki>
|}
-!! html
-<table><tbody>
-<tr><th>+bar</th></tr>
-<tr>
-<td><span typeof="mw:Nowiki">+bar</span></td></tr></tbody></table>
!! end
!! test
Tables: 4c. No escaping needed
-!! options
-parsoid
!! wikitext
{|
|foo-bar
@@ -19970,7 +21576,31 @@ bar|baz
|x
<div>a|b</div>
|}
-!! html
+!! html/php
+<table>
+<tr>
+<td>foo-bar
+</td>
+<td>foo+bar
+</td></tr>
+<tr>
+<td><i>foo</i>-bar
+</td>
+<td><i>foo</i>+bar
+</td></tr>
+<tr>
+<td>foo
+<p>bar|baz
++bar
+-bar
+</p>
+</td></tr>
+<tr>
+<td>x
+<div>a|b</div>
+</td></tr></table>
+
+!! html/parsoid
<table><tbody>
<tr><td>foo-bar</td><td>foo+bar</td></tr>
<tr><td><i>foo</i>-bar</td><td><i>foo</i>+bar</td></tr>
@@ -19985,15 +21615,23 @@ bar|baz
!! test
Tables: 4d. No escaping needed
-!! options
-parsoid
!! wikitext
{|
|[[Foo]]-bar
||+1
||-2
|}
-!! html
+!! html/php
+<table>
+<tr>
+<td><a href="/wiki/Foo" title="Foo">Foo</a>-bar
+</td>
+<td>+1
+</td>
+<td>-2
+</td></tr></table>
+
+!! html/parsoid
<table>
<tbody><tr><td><a rel="mw:WikiLink" href="./Foo" title="Foo">Foo</a>-bar</td>
<td data-parsoid='{"startTagSrc":"|","attrSepSrc":"|"}'>+1</td>
@@ -20026,23 +21664,39 @@ parsoid=wt2html
#### 5. Extlinks: No escapes needed
#### --------------------------------------
!! test
-Links 1. Quote marks in link text
-!! options
-parsoid
+Links 1. WikiLinks: No escapes needed
!! wikitext
-[[Foo|Foo<nowiki>''boo''</nowiki>]]
-!! html
-<a rel="mw:WikiLink" href="Foo">Foo''boo''</a>
+[[Foo|Foo''boo'']]
+[[Foo|[Foobar]]]
+[[Foo|x [Foobar] x]]
+!! html/php
+<p><a href="/wiki/Foo" title="Foo">Foo<i>boo</i></a>
+<a href="/wiki/Foo" title="Foo">[Foobar]</a>
+<a href="/wiki/Foo" title="Foo">x [Foobar] x</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="Foo" title="Foo">Foo<i>boo</i></a>
+<a rel="mw:WikiLink" href="Foo" title="Foo">[Foobar]</a>
+<a rel="mw:WikiLink" href="Foo" title="Foo">x [Foobar] x</a></p>
!! end
!! test
Links 2. WikiLinks: Escapes needed
!! options
-parsoid
+parsoid=html2wt
+!! html/parsoid
+<a href="Foo" rel="mw:WikiLink">Foobar]</a>
+<a href="Foo" rel="mw:WikiLink">x [http://google.com g] x</a>
+<a href="Foo" rel="mw:WikiLink">[[Bar]]</a>
+<a href="Foo" rel="mw:WikiLink">x [[Bar]] x</a>
+<a href="Foo" rel="mw:WikiLink">|Bar</a>
+<a href="Foo" rel="mw:WikiLink">]]bar</a>
+<a href="Foo" rel="mw:WikiLink">[[bar</a>
+<a href="Foo" rel="mw:WikiLink">x [[ y</a>
+<a href="Foo" rel="mw:WikiLink">x ]] y</a>
+<a href="Foo" rel="mw:WikiLink">x ]] y [[ z</a>
!! wikitext
-[[Foo|[Foobar]]]
[[Foo|<nowiki>Foobar]</nowiki>]]
-[[Foo|x [Foobar] x]]
[[Foo|x <nowiki>[http://google.com g]</nowiki> x]]
[[Foo|<nowiki>[[Bar]]</nowiki>]]
[[Foo|<nowiki>x [[Bar]] x</nowiki>]]
@@ -20052,37 +21706,43 @@ parsoid
[[Foo|<nowiki>x [[ y</nowiki>]]
[[Foo|<nowiki>x ]] y</nowiki>]]
[[Foo|<nowiki>x ]] y [[ z</nowiki>]]
-!! html
-<a href="Foo" rel="mw:WikiLink">[Foobar]</a>
-<a href="Foo" rel="mw:WikiLink">Foobar]</a>
-<a href="Foo" rel="mw:WikiLink">x [Foobar] x</a>
-<a href="Foo" rel="mw:WikiLink">x [http://google.com g] x</a>
-<a href="Foo" rel="mw:WikiLink">[[Bar]]</a>
-<a href="Foo" rel="mw:WikiLink">x [[Bar]] x</a>
-<a href="Foo" rel="mw:WikiLink">|Bar</a>
-<a href="Foo" rel="mw:WikiLink">]]bar</a>
-<a href="Foo" rel="mw:WikiLink">[[bar</a>
-<a href="Foo" rel="mw:WikiLink">x [[ y</a>
-<a href="Foo" rel="mw:WikiLink">x ]] y</a>
-<a href="Foo" rel="mw:WikiLink">x ]] y [[ z</a>
+!! html/php
+<p><a href="/wiki/Foo" title="Foo">Foobar]</a>
+<a href="/wiki/Foo" title="Foo">x [http://google.com g] x</a>
+<a href="/wiki/Foo" title="Foo">[[Bar]]</a>
+<a href="/wiki/Foo" title="Foo">x [[Bar]] x</a>
+<a href="/wiki/Foo" title="Foo">|Bar</a>
+<a href="/wiki/Foo" title="Foo">]]bar</a>
+<a href="/wiki/Foo" title="Foo">[[bar</a>
+<a href="/wiki/Foo" title="Foo">x [[ y</a>
+<a href="/wiki/Foo" title="Foo">x ]] y</a>
+<a href="/wiki/Foo" title="Foo">x ]] y [[ z</a>
+</p>
!! end
!! test
Links 3. WikiLinks: No escapes needed
-!! options
-parsoid
!! wikitext
[[Foo|[Foobar]]
[[Foo|foo|bar]]
-!! html
-<a href="Foo" rel="mw:WikiLink">[Foobar</a>
-<a href="Foo" rel="mw:WikiLink">foo|bar</a>
+!! html/php
+<p><a href="/wiki/Foo" title="Foo">[Foobar</a>
+<a href="/wiki/Foo" title="Foo">foo|bar</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="Foo">[Foobar</a>
+<a rel="mw:WikiLink" href="Foo" title="Foo">foo|bar</a></p>
!! end
!! test
Links 4. ExtLinks: Escapes needed
!! options
-parsoid
+parsoid=html2wt
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://google.com">[google]</a>
+<a rel="mw:ExtLink" href="http://google.com">google]</a></p>
+<p>[http://google.com]</p>
+<p>[http://google.com google]</p>
!! wikitext
[http://google.com <nowiki>[google]</nowiki>]
[http://google.com <nowiki>google]</nowiki>]
@@ -20091,21 +21751,23 @@ parsoid
<nowiki>[http://google.com google]</nowiki>
-!! html
-<p><a href="http://google.com" rel="mw:ExtLink">[google]</a>
-<a href="http://google.com" rel="mw:ExtLink">google]</a></p>
-<p>[http://google.com]</p>
-<p>[http://google.com google]</p>
+!! html/php
+<p><a rel="nofollow" class="external text" href="http://google.com">[google]</a>
+<a rel="nofollow" class="external text" href="http://google.com">google]</a>
+</p><p>[http://google.com]
+</p><p>[http://google.com google]
+</p>
!! end
!! test
Links 5. ExtLinks: No escapes needed
-!! options
-parsoid
!! wikitext
[http://google.com [google]
-!! html
-<a href="http://google.com" rel="mw:ExtLink">[google</a>
+!! html/php
+<p><a rel="nofollow" class="external text" href="http://google.com">[google</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:ExtLink" href="http://google.com">[google</a></p>
!! end
!! test
@@ -20162,61 +21824,90 @@ y
(http://example.com) foo
http://example.com,
http://example.com, foo
+!! html/php
+<p>x
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>
+y
+"<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>"
+(<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>)
+(<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>) foo
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>,
+<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>, foo
+</p>
!! end
-## Parsoid currently fails wt2html on this one!
!! test
Links 7b. Don't add spurious <nowiki/>s between text-nodes and url-links (bug 64300)
!! html/parsoid
-<p><a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url"}'>http://example.com</a>.,;:!?</p>
+<p><a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url"}'>http://example.com</a>.,;:!?\
+-<a rel="mw:ExtLink" href="http://example.com">http://example.com</a>:</p>
!! wikitext
-http://example.com.,;:!?
+http://example.com.,;:!?\
+-http://example.com:
+!! html/php
+<p><a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>.,;:!?\
+-<a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>:
+</p>
!! end
!! test
Links 8. Add <nowiki/>s between text-nodes and RFC-links when required (bug 64300)
!! html/parsoid
-<p><a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>RFC 123</a>4</p>
+<p><a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>RFC 123</a>4
+<a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>RFC 123</a>y
+X<a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>RFC 123</a>y</p>
!! wikitext
RFC 123<nowiki/>4
+RFC 123<nowiki/>y
+X<nowiki/>RFC 123<nowiki/>y
!! end
!! test
Links 9. Don't add spurious <nowiki/>s between text-nodes and RFC-links (bug 64300)
!! html/parsoid
-<p>x<a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>RFC 123</a>y
-X<a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>RFC 123</a>y
-<a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>RFC 123</a>?foo
+<p><a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>RFC 123</a>?foo
<a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>RFC 123</a>&amp;foo
+-<a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>RFC 123</a>-
</p>
!! wikitext
-xRFC 123y
-XRFC 123y
RFC 123?foo
RFC 123&foo
+-RFC 123-
+!! html/php
+<p><a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc123">RFC 123</a>?foo
+<a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc123">RFC 123</a>&amp;foo
+-<a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc123">RFC 123</a>-
+</p>
!! end
!! test
Links 10. Add <nowiki/>s between text-nodes and PMID-links when required (bug 64300)
!! html/parsoid
<p><a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>PMID 123</a>4
+<a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>PMID 123</a>y
+X<a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>PMID 123</a>y
!! wikitext
PMID 123<nowiki/>4
+PMID 123<nowiki/>y
+X<nowiki/>PMID 123<nowiki/>y
!! end
!! test
Links 11. Don't add spurious <nowiki/>s between text-nodes and PMID-links (bug 64300)
!! html/parsoid
-<p>x<a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>PMID 123</a>y
-X<a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>PMID 123</a>y
-<a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>PMID 123</a>?foo
+<p><a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>PMID 123</a>?foo
<a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>PMID 123</a>&foo
+-<a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>PMID 123</a>-
</p>
!! wikitext
-xPMID 123y
-XPMID 123y
PMID 123?foo
PMID 123&foo
+-PMID 123-
+!! html/php
+<p><a class="external mw-magiclink-pmid" rel="nofollow" href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract">PMID 123</a>?foo
+<a class="external mw-magiclink-pmid" rel="nofollow" href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract">PMID 123</a>&amp;foo
+-<a class="external mw-magiclink-pmid" rel="nofollow" href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract">PMID 123</a>-
+</p>
!! end
!! test
@@ -20224,20 +21915,47 @@ Links 12. Add <nowiki/>s between text-nodes and ISBN-links when required (bug 64
!! html/parsoid
<p><a href="./Special:BookSources/1234567890" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 1234567890</a>1
<a href="./Special:BookSources/1234567890" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 1234567890</a>x
-<a href="./Special:BookSources/1234567890" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 1234567890</a>b
+a<a href="./Special:BookSources/1234567890" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 1234567890</a>b
</p>
!! wikitext
ISBN 1234567890<nowiki/>1
ISBN 1234567890<nowiki/>x
-ISBN 1234567890<nowiki/>b
+a<nowiki/>ISBN 1234567890<nowiki/>b
!! end
!! test
-Links 12. Don't add spurious <nowiki/>s between text-nodes and ISBN-links (bug 64300)
+Links 13. Don't add spurious <nowiki/>s between text-nodes and ISBN-links (bug 64300)
!! html/parsoid
-<p><a href="./Special:BookSources/1234567890" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 1234567890</a>'s
+<p>-<a href="./Special:BookSources/1234567890" rel="mw:ExtLink" data-parsoid='{"stx":"magiclink"}'>ISBN 1234567890</a>'s
+!! wikitext
+-ISBN 1234567890's
+!! html/php
+<p>-<a href="/wiki/Special:BookSources/1234567890" class="internal mw-magiclink-isbn">ISBN 1234567890</a>'s
+</p>
+!! end
+
+!! test
+Links 14. Protect link-like plain text. (Parsoid bug T78425)
+!! options
+parsoid=html2wt
+!! html/*
+<p>this is not a link: http://example.com
+</p>
+!! wikitext
+this is not a link: <nowiki>http://example.com</nowiki>
+!! end
+
+!! test
+Links 15. Link trails can't become link prefixes.
+!! options
+language=is
!! wikitext
-ISBN 1234567890's
+[[Söfnuður]]-[[00]]
+!! html/php
+<p><a href="/wiki/S%C3%B6fnu%C3%B0ur" title="Söfnuður">Söfnuður-</a><a href="/wiki/00" title="00">00</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="Söfnuður" title="Söfnuður" data-parsoid='{"stx":"simple","tail":"-"}'>Söfnuður-</a><a rel="mw:WikiLink" href="00" title="00">00</a></p>
!! end
#### --------------- Quotes ---------------
@@ -20247,28 +21965,31 @@ ISBN 1234567890's
#### 4. No escaping needed
#### --------------------------------------
!! test
-1. Quotes inside <b> and <i>
+1a. Quotes inside <b> and <i>
!! options
parsoid=html2wt,wt2wt
!! wikitext
-''<nowiki>'foo'</nowiki>''
+''<nowiki/>'foo'''
''<nowiki>''foo''</nowiki>''
''<nowiki>'''foo'''</nowiki>''
''foo''<nowiki/>'s
-'''<nowiki>'foo'</nowiki>'''
+'''<nowiki/>'foo''''
'''<nowiki>''foo''</nowiki>'''
'''<nowiki>'''foo'''</nowiki>'''
-'''<nowiki>foo'</nowiki>''<nowiki>bar'</nowiki>''baz'''
+'''foo'<nowiki/>''bar'<nowiki/>''baz'''
'''foo'''<nowiki/>'s
'''foo''
''foo''<nowiki/>'
-'<nowiki/>''foo''<nowiki/>'
+''foo'''<nowiki/>'
+'''foo''<nowiki/>'
''''foo'''
'''foo'''<nowiki/>'
-'<nowiki/>'''foo'''<nowiki/>'
+''''foo'''<nowiki/>'
''fools'<span> errand</span>''
''<span>fool</span>'s errand''
-!! html
+'<nowiki/>''foo'' bar '''baz''
+a|!*#-:;+-~[]{}b'''x''
+!! html/*
<p><i>'foo'</i>
<i>''foo''</i>
<i>'''foo'''</i>
@@ -20280,12 +22001,42 @@ parsoid=html2wt,wt2wt
<b>foo</b>'s
'<i>foo</i>
<i>foo</i>'
+<i>foo'</i>'
'<i>foo</i>'
'<b>foo</b>
<b>foo</b>'
-'<b>foo</b>'</p>
+'<b>foo</b>'
<i>fools'<span> errand</span></i>
<i><span>fool</span>'s errand</i>
+'<i>foo</i> bar '<i>baz</i>
+a|!*#-:;+-~[]{}b'<i>x</i>
+</p>
+!! end
+
+!! test
+1b. Quotes inside <b> and <i> with other tags on same line
+!! options
+parsoid=html2wt,wt2wt
+!! wikitext
+'''a'' foo ''[[bar]]''
+''a''' foo ''[[bar]]''
+''a''' foo '''{{echo|[[bar]]}}'''
+[[foo]] x'''[[bar]]''
+'''foo'' <ref>test</ref>
+'''foo'' <div title="name">test</div>
+'''foo'' and <br> bar
+<references />
+!! html
+'<i>a</i> foo <i><a rel="mw:WikiLink" href="Bar" title="Bar">bar</a></i>
+<i>a'</i> foo <i><a rel="mw:WikiLink" href="Bar" title="Bar">bar</a></i>
+<i>a'</i> foo <b><a rel="mw:WikiLink" href="Bar" title="Bar" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[[bar]]"}},"i":0}}]}'>bar</a></b>
+<a rel="mw:WikiLink" href="Foo" title="Foo">foo</a> x'<i><a href="Bar" rel="mw:WikiLink" title="Bar">bar</a></i>
+'<i>foo</i> <span class="reference" id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span>
+'<i>foo</i> <div title="name">test</div>
+'<i>foo</i> and <br data-parsoid='{"stx":"html","noClose":true}'/> bar
+<ol class="references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">test</span></li>
+</ol>
!! end
!! test
@@ -20300,10 +22051,10 @@ parsoid=html2wt,wt2wt
</p>
!! 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 <i> and <b>
-(FIXME: Escaping one or both of [[ and ]] is also acceptable --
- this is one of the shortcomings of this format)
!! wikitext
''[[foo''<nowiki>]]</nowiki>
@@ -20319,9 +22070,11 @@ parsoid=html2wt,wt2wt
!! wikitext
'<span>''bar''</span>'
'<span>'''bar'''</span>'
+'a:b'foo
!! html
<p>'<span><i>bar</i></span>'
'<span><b>bar</b></span>'
+'a:b'foo
</p>
!! end
@@ -20397,8 +22150,13 @@ parsoid
!! wikitext
foo <ref>''a''
b</ref>
+<references />
!! html
-<p>foo <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"&lt;i data-parsoid=&#39;{\"dsr\":[9,14,2,2]}&#39;>a&lt;/i>\n b"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
+<p>foo <span about="#mwt2" class="reference" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1">[1]</a></span></p>
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"><i data-parsoid='{"dsr":[9,14,2,2]}'>a</i>
+ b</span></li>
+</ol>
!! end
!! test
@@ -20426,9 +22184,8 @@ parsoid
parsoid
!! wikitext
[[File:Foobar.jpg|thumb|caption]]
-!! html
!! html/parsoid
- <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+ <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
!! end
!! test
@@ -20446,22 +22203,22 @@ parsoid=html2wt
1. Valid behavior switches should be escaped
!! options
parsoid=html2wt
-!! wikitext
-<nowiki>__TOC__</nowiki>
-''<nowiki>__TOC__</nowiki>''
!! html
__TOC__
<i>__TOC__</i>
+!! wikitext
+<nowiki>__TOC__</nowiki>
+''<nowiki>__TOC__</nowiki>''
!! end
!! test
2. Invalid behavior switches should not be escaped
!! options
parsoid=html2wt
-!! wikitext
+!! html
__TOO__
__|__
-!! html
+!! wikitext
__TOO__
__|__
!! end
@@ -20485,12 +22242,14 @@ parsoid
!! test
2. other tags
!! wikitext
-<nowiki><div>foo</div>
-<div style="color:red">foo</div></nowiki>
+* <nowiki><div>foo</div></nowiki>
+* <nowiki><div style="color:red">foo</div></nowiki>
+* <nowiki><td></nowiki>
!! html
-<p>&lt;div&gt;foo&lt;/div&gt;
-&lt;div style=&quot;color:red&quot;&gt;foo&lt;/div&gt;
-</p>
+<ul><li> &lt;div&gt;foo&lt;/div&gt;</li>
+<li> &lt;div style=&quot;color:red&quot;&gt;foo&lt;/div&gt;</li>
+<li> &lt;td&gt;</li></ul>
+
!! end
!! test
@@ -20570,18 +22329,6 @@ a>b
</p>
!! end
-
-# This was a bug in the PHP parser (see bug 17663 and its dups,
-# https://bugzilla.wikimedia.org/show_bug.cgi?id=17663)
-!! test
-Tag names followed by punctuation should not be recognized as tags
-!! wikitext
-<s.ome> text
-!! html
-<p>&lt;s.ome&gt; text
-</p>
-!! end
-
!! test
HTML tag with necessary entities in attributes
!! wikitext
@@ -20650,7 +22397,7 @@ Table with broken attribute value quoting on consecutive lines
| title="Hello world|Foo
| style="color:red|Bar
|}
-!! html
+!! html/php
<table>
<tr>
<td>Foo
@@ -20658,18 +22405,7 @@ Table with broken attribute value quoting on consecutive lines
<td>Bar
</td></tr></table>
-!! end
-
-!! test
-Parsoid-only: Table with broken attribute value quoting on consecutive lines
-!! options
-parsoid
-!! wikitext
-{|
-| title="Hello world|Foo
-| style="color:red|Bar
-|}
-!! html
+!! html/parsoid
<table><tbody>
<tr>
<td title="Hello world">Foo
@@ -20783,9 +22519,9 @@ RT-ed inter-element separators should be valid separators
!!end
+# Parsoid-only since PHP parser relies on Tidy for correct output
!!test
Trailing newlines in a deep dom-subtree that ends a wikitext line should be migrated out
-(Parsoid-only since PHP parser relies on Tidy for correct output)
!!options
parsoid
!! wikitext
@@ -20798,6 +22534,14 @@ bar
|<small>foo<small>
|}
!! html
+<table>
+<tbody><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'><small data-parsoid='{"stx":"html","autoInsertedEnd":true}'>foo
+<p>bar</p></small></td></tr>
+</tbody></table>
+
+<table>
+<tbody><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'><small data-parsoid='{"stx":"html","autoInsertedEnd":true}'>foo<small data-parsoid='{"stx":"html","autoInsertedEnd":true}'></small></small></td></tr>
+</tbody></table>
!!end
!!test
@@ -20838,6 +22582,29 @@ Indented table with an empty td
!!end
+## We have some newline diffs RT-ing this edge case
+## and it is not important enough -- we seem to be emitting
+## at most 2 newlines after a </tr> and this is unrelated to
+## the issue from T85627 that this is testing.
+!!test
+Indented table with blank lines in between (T85627)
+!! options
+parsoid=wt2html
+!! wikitext
+ {|
+ |foo
+
+
+ |}
+!! html
+<table>
+
+<tr>
+<td>foo
+</td></tr></table>
+
+!!end
+
!!test
Indented block & table
!! wikitext
@@ -20874,15 +22641,15 @@ Indent and comment before table row
</td></tr></table>
!! html/parsoid
-<table data-parsoid='{}'>
- <!--hi--><tbody data-parsoid='{}'><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
+<table>
+ <!--hi--><tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
<td data-parsoid='{"autoInsertedEnd":true}'> there</td></tr>
</tbody></table>
!! end
+# Parsoid-specific since PHP parser doesn't handle this mixed tbl-wikitext
!!test
Empty TR followed by a template-generated TR
-(Parsoid-specific since PHP parser doesn't handle this mixed tbl-wikitext)
!!options
parsoid
!! wikitext
@@ -20925,32 +22692,29 @@ parsoid
!!test
Multi-line image caption generated by templates with/without trailing newlines
-!!options
-parsoid
!! wikitext
-[[File:foo.jpg|thumb|300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}]]
-[[File:foo.jpg|thumb|300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}\n\n]]
-!! html
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Foo.jpg" class="new" title="File:Foo.jpg">File:Foo.jpg</a> <div class="thumbcaption">foo\nA\nB\nC</div></div></div>
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&amp;wpDestFile=Foo.jpg" class="new" title="File:Foo.jpg">File:Foo.jpg</a> <div class="thumbcaption">foo\nA\nB\nC\n\n</div></div></div>
-
+[[File:Foobar.jpg|thumb|300x300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}]]
+[[File:Foobar.jpg|thumb|300x300px|foo\n{{echo|A}}\n{{echo|B}}\n{{echo|C}}\n\n]]
+!! html/parsoid
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="34" width="300"/></a><figcaption>foo\n<span about="#mwt9" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"A"}},"i":0}}]}'>A</span>\n<span about="#mwt10" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"B"}},"i":0}}]}'>B</span>\n<span about="#mwt11" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"C"}},"i":0}}]}'>C</span></figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="34" width="300"/></a><figcaption>foo\n<span about="#mwt12" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"A"}},"i":0}}]}'>A</span>\n<span about="#mwt13" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"B"}},"i":0}}]}'>B</span>\n<span about="#mwt14" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"C"}},"i":0}}]}'>C</span>\n\n</figcaption></figure>
!!end
!! test
New element inserted (without intervening newlines) after an old sol-transparent node should serialize correctly
!! options
parsoid=html2wt
+!! html
+<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"&lt;includeonly>foo&lt;/includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><p>new para</p>
+
+<link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid='{}'/><h1>new heading</h1>
!! wikitext
<includeonly>foo</includeonly>
new para
-[[./Category:Foo]]
+[[Category:Foo]]
= new heading =
-!! html
-<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"&lt;includeonly>foo&lt;/includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><p>new para</p>
-
-<link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid=''/><h1>new heading</h1>
!! end
## PHP emits broken html for this, and since this is primarily
@@ -20993,20 +22757,20 @@ plain text
!!end
!!test
-1. Ensure fostered text content is wrapped in spans
+1. Ensure fostered text content is wrapped in element nodes
!!options
parsoid=wt2html
!! wikitext
<table>hi</table><table>ho</table>
!! html
-<span>hi</span>
+<p>hi</p>
<table></table>
-<span>ho</span>
+<p>ho</p>
<table></table>
!!end
!!test
-2. Ensure fostered text content is wrapped in spans (traps regressions around fostered marker on the span getting lost)
+2. Ensure fostered text content is wrapped in element nodes (traps regressions around fostered marker on the element getting lost)
!!options
parsoid=wt2html,wt2wt
!! wikitext
@@ -21015,11 +22779,9 @@ parsoid=wt2html,wt2wt
<td> a
</table>
!! html
-<span> || ||</span>
-<table>
-<tbody>
-<tr>
-<td> a</td></tr>
+<p> || ||
+</p><table>
+<tbody><tr><td> a</td></tr>
</tbody></table>
!!end
@@ -21030,14 +22792,7 @@ parsoid=wt2html,wt2wt
!! wikitext
{{echo|<table>foo<tr><td>bar</td></tr></table>}}
!! html
-<span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;
-<table>foo
-<tr>
-<td>bar</td></tr></table>&quot;}},&quot;i&quot;:0}}]}">foo</span>
-<table>
-<tbody>
-<tr>
-<td>bar</td></tr></tbody></table>
+<span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;<table>foo<tr><td>bar</td></tr></table>&quot;}},&quot;i&quot;:0}}]}">foo</span><table><tbody><tr><td>bar</td></tr></tbody></table>
!!end
!!test
@@ -21047,14 +22802,13 @@ parsoid=wt2wt,wt2html
!! wikitext
<table>{{echo|foo<tr><td>bar</td></tr>}}</table>
!! html
-<span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
-<table>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo
-<tr>
-<td>bar</td></tr>&quot;}},&quot;i&quot;:0}},&quot;</table>&quot;]}">foo</span>
-<table>
+<p typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;<table>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo<tr><td>bar</td></tr>&quot;}},&quot;i&quot;:0}},&quot;</table>&quot;]}">foo</p><table>
<tbody>
<tr>
-<td>bar</td></tr></tbody></table>
+<td>bar</td>
+</tr>
+</tbody>
+</table>
!!end
!!test
@@ -21064,15 +22818,14 @@ parsoid=wt2wt,wt2html
!! wikitext
<table><div>{{echo|foo}}</div><tr><td>bar</td></tr></table>
!! html
-<div typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
-<table>
-<div>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo&quot;}},&quot;i&quot;:0}},&quot;</div>
-<tr>
-<td>bar</td></tr></table>&quot;]}">foo</div>
+<div typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;<table><div>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo&quot;}},&quot;i&quot;:0}},&quot;</div><tr><td>bar</td></tr></table>&quot;]}">foo</div>
<table>
<tbody>
<tr>
-<td>bar</td></tr></tbody></table>
+<td>bar</td>
+</tr>
+</tbody>
+</table>
!!end
!!test
@@ -21082,17 +22835,16 @@ parsoid=wt2wt,wt2html
!! wikitext
<table><div><p>{{echo|foo</p></div><tr><td>}}bar</td></tr></table>
!! html
-<div typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
-<table>
-<div>
-<p>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo</p></div>
-<tr>
-<td>&quot;}},&quot;i&quot;:0}},&quot;bar</td></tr></table>&quot;]}">
-<p>foo</p></div>
+<div typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;<table><div><p>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo</p></div><tr><td>&quot;}},&quot;i&quot;:0}},&quot;bar</td></tr></table>&quot;]}">
+<p>foo</p>
+</div>
<table>
<tbody>
<tr>
-<td>bar</td></tr></tbody></table>
+<td>bar</td>
+</tr>
+</tbody>
+</table>
!!end
!!test
@@ -21102,17 +22854,16 @@ parsoid=wt2wt,wt2html
!! wikitext
<table><div><p>{{echo|foo</p></div><tr><td>}}bar</td></tr></table>
!! html
-<div typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
-<table>
-<div>
-<p>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo</p></div>
-<tr>
-<td>&quot;}},&quot;i&quot;:0}},&quot;bar</td></tr></table>&quot;]}">
-<p>foo</p></div>
+<div typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;<table><div><p>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo</p></div><tr><td>&quot;}},&quot;i&quot;:0}},&quot;bar</td></tr></table>&quot;]}">
+<p>foo</p>
+</div>
<table>
<tbody>
<tr>
-<td>bar</td></tr></tbody></table>
+<td>bar</td>
+</tr>
+</tbody>
+</table>
!!end
!!test
@@ -21122,18 +22873,18 @@ parsoid=wt2wt,wt2html
!! wikitext
<table><tr><td><div><p>{{echo|foo</p></div></td>foo}}</tr></table>
!! html
-<span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
-<table>
-<tr>
-<td>
-<div>
-<p>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo</p></div></td>foo&quot;}},&quot;i&quot;:0}},&quot;</tr></table>&quot;]}">foo</span>
+<p typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;<table><tr><td><div><p>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo</p></div></td>foo&quot;}},&quot;i&quot;:0}},&quot;</tr></table>&quot;]}">foo</p>
<table>
<tbody>
<tr>
<td>
<div>
-<p>foo</p></div></td></tr></tbody></table>
+<p>foo</p>
+</div>
+</td>
+</tr>
+</tbody>
+</table>
!!end
!!test
@@ -21143,18 +22894,18 @@ parsoid=wt2wt,wt2html
!! wikitext
<table><tr><td><div><p>{{echo|foo</p></div></td>foo</tr></table>}}<p>ok</p>
!! html
-<span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
-<table>
-<tr>
-<td>
-<div>
-<p>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo</p></div></td>foo</tr></table>&quot;}},&quot;i&quot;:0}}]}">foo</span>
+<p typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;<table><tr><td><div><p>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;foo</p></div></td>foo</tr></table>&quot;}},&quot;i&quot;:0}}]}">foo</p>
<table>
<tbody>
<tr>
<td>
<div>
-<p>foo</p></div></td></tr></tbody></table>
+<p>foo</p>
+</div>
+</td>
+</tr>
+</tbody>
+</table>
<p>ok</p>
!!end
@@ -21165,14 +22916,14 @@ parsoid=wt2wt,wt2html
!! wikitext
<table>{{echo|<p>foo</p>}}<td>bar</td></table>
!! html
-<p typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;
-<table>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;
-<p>foo</p>&quot;}},&quot;i&quot;:0}},&quot;
-<td>bar</td></table>&quot;]}">foo</p>
+<p typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;<table>&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;<p>foo</p>&quot;}},&quot;i&quot;:0}},&quot;<td>bar</td></table>&quot;]}">foo</p>
<table>
<tbody>
<tr>
-<td>bar</td></tr></tbody></table>
+<td>bar</td>
+</tr>
+</tbody>
+</table>
!!end
!!test
@@ -21186,11 +22937,13 @@ parsoid=wt2wt,wt2html
|b
|}
!! html
-<p typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;a\n&quot;}},&quot;i&quot;:0}}]}">a</p><span typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;{|&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;style&quot;:{&quot;wt&quot;:&quot;'color:red'&quot;}},&quot;i&quot;:0}},&quot;\n|-\n|b\n|}&quot;]}">{{{1}}}</span>
-<table>
+<p typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;a\n&quot;}},&quot;i&quot;:0}}]}">a</p><p typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[&quot;{|&quot;,{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;style&quot;:{&quot;wt&quot;:&quot;'color:red'&quot;}},&quot;i&quot;:0}},&quot;\n|-\n|b\n|}&quot;]}">{{{1}}}</p><table>
<tbody>
<tr>
-<td>b</td></tr></tbody></table>
+<td>b</td>
+</tr>
+</tbody>
+</table>
!!end
!!test
@@ -21200,8 +22953,7 @@ parsoid=wt2wt,wt2html
!! wikitext
<table>{{echo|hi</table>hello}}
!! html
-<span about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":["&lt;table>",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"hi&lt;/table>hello"}},"i":0}}]}' data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"pi":[[{"k":"1","spc":["","","",""]}]]}'>hi</span>
-<table about="#mwt2" data-parsoid='{"stx":"html"}'></table><span about="#mwt2" data-parsoid="{}">hello</span>
+<p about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":["&lt;table>",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"hi&lt;/table>hello"}},"i":0}}]}' data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"pi":[[{"k":"1","spc":["","","",""]}]]}'>hi</p><table about="#mwt2" data-parsoid='{"stx":"html"}'></table><p about="#mwt2">hello</p>
!!end
!!test
@@ -21216,7 +22968,7 @@ parsoid=wt2html,wt2wt
</div>
|}
!! html
-<div about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"OpenTable","href":"./Template:OpenTable"},"params":{},"i":0}},"\n&lt;div>"]}' data-parsoid='{"stx":"html","autoInsertedEnd":true,"pi":[[]]}'></div><span about="#mwt1" data-parsoid="{}">
+<div about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"OpenTable","href":"./Template:OpenTable"},"params":{},"i":0}},"\n&lt;div>"]}' data-parsoid='{"stx":"html","autoInsertedEnd":true,"pi":[[]]}'></div><span about="#mwt1">
</span>
<table about="#mwt1" data-parsoid='{"autoInsertedEnd":true}'></table>
@@ -21234,7 +22986,7 @@ Properly encapsulate empty-content transclusions in fosterable positions
}}
</table>
!! html/parsoid
-<table about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":["&lt;table>\n",{"template":{"target":{"wt":"#if:","function":"#if"},"params":{"1":{"wt":"\n&lt;td>foo&lt;/td>\n"}},"i":0}},"\n&lt;/table>"]}' data-parsoid='{"stx":"html","pi":[[{"k":"1","spc":["","","",""]}]],"src":"&lt;table>\n{{#if:|\n&lt;td>foo&lt;/td>\n}}\n&lt;/table>"}'>
+<table about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":["&lt;table>\n",{"template":{"target":{"wt":"#if:","function":"#if"},"params":{"1":{"wt":"\n&lt;td>foo&lt;/td>\n"}},"i":0}},"\n&lt;/table>"]}' data-parsoid='{"stx":"html","pi":[[{"k":"1","spc":["","","",""]}]]}'>
</table>
!! end
@@ -21243,12 +22995,23 @@ Properly encapsulate empty-content transclusions in fosterable positions
Support <object> element with .data attribute
!!options
parsoid=html2wt
-!! wikitext
-<object data="test.swf"></object>
!! html
<object data="test.swf"></object>
+!! wikitext
+<object data="test.swf"></object>
!!end
+!! test
+Don't block XML namespace declaration
+!! wikitext
+<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">MediaWiki</span>
+!! html/php
+<p><span>MediaWiki</span>
+</p>
+!! html/parsoid
+<p><span xmlns:dct="http://purl.org/dc/terms/" data-x-property="dct:title" data-parsoid='{"stx":"html"}'>MediaWiki</span></p>
+!! end
+
# -----------------------------------------------------------------
# The following section of tests are primarily to spec requirements
# around serialization of new/edited content.
@@ -21256,15 +23019,101 @@ parsoid=html2wt
# All these tests are marked Parsoid html2wt and html2html only
# ----------------------------------------------------------------
+# 'mi' is a localinterwiki prefix as well as a language
!! test
Serialize interwiki links pointing to the current wiki as plain wiki links (bug 65869)
!! options
parsoid=html2wt
-language=es
+!! html
+<p><a rel="mw:ExtLink" href="http://mi.wikipedia.org/wiki/Foo">Foo</a></p>
!! wikitext
[[Foo]]
+!! end
+
+# See T93839
+!! test
+New wikilinks should be serialized properly
+!! options
+parsoid=html2wt
!! html
-<p><a rel="mw:ExtLink" href="http://es.wikipedia.org/wiki/Foo">Foo</a></p>
+<a rel="mw:WikiLink" href="./Foo" title="Foo" data-parsoid='{}'>Foo</a>
+<a rel="mw:WikiLink" href="./Foo" title="Foo">Foo</a>
+!! wikitext
+[[Foo]]
+[[Foo]]
+!! end
+
+!! test
+New wiki links (href variations)
+!! options
+parsoid=html2wt
+!! html
+<a rel="mw:WikiLink" href="./Foo_bar">Foo_bar</a>
+<a rel="mw:WikiLink" href="Foo_bar">Foo_bar</a>
+<a rel="mw:WikiLink" href="Foo bar">Foo_bar</a>
+<a rel="mw:WikiLink" href="./Toxine_bact%C3%A9rienne">Toxine bactérienne</a>
+!! wikitext
+[[Foo_bar]]
+[[Foo_bar]]
+[[Foo_bar]]
+[[Toxine bactérienne]]
+!! end
+
+!! test
+New wiki links (content string variations)
+!! options
+parsoid=html2wt
+!! html
+<a rel="mw:WikiLink" href="./Foo_bar">Foo_bar</a>
+<a rel="mw:WikiLink" href="./Foo_bar">Foo bar</a>
+<a rel="mw:WikiLink" href="./Foo_bar">./Foo_bar</a>
+!! wikitext
+[[Foo_bar]]
+[[Foo bar]]
+[[Foo_bar|./Foo_bar]]
+!! end
+
+!! test
+New category links (href variations)
+!! options
+parsoid=html2wt
+!! html
+<link rel="mw:PageProp/Category" href="./Category:Toxine_bactérienne" />
+<link rel="mw:PageProp/Category" href="./Category:Toxine_bact%C3%A9rienne" />
+<link rel="mw:PageProp/Category" href="Category:Toxine_bact%C3%A9rienne" />
+!! wikitext
+[[Category:Toxine bactérienne]]
+[[Category:Toxine bactérienne]]
+[[Category:Toxine bactérienne]]
+!! end
+
+!! test
+New sol transparent links don't need indent-pre nowiki protection
+!! options
+parsoid=html2wt
+language=de
+!! html
+ <link rel="mw:PageProp/redirect" href="./Main_Page">
+<!-- this is good --> <link rel="mw:PageProp/Category" href="./Category:Good" />
+<!-- this is great --> <link rel="mw:PageProp/Category" href="./Kategorie:Great" />
+!! wikitext
+ #WEITERLEITUNG [[Main Page]]
+<!-- this is good --> [[Category:Good]]
+<!-- this is great --> [[Kategorie:Great]]
+!! end
+
+!! test
+New interlanguage links (href variations)
+!! options
+parsoid=html2wt
+!! html
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Toxine bactérienne" />
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Toxine_bactérienne" />
+<link rel="mw:PageProp/Language" href="http://es.wikipedia.org/wiki/Toxine_bact%C3%A9rienne" />
+!! wikitext
+[[es:Toxine bactérienne]]
+[[es:Toxine_bactérienne]]
+[[es:Toxine_bactérienne]]
!! end
!! test
@@ -21401,7 +23250,7 @@ parsoid
!! wikitext
[[File:Foobar.jpg|thumb|alt=|bar]]
!! html
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"alt","ak":"alt="},{"ck":"caption","ak":"bar"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img alt="" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"alt":"","resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"alt":"alt=","resource":"File:Foobar.jpg"}}'/></a><figcaption>bar</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"alt","ak":"alt="},{"ck":"caption","ak":"bar"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img alt="" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"alt":"","resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"alt":"alt=","resource":"File:Foobar.jpg"}}'/></a><figcaption>bar</figcaption></figure>
!! end
#!! test
@@ -21409,37 +23258,34 @@ parsoid
#!! options
#parsoid=html2wt
#language=ar
-#!! input
+#!! html
+#<figure class="mw-default-size mw-halign-right" typeof="mw:Image/Thumb"><a href="Imagen:Foobar.jpg"><img resource="./Imagen:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="20" width="180"/></a></figure>
+#!! wikitext
#[[Imagen:Foobar.jpg|derecha|miniaturadeimagen]]
-#!! result
-#<figure class="mw-default-size mw-halign-right" typeof="mw:Image/Thumb"><a href="Imagen:Foobar.jpg"><img resource="./Imagen:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="20" width="180"/></a></figure>
#!! end
!! test
Image: Block level image should have \n before and after
-!! options
-parsoid
!! wikitext
123
[[File:Foobar.jpg|right|thumb|150x150px]]
456
-!! html
-<p>123</p><figure typeof="mw:Image/Thumb" class="mw-halign-right"><a href="./File:Foobar.png"><img src="http://192.168.142.128/mw/images/thumb/b/bc/Foobar.png/131px-Foobar.png" width="131" height="150" resource="./File:Foobar.png" data-parsoid='{"a":{"resource":"./File:Foobar.png","width":"131"},"sa":{"resource":"File:Foobar.png","width":"150"}}'></a></figure><p>456</p>
+!! html/parsoid
+<p>123</p>
+<figure class="mw-halign-right" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="17" width="150"/></a></figure>
+<p>456</p>
!!end
!! test
-Image: New block level image should have \n before and after (existing
-content)
-!! options
-parsoid
+Image: New block level image should have \n before and after (existing content)
!! wikitext
123
[[File:Foobar.jpg|right|thumb|150x150px]]
456
-!! html
-<p data-parsoid='{"dsr":[0,3,0,0]}'>123</p>
-<figure class="mw-halign-right" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"right","ak":"right"},{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"150x150px"}],"dsr":[4,45,2,2]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"dsr":[6,43,null,null]}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/150px-Foobar.jpg" height="17" width="150" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"17","width":"150"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></figure>
-<p data-parsoid='{"dsr":[46,49,0,0]}'>456</p>
+!! html/parsoid
+<p>123</p>
+<figure class="mw-halign-right" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"right","ak":"right"},{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"150x150px"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/150px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="17" width="150" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"17","width":"150"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></figure>
+<p>456</p>
!!end
!! test
@@ -21451,7 +23297,9 @@ parsoid
[[File:Foobar.jpg|thumb|upright=0.5|caption]]
[[File:Foobar.jpg|thumb|500x500px|upright=0.5|caption]]
!! html
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="19" width="170"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="12" width="110"/></a><figcaption>caption</figcaption></figure><figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="57" width="500"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="19" width="170"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="12" width="110"/></a><figcaption>caption</figcaption></figure>
+<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="57" width="500"/></a><figcaption>caption</figcaption></figure>
!!end
!! test
@@ -21461,7 +23309,7 @@ parsoid
!! wikitext
[[File:Foobar.jpg|500x500px|upright=0.5|caption]]
!! html
-<p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="57" width="500"/></a></span></p>
+<p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="57" width="500"/></a></span></p>
!!end
!! test
@@ -21470,7 +23318,7 @@ Image: from basic HTML (1)
parsoid=html2wt
!! html/parsoid
<span typeof="mw:Image">
- <img src="File:Foobar.jpg" width=100 height=100 alt="Alt">
+ <img src="./File:Foobar.jpg" width=100 height=100 alt="Alt">
</span>
!! wikitext
[[File:Foobar.jpg|link=|alt=Alt|100x100px]]
@@ -21481,7 +23329,7 @@ Image: from basic HTML (2)
!! options
parsoid=html2wt
!! html/parsoid
-<img src="File:Foobar.jpg" width=100 height=100 alt="Alt">
+<img src="./File:Foobar.jpg" width=100 height=100 alt="Alt">
!! wikitext
[[File:Foobar.jpg|link=|alt=Alt|100x100px]]
!! end
@@ -21491,7 +23339,7 @@ Image: from basic HTML (3)
!! options
parsoid=html2wt
!! html/parsoid
-<a href="Main"><img src="File:Foobar.jpg" width=100 height=100 alt="Alt"></a>
+<a href="Main"><img src="./File:Foobar.jpg" width=100 height=100 alt="Alt"></a>
!! wikitext
[[File:Foobar.jpg|link=Main|alt=Alt|100x100px]]
!! end
@@ -21501,7 +23349,7 @@ Image: from basic HTML (4)
!! options
parsoid=html2wt
!! html/parsoid
-<img src="File:Foobar.jpg">
+<img src="./File:Foobar.jpg">
!! wikitext
[[File:Foobar.jpg|link=]]
!! end
@@ -21510,28 +23358,41 @@ parsoid=html2wt
Lists: Serialize correctly even when list content is wrapped in p-tags (like VE does)
!! options
parsoid=html2wt
-!! wikitext
-* foo
!! html
<ul>
<li><p>foo</p></li>
</ul>
+!! wikitext
+* foo
!! end
!! test
Lists: Serialize correctly even when list tags has unneeded whitespace between tags
!! options
parsoid=html2wt
-!! wikitext
-* foo
!! html
<ul> <li>foo</li></ul>
+!! wikitext
+* foo
!! end
!! test
Don't strip leading whitespace when handling indent-pre suppressing tags
!! options
parsoid=html2wt
+!! html
+<table>
+ <tr><td> indented row</td></tr>
+</table>
+<blockquote><p>
+ <b>This is very bold of you!</b>
+</p>
+<table><tr><td>
+ indented cell (no pre-wrapping!)
+</td></tr></table>
+</blockquote>
+<p>foo</p>
+ <div>bar</div>
!! wikitext
{|
| indented row
@@ -21546,19 +23407,6 @@ parsoid=html2wt
</blockquote>
foo
<div>bar</div>
-!! html
-<table>
- <tr><td> indented row</td></tr>
-</table>
-<blockquote><p>
- <b>This is very bold of you!</b>
-</p>
-<table><tr><td>
- indented cell (no pre-wrapping!)
-</td></tr></table>
-</blockquote>
-<p>foo</p>
- <div>bar</div>
!! end
!! test
@@ -21597,33 +23445,38 @@ foo
Lists: Add space after bullets
!! options
parsoid=html2wt
-!! wikitext
-* foo
-* bar
-* <span> baz</span>
!! html
<ul>
<li>foo</li>
<li> bar</li>
<li><span> baz</span></li>
</ul>
+!! wikitext
+* foo
+* bar
+* <span> baz</span>
!! end
!! test
Lists: Dont insert newlines in a serialized list item.
!! options
parsoid=html2wt
+!! html
+<ul><li>a<br>b</li><li>c</li></ul>
!! wikitext
* a<br>b
* c
-!! html
-<ul><li>a<br>b</li><li>c</li></ul>
!! end
!! test
Headings: Add space before/after == (Bug 51744)
!! options
parsoid=html2wt
+!! html
+<h2>foo</h2>
+<h2> bar</h2>
+<h2>baz </h2>
+<h2><span> baz</span></h2>
!! wikitext
== foo ==
@@ -21632,25 +23485,32 @@ parsoid=html2wt
== baz ==
== <span> baz</span> ==
-!! html
-<h2>foo</h2>
-<h2> bar</h2>
-<h2>baz </h2>
-<h2><span> baz</span></h2>
!! end
!! test
-Parsoid: Serialize positional parameters with = in them as named parameter
+Headings: Force metas to serialize before/after
!! options
parsoid=html2wt
+!! html
+<h2>hello there<link href="Category:A1" rel="mw:PageProp/Category" /></h2>
+<h2><link href="Category:A2" rel="mw:PageProp/Category" />hi pal</h2>
+
+<h2><!--foo--> <link href="Category:A3" rel="mw:PageProp/Category" /> how goes it</h2>
!! wikitext
-{{echo|1 = f=oo}}
+== hello there ==
+[[Category:A1]]
-{{echo|1 = f=oo|2 = bar}}
+[[Category:A2]]
+== hi pal ==
-<!--Orig params with data-parsoid has heuristics for handling = chars-->
-<!--FIXME: But maybe the heuristic needs fixing to apply to new params as well-->
-{{echo|<nowiki>f=oo</nowiki>|bar}}
+<!--foo--> [[Category:A3]]
+== how goes it ==
+!! end
+
+!! test
+Parsoid: Serialize positional parameters with = in them as named parameter
+!! options
+parsoid=html2wt
!! html
<p about="#mwt1" typeof="mw:Transclusion"
data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"f=oo"}},"i":0}}]}'>foo</p>
@@ -21661,12 +23521,37 @@ data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},
<!--Orig params with data-parsoid has heuristics for handling = chars-->
<!--FIXME: But maybe the heuristic needs fixing to apply to new params as well-->
<p data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]},{"k":"2","spc":["","","",""]}]]}' about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"f=oo"},"2":{"wt":"bar"}},"i":0}}]}'>foo</p>
+!! wikitext
+{{echo|1 = f=oo}}
+
+{{echo|1 = f=oo|2 = bar}}
+
+<!--Orig params with data-parsoid has heuristics for handling = chars-->
+<!--FIXME: But maybe the heuristic needs fixing to apply to new params as well-->
+{{echo|<nowiki>f=oo</nowiki>|bar}}
+!! end
+
+!! test
+Parsoid: Serialize positional parameters with = in extlink as named parameter
+!! options
+parsoid=html2wt
+!! html
+<p><a rel="mw:ExtLink" href="http://stuff?is=ok" about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"http://stuff?is=ok"}},"i":0}}]}'>http://stuff?is=ok</a></p>
+!! wikitext
+{{echo|1 = http://stuff?is=ok}}
!! end
!! test
Parsoid: Correctly serialize block-node children when they are a combination of text and p-nodes
!! options
parsoid=html2wt
+!! html
+<div>a<p>b</p></div>
+<div>a
+<p>b</p></div>
+<div>
+a
+<p>b</p></div>
!! wikitext
<div>a
b
@@ -21679,23 +23564,32 @@ a
b
</div>
-!! html
-<div>a<p>b</p></div>
-<div>a
-<p>b</p></div>
-<div>
-a
-<p>b</p></div>
!! end
!! test
Substrings resembling wikitext in hrefs should not get nowiki escapes
!! options
parsoid=html2wt
+!! html
+<a rel="mw:WikiLink" href="./Foo''bar''baz">Foo''bar''baz</a>
!! wikitext
[[Foo''bar''baz]]
+!! end
+
+!! test
+Enforce single-line context in the serializer
+!! options
+parsoid=html2wt
!! html
-<a rel="mw:WikiLink" href="./Foo''bar''baz">Foo''bar''baz</a>
+<h2>testing
+123</h2>
+
+<ul><li>asd
+sdf</li></ul>
+!! wikitext
+== testing 123 ==
+
+* asd sdf
!! end
#-----------------------------
@@ -21706,6 +23600,15 @@ parsoid=html2wt
1. I/B quote minimization: wikitext-only tags should be combined
!! options
parsoid=html2wt
+!! html
+<p><i>A</i><i>B</i></p>
+<p><b>A</b><b>B</b></p>
+<p><i>A</i><b><i>B</i></b></p>
+<p><b>A</b><i><b>B</b></i></p>
+<p><b>A</b><i><b>B</b><b>C</b></i><b>D</b></p>
+<p><i><b>A</b></i><i><b>B</b></i></p>
+<p><i><b>A</b></i><b><i>B</i></b></p>
+<p><b><i>A</i></b><i><b>B</b></i></p>
!! wikitext
''AB''
@@ -21722,57 +23625,78 @@ parsoid=html2wt
'''''AB'''''
'''''AB'''''
-!! html
-<p><i>A</i><i>B</i></p>
-<p><b>A</b><b>B</b></p>
-<p><i>A</i><b><i>B</i></b></p>
-<p><b>A</b><i><b>B</b></i></p>
-<p><b>A</b><i><b>B</b><b>C</b></i><b>D</b></p>
-<p><i><b>A</b></i><i><b>B</b></i></p>
-<p><i><b>A</b></i><b><i>B</i></b></p>
-<p><b><i>A</i></b><i><b>B</b></i></p>
!! end
!! test
2. I/B quote minimization: wikitext and html tags should not be combined
!! options
parsoid=html2wt
-!! wikitext
-''A''<i>B</i>
-
-''A'''''<i>B</i>'''
!! html
<p><i>A</i><i data-parsoid='{"stx":"html"}'>B</i></p>
<p><i>A</i><b><i data-parsoid='{"stx":"html"}'>B</i></b></p>
+!! wikitext
+''A''<i>B</i>
+
+''A''<nowiki/>'''<i>B</i>'''
!! end
!! test
3. I/B quote minimization: templated content stops minimization
!! options
parsoid=html2wt
+!! html
+<p><i>A</i><i about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&#39;&#39;B&#39;&#39;"}},"i":0}}]}'>B</i>
+<p><i>A</i><b about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&#39;&#39;&#39;&#39;&#39;B&#39;&#39;&#39;&#39;&#39;"}},"i":0}}]}'><i>B</i></b>
!! wikitext
''A''{{echo|''B''}}
''A''{{echo|'''''B'''''}}
-!! html
-<p><i>A</i><i about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&#39;&#39;B&#39;&#39;"}},"i":0}}]}'>B</i>
-<p><i>A</i><b about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&#39;&#39;&#39;&#39;&#39;B&#39;&#39;&#39;&#39;&#39;"}},"i":0}}]}'><i>B</i></b>
!! end
!! test
4. I/B quote minimization: new content should be mimimized with adjacent old content
!! options
parsoid=html2wt
+!! html
+<p><i>A</i><i>B</i></p>
+<p><b>A</b><b>B</b></p>
+<p><i>A</i><b><i>B</i></b></p>
!! wikitext
''AB''
'''AB'''
''A'''B'''''
-!! html
-<p><i>A</i><i data-parsoid='{}'>B</i></p>
-<p><b data-parsoid='{}'>A</b><b>B</b></p>
-<p><i>A</i><b data-parsoid='{}'><i data-parsoid='{}'>B</i></b></p>
+!! end
+
+!! test
+5a. Merge adjacent quote nodes if they've been edited
+!! options
+parsoid={
+ "modes": ["wt2wt", "selser"],
+ "changes": [
+ ["p", "contents", "remove", ":contains('b')"]
+ ]
+}
+!! wikitext
+''a''b''c''
+!! wikitext/edited
+''ac''
+!! end
+
+!! test
+5b. Merge adjacent quote nodes if they've been edited
+!! options
+parsoid={
+ "modes": ["wt2wt", "selser"],
+ "changes": [
+ ["#x", "remove"]
+ ]
+}
+!! wikitext
+''a''<span id="x">b</span>''c''
+!! wikitext/edited
+''ac''
!! end
#------------------------------------
@@ -21796,16 +23720,6 @@ parsoid=html2wt
Magic words
!! options
parsoid=html2wt
-!! wikitext
-__TOC__
-__NOTOC__
-__FORCETOC__
-__INDEX__
-__NOINDEX__
-__NOGALLERY__
-__NOEDITSECTION__
-__NOTITLECONVERT__
-__NOCONTENTCONVERT__
!! html
<meta property='mw:PageProp/toc' />
<meta property='mw:PageProp/notoc' />
@@ -21817,12 +23731,34 @@ __NOCONTENTCONVERT__
<meta property='mw:PageProp/notitleconvert' />
<meta property='mw:PageProp/nocontentconvert' />
<meta property='mw:PageProp/unknownproperty' />
+!! wikitext
+__TOC__
+__NOTOC__
+__FORCETOC__
+__INDEX__
+__NOINDEX__
+__NOGALLERY__
+__NOEDITSECTION__
+__NOTITLECONVERT__
+__NOCONTENTCONVERT__
!! end
!! test
Consecutive <pre>s should not get merged
!! options
parsoid=html2wt,html2html
+!! html
+<pre>a</pre><pre>b</pre>
+
+<pre>c
+</pre><pre>
+d</pre>
+
+<pre>e
+
+</pre><pre>
+
+f</pre>
!! wikitext
a
@@ -21837,58 +23773,209 @@ parsoid=html2wt,html2html
f
-!! html
-<pre>a</pre><pre>b</pre>
-
-<pre>c
-</pre><pre>
-d</pre>
-
-<pre>e
-
-</pre><pre>
-
-f</pre>
!! end
!! test
Edited ISBN links not serializable as ISBN links should serialize as wikilinks
!! options
parsoid=html2wt
-!! wikitext
-[[Special:BookSources/1234567890|ISBN 1234567895]]
!! html
<a rel="mw:ExtLink" href="./Special:BookSources/1234567890">ISBN 1234567895</a>
+!! wikitext
+[[Special:BookSources/1234567890|ISBN 1234567895]]
!! end
!! test
Edited RFC links not serializable as RFC links should serialize as extlinks
!! options
parsoid=html2wt
-!! wikitext
-[//tools.ietf.org/html/rfc123 New RFC]
!! html
<a href="//tools.ietf.org/html/rfc123" rel="mw:ExtLink">New RFC</a>
+!! wikitext
+[//tools.ietf.org/html/rfc123 New RFC]
!! end
!! test
Edited PMID links not serializable as PMID links should serialize as extlinks
!! options
parsoid=html2wt
-!! wikitext
-[//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract New PMID]
!! html
<a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink">New PMID</a>
+!! wikitext
+[//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract New PMID]
+!! end
+
+!! test
+WTS of autolinks with trailing/surrounding context
+!! options
+parsoid=html2wt
+!! html/parsoid
+<p><a href="http://cscott.net">http://cscott.net</a><b>foo</b></p>
+<p><a href="http://cscott.net">http://cscott.net</a><b data-parsoid='{"stx":"html"}'>foo</b></p>
+<p><b><a href="http://cscott.net">http://cscott.net</a></b></p>
+<p><b><a href="http://cscott.net">http://cscott.net</a> </b></p>
+<p><b><a href="http://cscott.net">http://cscott.net</a>x</b></p>
+<p><a href="http://cscott.net">http://cscott.net</a>x</p>
+!! wikitext
+http://cscott.net<nowiki/>'''foo'''
+
+http://cscott.net<b>foo</b>
+
+'''http://cscott.net<nowiki/>'''
+
+'''http://cscott.net '''
+
+'''http://cscott.net<nowiki/>x'''
+
+http://cscott.net<nowiki/>x
+!! end
+
+!! test
+WTS of autolinks with nowikis (round-trip)
+!! wikitext
+x<nowiki/>http://cscott.net<nowiki/>x
+!! html/parsoid
+<p>x<a rel="mw:ExtLink" href="http://cscott.net">http://cscott.net</a>x</p>
+!! end
+
+# this is the "easy" test because it leaves in place all the
+# data-parsoid information indicating this is an autolink
+!! test
+WTS of autolinks with escapes (editing)
+!! options
+parsoid={
+ "modes": ["wt2wt"],
+ "changes": [
+ [ "meta", "remove" ]
+ ]
+}
+!! wikitext
+x<nowiki/>http://cscott.net<nowiki/>x
+!! wikitext/edited
+x<nowiki/>http://cscott.net<nowiki/>x
!! end
!! test
Edited Redirect link should emit a non-piped wikitext link
!! options
parsoid=html2wt
+!! html
+<link rel="mw:PageProp/redirect" href="Bar" data-parsoid='{"a":{"href":"./Foo"},"sa":{"href":"Foo"}}'>
!! wikitext
#REDIRECT [[Bar]]
+!! end
+
+!! test
+T75121: Infer extension name from typeOf if data-mw is not present
+!! options
+parsoid=html2wt
+!! html
+<div typeOf="mw:Extension/foo"></div>
+!! wikitext
+<foo />
+!! end
+
+# Note that the <p> wrapping isn't present in PHP parser output
+# The important thing for this test is that P-wrapping doesn't
+# interfere with the <nowiki> protection for leading - in <td>
+# (which isn't necessary for <th>).
+!! test
+T88318: p-wrapped dash in table.
+!! options
+parsoid=html2wt,wt2wt
+!! html/parsoid
+<table><tbody>
+<tr><th><p>-</p></th><th><p>- </p></th></tr>
+<tr><td><p>-</p></td><td><p>- </p></td></tr>
+<tr><td><small>-</small></td><td><br/><p>-</p></td><td><br/>-</td></tr>
+</tbody></table>
+!! wikitext
+{|
+!-
+!-
+|-
+|<nowiki>-</nowiki>
+|<nowiki>- </nowiki>
+|-
+|<small>-</small>
+|<br>
+-
+|<br>
+-
+|}
+!! html/php+tidy
+<table>
+<tr>
+<th>-</th>
+<th>-</th>
+</tr>
+<tr>
+<td>-</td>
+<td>-</td>
+</tr>
+<tr>
+<td><small>-</small></td>
+<td><br />
+<p>-</p>
+</td>
+<td><br />
+<p>-</p>
+</td>
+</tr>
+</table>
+!! end
+
+!! test
+HTML id attribute with Parsoid-like element ids should not be serialized to wikitext
+!! options
+parsoid=html2wt
+!! html
+<table id='mwAb'>
+<td id='mwAc'>foo</td>
+<td id='serialize-this'>bar</td>
+</table>
+!! wikitext
+{|
+|foo
+| id="serialize-this" |bar
+|}
+!! end
+
+!! test
+Parsoid-like element ids should not be serialized to wikitext unless shadowed
+!! options
+parsoid=html2wt
!! html
-<link rel="mw:PageProp/redirect" href="Bar" data-parsoid='{"src":"#REDIRECT ","a":{"href":"./Foo"},"sa":{"href":"Foo"}}'>
+<div id="mwAQ" data-parsoid='{"stx":"html","a":{"id":"mwAQ"},"sa":{"id":"hello"}}'>ok</div>
+!! wikitext
+<div id="hello">ok</div>
+!! end
+
+!! test
+WTS change modes
+!! options
+parsoid={
+ "modes": ["wt2wt"],
+ "changes": [
+ [ "#xyz", "before", "<b>before</b> stuff " ],
+ [ "#xyz", "after", " stuff <i>after</i>" ],
+ [ "#xyz", "html", "x <b>y</b> z" ]
+ ]
+}
+!! wikitext
+<span id="xyz">hello</span>
+!! wikitext/edited
+'''before''' stuff <span id="xyz">x '''y''' z</span> stuff ''after''
+!! end
+
+!! test
+Never serialize a-tag as html, regardless of what data-parsoid has to say
+!! options
+parsoid=html2wt
+!! html
+<a rel="mw:WikiLink" href="./Foo" title="Foo" data-parsoid='{"stx":"html"}'>Foo</a>
+!! wikitext
+[[Foo]]
!! end
# -----------------------------------------------------------------
@@ -21896,6 +23983,53 @@ parsoid=html2wt
# 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
+1. Selser: New comments should not be lost
+!! options
+parsoid={
+ "modes": ["selser"],
+ "changes": [
+ [ "#a", "after", "<!--c1-->" ],
+ [ "#b", "before", "<!--c2-->" ]
+ ]
+}
+!! wikitext
+<span id="a">a</span>
+
+<span id="b">b</span>
+!! wikitext/edited
+<span id="a">a</span><!--c1-->
+
+<!--c2--><span id="b">b</span>
+!! end
+
+## T89383
+!! test
+2. Selser: Check for validity of DSR before using it
+!! options
+parsoid={
+ "modes": ["selser"],
+ "changes": [
+ [ "#a", "before", "<meta property='mw:PageProp/displaytitle' content='foo'>" ]
+ ]
+}
+!! wikitext
+<span id="a">a</span>
+!! wikitext/edited
+{{DISPLAYTITLE:foo}}
+<span id="a">a</span>
+!! end
+
+
TODO:
more images
more tables
diff --git a/tests/parser/parserTestsParserHook.php b/tests/parser/parserTestsParserHook.php
index c8b3e897..221fc79a 100644
--- a/tests/parser/parserTestsParserHook.php
+++ b/tests/parser/parserTestsParserHook.php
@@ -29,6 +29,7 @@ class ParserTestParserHook {
static function setup( &$parser ) {
$parser->setHook( 'tag', array( __CLASS__, 'dumpHook' ) );
+ $parser->setHook( 'tåg', array( __CLASS__, 'dumpHook' ) );
$parser->setHook( 'statictag', array( __CLASS__, 'staticTagHook' ) );
return true;
}
diff --git a/tests/parser/preprocess/All_system_messages.expected b/tests/parser/preprocess/All_system_messages.expected
index 078d8f0d..2ee805e0 100644
--- a/tests/parser/preprocess/All_system_messages.expected
+++ b/tests/parser/preprocess/All_system_messages.expected
@@ -2207,13 +2207,6 @@ Log in
&lt;/td&gt;&lt;td&gt;
<template lineStart="1"><title>int:Login</title></template>
&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
-[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Loginend&amp;action=edit loginend]&lt;br&gt;
-[[MediaWiki_talk:Loginend|Talk]]
-&lt;/td&gt;&lt;td&gt;
-&amp;amp;nbsp;
-&lt;/td&gt;&lt;td&gt;
-<template lineStart="1"><title>int:Loginend</title></template>
-&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;
[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Loginerror&amp;action=edit loginerror]&lt;br&gt;
[[MediaWiki_talk:Loginerror|Talk]]
&lt;/td&gt;&lt;td&gt;
diff --git a/tests/parser/preprocess/All_system_messages.txt b/tests/parser/preprocess/All_system_messages.txt
index 3c30da94..4a30f56f 100644
--- a/tests/parser/preprocess/All_system_messages.txt
+++ b/tests/parser/preprocess/All_system_messages.txt
@@ -2207,13 +2207,6 @@ Log in
</td><td>
{{int:Login}}
</td></tr><tr><td>
-[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Loginend&action=edit loginend]<br>
-[[MediaWiki_talk:Loginend|Talk]]
-</td><td>
-&amp;nbsp;
-</td><td>
-{{int:Loginend}}
-</td></tr><tr><td>
[http://tl.wiktionary.org/w/wiki.phtml?title=MediaWiki:Loginerror&action=edit loginerror]<br>
[[MediaWiki_talk:Loginerror|Talk]]
</td><td>
diff --git a/tests/parserTests.php b/tests/parserTests.php
index 9965c438..5d21319b 100644
--- a/tests/parserTests.php
+++ b/tests/parserTests.php
@@ -70,10 +70,6 @@ if ( $wgDBtype == 'sqlite' ) {
}
}
-# There is a convention that the parser should never
-# refer to $wgTitle directly, but instead use the title
-# passed to it.
-$wgTitle = Title::newFromText( 'Parser test script do not use' );
$tester = new ParserTest( $options );
if ( isset( $options['file'] ) ) {
diff --git a/tests/phpunit/LessFileCompilationTest.php b/tests/phpunit/LessFileCompilationTest.php
index 71e0f4b2..df4690a4 100644
--- a/tests/phpunit/LessFileCompilationTest.php
+++ b/tests/phpunit/LessFileCompilationTest.php
@@ -38,7 +38,7 @@ class LessFileCompilationTest extends ResourceLoaderTestCase {
"$thisString must refer to a readable file"
);
- $rlContext = static::getResourceLoaderContext();
+ $rlContext = $this->getResourceLoaderContext();
// Bleh
$method = new ReflectionMethod( $this->module, 'getLessCompiler' );
diff --git a/tests/phpunit/Makefile b/tests/phpunit/Makefile
index c3e2a303..a33b86a3 100644
--- a/tests/phpunit/Makefile
+++ b/tests/phpunit/Makefile
@@ -1,4 +1,4 @@
-.PHONY: help test phpunit install coverage warning destructive parser noparser safe databaseless list-groups
+.PHONY: help test phpunit coverage warning destructive parser noparser safe databaseless list-groups
.DEFAULT: warning
SHELL = /bin/sh
@@ -35,9 +35,6 @@ destructive: phpunit
phpunit:
${PU}
-install:
- ./install-phpunit.sh
-
tap:
${PU} --tap
@@ -83,7 +80,7 @@ help:
# You will need the Xdebug PHP extension for the later.
# [no]parser Skip or only run Parser tests
#
- # list-groups List availabe Tests groups.
+ # list-groups List available Tests groups.
#
# Options:
# CONFIG_FILE Path to a PHPUnit configuration file (default: suite.xml)
diff --git a/tests/phpunit/MediaWikiTestCase.php b/tests/phpunit/MediaWikiTestCase.php
index 995853ea..72cac051 100644
--- a/tests/phpunit/MediaWikiTestCase.php
+++ b/tests/phpunit/MediaWikiTestCase.php
@@ -104,7 +104,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
ObjectCache::$instances[CACHE_DB] = new HashBagOStuff;
$needsResetDB = false;
- $logName = get_class( $this ) . '::' . $this->getName( false );
if ( $this->needsDB() ) {
// set up a DB connection for this test to use
@@ -117,34 +116,22 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
$this->checkDbIsSupported();
if ( !self::$dbSetup ) {
- wfProfileIn( $logName . ' (clone-db)' );
-
// switch to a temporary clone of the database
self::setupTestDB( $this->db, $this->dbPrefix() );
if ( ( $this->db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
$this->resetDB();
}
-
- wfProfileOut( $logName . ' (clone-db)' );
}
-
- wfProfileIn( $logName . ' (prepare-db)' );
$this->addCoreDBData();
$this->addDBData();
- wfProfileOut( $logName . ' (prepare-db)' );
-
$needsResetDB = true;
}
- wfProfileIn( $logName );
parent::run( $result );
- wfProfileOut( $logName );
if ( $needsResetDB ) {
- wfProfileIn( $logName . ' (reset-db)' );
$this->resetDB();
- wfProfileOut( $logName . ' (reset-db)' );
}
}
@@ -198,7 +185,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
}
protected function setUp() {
- wfProfileIn( __METHOD__ );
parent::setUp();
$this->called['setUp'] = true;
@@ -223,12 +209,15 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
$this->db->ignoreErrors( false );
}
- wfProfileOut( __METHOD__ );
+ DeferredUpdates::clearPendingUpdates();
+
}
- protected function tearDown() {
- wfProfileIn( __METHOD__ );
+ protected function addTmpFiles( $files ) {
+ $this->tmpFiles = array_merge( $this->tmpFiles, (array)$files );
+ }
+ protected function tearDown() {
$this->called['tearDown'] = true;
// Cleaning up temporary files
foreach ( $this->tmpFiles as $fileName ) {
@@ -271,7 +260,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
}
parent::tearDown();
- wfProfileOut( __METHOD__ );
}
/**
@@ -429,6 +417,35 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
}
/**
+ * Insert a new page.
+ *
+ * Should be called from addDBData().
+ *
+ * @since 1.25
+ * @param string $pageName Page name
+ * @param string $text Page's content
+ * @return array Title object and page id
+ */
+ protected function insertPage( $pageName, $text = 'Sample page for unit test.' ) {
+ $title = Title::newFromText( $pageName, 0 );
+
+ $user = User::newFromName( 'UTSysop' );
+ $comment = __METHOD__ . ': Sample page for unit test.';
+
+ // Avoid memory leak...?
+ // LinkCache::singleton()->clear();
+ // Maybe. But doing this absolutely breaks $title->isRedirect() when called during unit tests....
+
+ $page = WikiPage::factory( $title );
+ $page->doEditContent( ContentHandler::makeContent( $text, $title ), $comment, 0, false, $user );
+
+ return array(
+ 'title' => $title,
+ 'id' => $page->getId(),
+ );
+ }
+
+ /**
* Stub. If a test needs to add additional data to the database, it should
* implement this method and do so
*
@@ -453,7 +470,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
'page_namespace' => 0,
'page_title' => ' ',
'page_restrictions' => null,
- 'page_counter' => 0,
'page_is_redirect' => 0,
'page_is_new' => 0,
'page_random' => 0,
@@ -464,7 +480,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
User::resetIdByNameCache();
- //Make sysop user
+ // Make sysop user
$user = User::newFromName( 'UTSysop' );
if ( $user->idForName() == 0 ) {
@@ -476,7 +492,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
$user->saveSettings();
}
- //Make 1 page with 1 revision
+ // Make 1 page with 1 revision
$page = WikiPage::factory( Title::newFromText( 'UTPage' ) );
if ( $page->getId() == 0 ) {
$page->doEditContent(
@@ -484,7 +500,8 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
'UTPageSummary',
EDIT_NEW,
false,
- User::newFromName( 'UTSysop' ) );
+ $user
+ );
}
}
@@ -603,7 +620,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
if ( isset( $compatibility[$func] ) ) {
return call_user_func_array( array( $this, $compatibility[$func] ), $args );
} else {
- throw new MWException( "Called non-existant $func method on "
+ throw new MWException( "Called non-existent $func method on "
. get_class( $this ) );
}
}
@@ -614,7 +631,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
* @param string $msg
*/
private function assertEmpty2( $value, $msg ) {
- return $this->assertTrue( $value == '', $msg );
+ $this->assertTrue( $value == '', $msg );
}
private static function unprefixTable( $tableName ) {
@@ -630,7 +647,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
/**
* @since 1.18
*
- * @param DataBaseBase $db
+ * @param DatabaseBase $db
*
* @return array
*/
@@ -753,7 +770,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
/**
* Utility method taking an array of elements and wrapping
- * each element in it's own array. Useful for data providers
+ * each element in its own array. Useful for data providers
* that only return a single argument.
*
* @since 1.20
@@ -1120,9 +1137,23 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
}
/**
+ * @param array $matcher
+ * @param string $actual
+ * @param bool $isHtml
+ *
+ * @return bool
+ */
+ private static function tagMatch( $matcher, $actual, $isHtml = true ) {
+ $dom = PHPUnit_Util_XML::load( $actual, $isHtml );
+ $tags = PHPUnit_Util_XML::findNodes( $dom, $matcher, $isHtml );
+ return count( $tags ) > 0 && $tags[0] instanceof DOMNode;
+ }
+
+ /**
* Note: we are overriding this method to remove the deprecated error
* @see https://bugzilla.wikimedia.org/show_bug.cgi?id=69505
* @see https://github.com/sebastianbergmann/phpunit/issues/1292
+ * @deprecated
*
* @param array $matcher
* @param string $actual
@@ -1132,10 +1163,21 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
public static function assertTag( $matcher, $actual, $message = '', $isHtml = true ) {
//trigger_error(__METHOD__ . ' is deprecated', E_USER_DEPRECATED);
- $dom = PHPUnit_Util_XML::load( $actual, $isHtml );
- $tags = PHPUnit_Util_XML::findNodes( $dom, $matcher, $isHtml );
- $matched = count( $tags ) > 0 && $tags[0] instanceof DOMNode;
+ self::assertTrue( self::tagMatch( $matcher, $actual, $isHtml ), $message );
+ }
+
+ /**
+ * @see MediaWikiTestCase::assertTag
+ * @deprecated
+ *
+ * @param array $matcher
+ * @param string $actual
+ * @param string $message
+ * @param bool $isHtml
+ */
+ public static function assertNotTag( $matcher, $actual, $message = '', $isHtml = true ) {
+ //trigger_error(__METHOD__ . ' is deprecated', E_USER_DEPRECATED);
- self::assertTrue( $matched, $message );
+ self::assertFalse( self::tagMatch( $matcher, $actual, $isHtml ), $message );
}
}
diff --git a/tests/phpunit/ResourceLoaderTestCase.php b/tests/phpunit/ResourceLoaderTestCase.php
index f5f302e0..deecb31e 100644
--- a/tests/phpunit/ResourceLoaderTestCase.php
+++ b/tests/phpunit/ResourceLoaderTestCase.php
@@ -1,7 +1,12 @@
<?php
abstract class ResourceLoaderTestCase extends MediaWikiTestCase {
- protected static function getResourceLoaderContext( $lang = 'en' ) {
+ /**
+ * @param string $lang
+ * @param string $dir
+ * @return ResourceLoaderContext
+ */
+ protected function getResourceLoaderContext( $lang = 'en', $dir = 'ltr' ) {
$resourceLoader = new ResourceLoader();
$request = new FauxRequest( array(
'lang' => $lang,
@@ -10,7 +15,14 @@ abstract class ResourceLoaderTestCase extends MediaWikiTestCase {
'skin' => 'vector',
'target' => 'test',
) );
- return new ResourceLoaderContext( $resourceLoader, $request );
+ $ctx = $this->getMockBuilder( 'ResourceLoaderContext' )
+ ->setConstructorArgs( array( $resourceLoader, $request ) )
+ ->setMethods( array( 'getDirection' ) )
+ ->getMock();
+ $ctx->expects( $this->any() )->method( 'getDirection' )->will(
+ $this->returnValue( $dir )
+ );
+ return $ctx;
}
protected function setUp() {
@@ -86,10 +98,3 @@ class ResourceLoaderTestModule extends ResourceLoaderModule {
class ResourceLoaderFileModuleTestModule extends ResourceLoaderFileModule {
}
-
-class ResourceLoaderWikiModuleTestModule extends ResourceLoaderWikiModule {
- // Override expected via PHPUnit mocks and stubs
- protected function getPages( ResourceLoaderContext $context ) {
- return array();
- }
-}
diff --git a/tests/phpunit/bootstrap.php b/tests/phpunit/bootstrap.php
index 121aade9..a5c8ef61 100644
--- a/tests/phpunit/bootstrap.php
+++ b/tests/phpunit/bootstrap.php
@@ -15,14 +15,7 @@ EOF;
}
class MediaWikiPHPUnitBootstrap {
-
- public function __construct() {
- wfProfileIn( __CLASS__ );
- }
-
public function __destruct() {
- wfProfileOut( __CLASS__ );
-
// Return to real wiki db, so profiling data is preserved
MediaWikiTestCase::teardownTestDB();
diff --git a/tests/phpunit/data/composer/composer.json b/tests/phpunit/data/composer/composer.json
new file mode 100644
index 00000000..bcd196f4
--- /dev/null
+++ b/tests/phpunit/data/composer/composer.json
@@ -0,0 +1,48 @@
+{
+ "name": "mediawiki/core",
+ "description": "Free software wiki application developed by the Wikimedia Foundation and others",
+ "keywords": ["mediawiki", "wiki"],
+ "homepage": "https://www.mediawiki.org/",
+ "authors": [
+ {
+ "name": "MediaWiki Community",
+ "homepage": "https://www.mediawiki.org/wiki/Special:Version/Credits"
+ }
+ ],
+ "license": "GPL-2.0",
+ "support": {
+ "issues": "https://bugzilla.wikimedia.org/",
+ "irc": "irc://irc.freenode.net/mediawiki",
+ "wiki": "https://www.mediawiki.org/"
+ },
+ "require": {
+ "leafo/lessphp": "0.5.0",
+ "php": ">=5.3.3",
+ "psr/log": "1.0.0",
+ "cssjanus/cssjanus": "1.1.1",
+ "cdb/cdb": "1.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "*"
+ },
+ "suggest": {
+ "ext-fileinfo": "*",
+ "ext-mbstring": "*",
+ "ext-wikidiff2": "*",
+ "ext-apc": "*",
+ "monolog/monolog": "*"
+ },
+ "autoload": {
+ "psr-0": {
+ "ComposerHookHandler": "includes/composer"
+ }
+ },
+ "scripts": {
+ "pre-update-cmd": "ComposerHookHandler::onPreUpdate",
+ "pre-install-cmd": "ComposerHookHandler::onPreInstall"
+ },
+ "config": {
+ "prepend-autoloader": false,
+ "optimize-autoloader": true
+ }
+}
diff --git a/tests/phpunit/data/composer/composer.lock b/tests/phpunit/data/composer/composer.lock
new file mode 100644
index 00000000..cae6a478
--- /dev/null
+++ b/tests/phpunit/data/composer/composer.lock
@@ -0,0 +1,1195 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "This file is @generated automatically"
+ ],
+ "hash": "a3bb80b0ac4c4a31e52574d48c032923",
+ "packages": [
+ {
+ "name": "composer/installers",
+ "version": "v1.0.19",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/installers.git",
+ "reference": "89d77bfbee79e16653f7162c86e602cc188471db"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/installers/zipball/89d77bfbee79e16653f7162c86e602cc188471db",
+ "reference": "89d77bfbee79e16653f7162c86e602cc188471db",
+ "shasum": ""
+ },
+ "replace": {
+ "roundcube/plugin-installer": "*",
+ "shama/baton": "*"
+ },
+ "require-dev": {
+ "composer/composer": "1.0.*@dev",
+ "phpunit/phpunit": "4.1.*"
+ },
+ "type": "composer-installer",
+ "extra": {
+ "class": "Composer\\Installers\\Installer",
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Composer\\Installers\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kyle Robinson Young",
+ "email": "kyle@dontkry.com",
+ "homepage": "https://github.com/shama"
+ }
+ ],
+ "description": "A multi-framework Composer library installer",
+ "homepage": "http://composer.github.com/installers/",
+ "keywords": [
+ "Craft",
+ "Dolibarr",
+ "Hurad",
+ "MODX Evo",
+ "OXID",
+ "Thelia",
+ "WolfCMS",
+ "agl",
+ "annotatecms",
+ "bitrix",
+ "cakephp",
+ "chef",
+ "codeigniter",
+ "concrete5",
+ "croogo",
+ "dokuwiki",
+ "drupal",
+ "elgg",
+ "fuelphp",
+ "grav",
+ "installer",
+ "joomla",
+ "kohana",
+ "laravel",
+ "lithium",
+ "magento",
+ "mako",
+ "mediawiki",
+ "modulework",
+ "moodle",
+ "phpbb",
+ "piwik",
+ "ppi",
+ "puppet",
+ "roundcube",
+ "shopware",
+ "silverstripe",
+ "symfony",
+ "typo3",
+ "wordpress",
+ "zend",
+ "zikula"
+ ],
+ "time": "2014-11-29 01:29:17"
+ },
+ {
+ "name": "cssjanus/cssjanus",
+ "version": "v1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/cssjanus/php-cssjanus.git",
+ "reference": "62a9c32e6e140de09082b40a6e99d868ad14d4e0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/cssjanus/php-cssjanus/zipball/62a9c32e6e140de09082b40a6e99d868ad14d4e0",
+ "reference": "62a9c32e6e140de09082b40a6e99d868ad14d4e0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "0.8.*",
+ "phpunit/phpunit": "3.7.*",
+ "squizlabs/php_codesniffer": "1.*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "description": "Convert CSS stylesheets between left-to-right and right-to-left.",
+ "time": "2014-11-14 20:00:50"
+ },
+ {
+ "name": "leafo/lessphp",
+ "version": "v0.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/leafo/lessphp.git",
+ "reference": "0f5a7f5545d2bcf4e9fad9a228c8ad89cc9aa283"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/leafo/lessphp/zipball/0f5a7f5545d2bcf4e9fad9a228c8ad89cc9aa283",
+ "reference": "0f5a7f5545d2bcf4e9fad9a228c8ad89cc9aa283",
+ "shasum": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.4.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "lessc.inc.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "Leaf Corcoran",
+ "email": "leafot@gmail.com",
+ "homepage": "http://leafo.net"
+ }
+ ],
+ "description": "lessphp is a compiler for LESS written in PHP.",
+ "homepage": "http://leafo.net/lessphp/",
+ "time": "2014-11-24 18:39:20"
+ },
+ {
+ "name": "mediawiki/translate",
+ "version": "2014.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/wikimedia/mediawiki-extensions-Translate.git",
+ "reference": "2bc100763f3150380412faceea258c7378ce7ea0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/wikimedia/mediawiki-extensions-Translate/zipball/2bc100763f3150380412faceea258c7378ce7ea0",
+ "reference": "2bc100763f3150380412faceea258c7378ce7ea0",
+ "shasum": ""
+ },
+ "require": {
+ "composer/installers": ">=1.0.1",
+ "mediawiki/universal-language-selector": "*",
+ "php": ">=5.3.0"
+ },
+ "suggest": {
+ "mediawiki/babel": "Users can easily indicate their language proficiency on their user page",
+ "mediawiki/translation-notifications": "Manage communication with translators",
+ "mustangostang/spyc": "More recent version of the bundled spyc library"
+ },
+ "type": "mediawiki-extension",
+ "autoload": {
+ "files": [
+ "Translate.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+"
+ ],
+ "authors": [
+ {
+ "name": "Niklas Laxström",
+ "email": "niklas.laxstrom@gmail.com",
+ "role": "Lead nitpicker"
+ },
+ {
+ "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",
+ "homepage": "https://www.mediawiki.org/wiki/Extension:Translate",
+ "keywords": [
+ "g11n",
+ "i18n",
+ "internationalization",
+ "l10n",
+ "localization",
+ "m17n",
+ "mediawiki",
+ "translatewiki.net",
+ "translation"
+ ],
+ "time": "2014-12-30 15:21:24"
+ },
+ {
+ "name": "mediawiki/universal-language-selector",
+ "version": "2014.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/wikimedia/mediawiki-extensions-UniversalLanguageSelector.git",
+ "reference": "f730b0f47e2828001c1e03ec40d4681bfb0bff2d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/wikimedia/mediawiki-extensions-UniversalLanguageSelector/zipball/f730b0f47e2828001c1e03ec40d4681bfb0bff2d",
+ "reference": "f730b0f47e2828001c1e03ec40d4681bfb0bff2d",
+ "shasum": ""
+ },
+ "require": {
+ "composer/installers": ">=1.0.1",
+ "php": ">=5.3.0"
+ },
+ "suggest": {
+ "mediawiki/cldr": "Language names in all languages"
+ },
+ "type": "mediawiki-extension",
+ "autoload": {
+ "files": [
+ "UniversalLanguageSelector.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+",
+ "MIT"
+ ],
+ "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.",
+ "homepage": "https://www.mediawiki.org/wiki/Extension:UniversalLanguageSelector",
+ "keywords": [
+ "Input methods",
+ "Language selection",
+ "Web fonts",
+ "mediawiki"
+ ],
+ "time": "2014-12-30 15:21:25"
+ },
+ {
+ "name": "oojs/oojs-ui",
+ "version": "v0.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/wikimedia/oojs-ui.git",
+ "reference": "50fa12637ad377f00bdbf1913406a3bfe9c1689e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/wikimedia/oojs-ui/zipball/50fa12637ad377f00bdbf1913406a3bfe9c1689e",
+ "reference": "50fa12637ad377f00bdbf1913406a3bfe9c1689e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "php/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "homepage": "https://www.mediawiki.org/wiki/OOjs_UI",
+ "time": "2014-12-16 20:50:05"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
+ "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
+ "shasum": ""
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "Psr\\Log\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "time": "2012-12-21 11:40:51"
+ },
+ {
+ "name": "wikimedia/cdb",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/wikimedia/cdb.git",
+ "reference": "3b7d5366c88eccf2517ebac57c59eb557c82f46c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/wikimedia/cdb/zipball/3b7d5366c88eccf2517ebac57c59eb557c82f46c",
+ "reference": "3b7d5366c88eccf2517ebac57c59eb557c82f46c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "*"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Tim Starling",
+ "email": "tstarling@wikimedia.org"
+ },
+ {
+ "name": "Chad Horohoe",
+ "email": "chad@wikimedia.org"
+ }
+ ],
+ "description": "Constant Database (CDB) wrapper library for PHP. Provides pure-PHP fallback when dba_* functions are absent.",
+ "homepage": "https://www.mediawiki.org/wiki/CDB",
+ "time": "2014-12-08 19:26:44"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "doctrine/instantiator",
+ "version": "1.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/instantiator.git",
+ "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119",
+ "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3,<8.0-DEV"
+ },
+ "require-dev": {
+ "athletic/athletic": "~0.1.8",
+ "ext-pdo": "*",
+ "ext-phar": "*",
+ "phpunit/phpunit": "~4.0",
+ "squizlabs/php_codesniffer": "2.0.*@ALPHA"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Instantiator\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com",
+ "homepage": "http://ocramius.github.com/"
+ }
+ ],
+ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+ "homepage": "https://github.com/doctrine/instantiator",
+ "keywords": [
+ "constructor",
+ "instantiate"
+ ],
+ "time": "2014-10-13 12:58:55"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "2.0.14",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "ca158276c1200cc27f5409a5e338486bc0b4fc94"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca158276c1200cc27f5409a5e338486bc0b4fc94",
+ "reference": "ca158276c1200cc27f5409a5e338486bc0b4fc94",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "phpunit/php-file-iterator": "~1.3",
+ "phpunit/php-text-template": "~1.2",
+ "phpunit/php-token-stream": "~1.3",
+ "sebastian/environment": "~1.0",
+ "sebastian/version": "~1.0"
+ },
+ "require-dev": {
+ "ext-xdebug": ">=2.1.4",
+ "phpunit/phpunit": "~4.1"
+ },
+ "suggest": {
+ "ext-dom": "*",
+ "ext-xdebug": ">=2.2.1",
+ "ext-xmlwriter": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "include-path": [
+ ""
+ ],
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "time": "2014-12-26 13:28:33"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "1.3.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb",
+ "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "File/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "include-path": [
+ ""
+ ],
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "time": "2013-10-10 15:34:57"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a",
+ "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "Text/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "include-path": [
+ ""
+ ],
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "time": "2014-01-30 17:20:04"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "1.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
+ "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "PHP/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "include-path": [
+ ""
+ ],
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "time": "2013-08-02 07:42:54"
+ },
+ {
+ "name": "phpunit/php-token-stream",
+ "version": "1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-token-stream.git",
+ "reference": "f8d5d08c56de5cfd592b3340424a81733259a876"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/f8d5d08c56de5cfd592b3340424a81733259a876",
+ "reference": "f8d5d08c56de5cfd592b3340424a81733259a876",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Wrapper around PHP's tokenizer extension.",
+ "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
+ "keywords": [
+ "tokenizer"
+ ],
+ "time": "2014-08-31 06:12:13"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "4.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "6a5e49a86ce5e33b8d0657abe145057fc513543a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6a5e49a86ce5e33b8d0657abe145057fc513543a",
+ "reference": "6a5e49a86ce5e33b8d0657abe145057fc513543a",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-pcre": "*",
+ "ext-reflection": "*",
+ "ext-spl": "*",
+ "php": ">=5.3.3",
+ "phpunit/php-code-coverage": "~2.0",
+ "phpunit/php-file-iterator": "~1.3.2",
+ "phpunit/php-text-template": "~1.2",
+ "phpunit/php-timer": "~1.0.2",
+ "phpunit/phpunit-mock-objects": "~2.3",
+ "sebastian/comparator": "~1.0",
+ "sebastian/diff": "~1.1",
+ "sebastian/environment": "~1.1",
+ "sebastian/exporter": "~1.0",
+ "sebastian/global-state": "~1.0",
+ "sebastian/version": "~1.0",
+ "symfony/yaml": "~2.0"
+ },
+ "suggest": {
+ "phpunit/php-invoker": "~1.1"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.4.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "time": "2014-12-28 07:57:05"
+ },
+ {
+ "name": "phpunit/phpunit-mock-objects",
+ "version": "2.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
+ "reference": "c63d2367247365f688544f0d500af90a11a44c65"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c63d2367247365f688544f0d500af90a11a44c65",
+ "reference": "c63d2367247365f688544f0d500af90a11a44c65",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "~1.0,>=1.0.1",
+ "php": ">=5.3.3",
+ "phpunit/php-text-template": "~1.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.3"
+ },
+ "suggest": {
+ "ext-soap": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Mock Object library for PHPUnit",
+ "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
+ "keywords": [
+ "mock",
+ "xunit"
+ ],
+ "time": "2014-10-03 05:12:11"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "c484a80f97573ab934e37826dba0135a3301b26a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/c484a80f97573ab934e37826dba0135a3301b26a",
+ "reference": "c484a80f97573ab934e37826dba0135a3301b26a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "sebastian/diff": "~1.1",
+ "sebastian/exporter": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "http://www.github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "time": "2014-11-16 21:32:38"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "5843509fed39dee4b356a306401e9dd1a931fec7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/5843509fed39dee4b356a306401e9dd1a931fec7",
+ "reference": "5843509fed39dee4b356a306401e9dd1a931fec7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "http://www.github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff"
+ ],
+ "time": "2014-08-15 10:29:00"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e6c71d918088c251b181ba8b3088af4ac336dd7",
+ "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "http://www.github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "time": "2014-10-25 08:00:45"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "c7d59948d6e82818e1bdff7cadb6c34710eb7dc0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c7d59948d6e82818e1bdff7cadb6c34710eb7dc0",
+ "reference": "c7d59948d6e82818e1bdff7cadb6c34710eb7dc0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "http://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "time": "2014-09-10 00:51:36"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01",
+ "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.2"
+ },
+ "suggest": {
+ "ext-uopz": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "http://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "time": "2014-10-06 09:23:50"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "1.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/a77d9123f8e809db3fbdea15038c27a95da4058b",
+ "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b",
+ "shasum": ""
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "time": "2014-12-15 14:25:24"
+ },
+ {
+ "name": "symfony/yaml",
+ "version": "v2.6.1",
+ "target-dir": "Symfony/Component/Yaml",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/Yaml.git",
+ "reference": "3346fc090a3eb6b53d408db2903b241af51dcb20"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/Yaml/zipball/3346fc090a3eb6b53d408db2903b241af51dcb20",
+ "reference": "3346fc090a3eb6b53d408db2903b241af51dcb20",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Symfony\\Component\\Yaml\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Symfony Community",
+ "homepage": "http://symfony.com/contributors"
+ },
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ }
+ ],
+ "description": "Symfony Yaml Component",
+ "homepage": "http://symfony.com",
+ "time": "2014-12-02 20:19:20"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "platform": {
+ "php": ">=5.3.3"
+ },
+ "platform-dev": []
+}
diff --git a/tests/phpunit/data/composer/new-composer.json b/tests/phpunit/data/composer/new-composer.json
new file mode 100644
index 00000000..0634c2dd
--- /dev/null
+++ b/tests/phpunit/data/composer/new-composer.json
@@ -0,0 +1,48 @@
+{
+ "name": "mediawiki/core",
+ "description": "Free software wiki application developed by the Wikimedia Foundation and others",
+ "keywords": ["mediawiki", "wiki"],
+ "homepage": "https://www.mediawiki.org/",
+ "authors": [
+ {
+ "name": "MediaWiki Community",
+ "homepage": "https://www.mediawiki.org/wiki/Special:Version/Credits"
+ }
+ ],
+ "license": "GPL-2.0",
+ "support": {
+ "issues": "https://bugzilla.wikimedia.org/",
+ "irc": "irc://irc.freenode.net/mediawiki",
+ "wiki": "https://www.mediawiki.org/"
+ },
+ "require": {
+ "leafo/lessphp": "0.5.0",
+ "php": ">=5.3.3",
+ "psr/log": "1.0.0",
+ "cssjanus/cssjanus": "1.1.1",
+ "wikimedia/cdb": "1.0.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "*"
+ },
+ "suggest": {
+ "ext-fileinfo": "*",
+ "ext-mbstring": "*",
+ "ext-wikidiff2": "*",
+ "ext-apc": "*",
+ "monolog/monolog": "*"
+ },
+ "autoload": {
+ "psr-0": {
+ "ComposerHookHandler": "includes/composer"
+ }
+ },
+ "scripts": {
+ "pre-update-cmd": "ComposerHookHandler::onPreUpdate",
+ "pre-install-cmd": "ComposerHookHandler::onPreInstall"
+ },
+ "config": {
+ "prepend-autoloader": false,
+ "optimize-autoloader": true
+ }
+}
diff --git a/tests/phpunit/data/cssmin/circle.svg b/tests/phpunit/data/cssmin/circle.svg
new file mode 100644
index 00000000..6b7d1afd
--- /dev/null
+++ b/tests/phpunit/data/cssmin/circle.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8">
+<circle cx="4" cy="4" r="2"/>
+</svg>
diff --git a/tests/phpunit/data/gitinfo/info-testValidJsonData.json b/tests/phpunit/data/gitinfo/info-testValidJsonData.json
index e955a2b6..8cf21bda 100644
--- a/tests/phpunit/data/gitinfo/info-testValidJsonData.json
+++ b/tests/phpunit/data/gitinfo/info-testValidJsonData.json
@@ -1 +1,7 @@
-{ "head": "refs/heads/master", "headSHA1": "0123456789abcdef0123456789abcdef01234567", "headCommitDate": "1070884800", "branch": "master", "remoteURL": "https://gerrit.wikimedia.org/r/mediawiki/core" } \ No newline at end of file
+{
+ "head": "refs/heads/master",
+ "headSHA1": "0123456789abcdef0123456789abcdef01234567",
+ "headCommitDate": "1070884800",
+ "branch": "master",
+ "remoteURL": "https://gerrit.wikimedia.org/r/mediawiki/core"
+}
diff --git a/tests/phpunit/data/helpers/WellProtectedClass.php b/tests/phpunit/data/helpers/WellProtectedClass.php
new file mode 100644
index 00000000..99c7f642
--- /dev/null
+++ b/tests/phpunit/data/helpers/WellProtectedClass.php
@@ -0,0 +1,21 @@
+<?php
+
+class WellProtectedClass {
+ protected $property;
+
+ public function __construct() {
+ $this->property = 1;
+ }
+
+ protected function incrementPropertyValue() {
+ $this->property++;
+ }
+
+ public function getProperty() {
+ return $this->property;
+ }
+
+ protected function whatSecondArg( $a, $b = false ) {
+ return $b;
+ }
+}
diff --git a/tests/phpunit/data/media/Soccer_ball_animated.svg b/tests/phpunit/data/media/Soccer_ball_animated.svg
index 6bd82fc4..183e43d8 100644
--- a/tests/phpunit/data/media/Soccer_ball_animated.svg
+++ b/tests/phpunit/data/media/Soccer_ball_animated.svg
@@ -1,55 +1,55 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg>
-<svg width="150" height="150" viewBox="-105 -105 210 210" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <defs>
- <clipPath id="ball">
- <circle r="100" stroke-width="0"/>
- </clipPath>
- <radialGradient id="shadow1" cx=".4" cy=".3" r=".8">
- <stop offset="0" stop-color="white" stop-opacity="1"/>
- <stop offset=".4" stop-color="white" stop-opacity="1"/>
- <stop offset=".8" stop-color="#EEEEEE" stop-opacity="1"/>
- </radialGradient>
- <radialGradient id="shadow2" cx=".5" cy=".5" r=".5">
- <stop offset="0" stop-color="white" stop-opacity="0"/>
- <stop offset=".8" stop-color="white" stop-opacity="0"/>
- <stop offset=".99" stop-color="black" stop-opacity=".3"/>
- <stop offset="1" stop-color="black" stop-opacity="1"/>
- </radialGradient>
- <g id="black_stuff" stroke-linejoin="round" clip-path="url(#ball)">
- <g fill="black">
- <path d="M 6,-32 Q 26,-28 46,-19 Q 57,-35 64,-47 Q 50,-68 37,-76 Q 17,-75 1,-68 Q 4,-51 6,-32"/>
- <path d="M -26,-2 Q -45,-8 -62,-11 Q -74,5 -76,22 Q -69,40 -50,54 Q -32,47 -17,39 Q -23,15 -26,-2"/>
- <path d="M -95,22 Q -102,12 -102,-8 V 80 H -85 Q -95,45 -95,22"/>
- <path d="M 55,24 Q 41,41 24,52 Q 28,65 31,79 Q 55,78 68,67 Q 78,50 80,35 Q 65,28 55,24"/>
- <path d="M 0,120 L -3,95 Q -25,93 -42,82 Q -50,84 -60,81"/>
- <path d="M -90,-48 Q -80,-52 -68,-49 Q -52,-71 -35,-77 Q -35,-100 -40,-100 H -100"/>
- <path d="M 100,-55 L 87,-37 Q 98,-10 97,5 L 100,6"/>
- </g>
- <g fill="none">
- <path d="M 6,-32 Q -18,-12 -26,-2
- M 46,-19 Q 54,5 55,24
- M 64,-47 Q 77,-44 87,-37
- M 37,-76 Q 39,-90 36,-100
- M 1,-68 Q -13,-77 -35,-77
- M -62,-11 Q -67,-25 -68,-49
- M -76,22 Q -85,24 -95,22
- M -50,54 Q -49,70 -42,82
- M -17,39 Q 0,48 24,52
- M 31,79 Q 20,92 -3,95
- M 68,67 L 80,80
- M 80,35 Q 90,25 97,5
- "/>
- </g>
- </g>
- </defs>
- <circle r="100" fill="white" stroke="none"/>
- <circle r="100" fill="url(#shadow1)" stroke="none"/>
- <g><animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="360" begin="0s" dur="3s" repeatCount="indefinite"/>
- <use xlink:href="#black_stuff" stroke="#EEE" stroke-width="7"/>
- <use xlink:href="#black_stuff" stroke="#DDD" stroke-width="4"/>
- <use xlink:href="#black_stuff" stroke="#999" stroke-width="2"/>
- <use xlink:href="#black_stuff" stroke="black" stroke-width="1"/>
- </g>
- <circle r="100" fill="url(#shadow2)" stroke="none"/>
-</svg>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg>
+<svg width="150" height="150" viewBox="-105 -105 210 210" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <clipPath id="ball">
+ <circle r="100" stroke-width="0"/>
+ </clipPath>
+ <radialGradient id="shadow1" cx=".4" cy=".3" r=".8">
+ <stop offset="0" stop-color="white" stop-opacity="1"/>
+ <stop offset=".4" stop-color="white" stop-opacity="1"/>
+ <stop offset=".8" stop-color="#EEEEEE" stop-opacity="1"/>
+ </radialGradient>
+ <radialGradient id="shadow2" cx=".5" cy=".5" r=".5">
+ <stop offset="0" stop-color="white" stop-opacity="0"/>
+ <stop offset=".8" stop-color="white" stop-opacity="0"/>
+ <stop offset=".99" stop-color="black" stop-opacity=".3"/>
+ <stop offset="1" stop-color="black" stop-opacity="1"/>
+ </radialGradient>
+ <g id="black_stuff" stroke-linejoin="round" clip-path="url(#ball)">
+ <g fill="black">
+ <path d="M 6,-32 Q 26,-28 46,-19 Q 57,-35 64,-47 Q 50,-68 37,-76 Q 17,-75 1,-68 Q 4,-51 6,-32"/>
+ <path d="M -26,-2 Q -45,-8 -62,-11 Q -74,5 -76,22 Q -69,40 -50,54 Q -32,47 -17,39 Q -23,15 -26,-2"/>
+ <path d="M -95,22 Q -102,12 -102,-8 V 80 H -85 Q -95,45 -95,22"/>
+ <path d="M 55,24 Q 41,41 24,52 Q 28,65 31,79 Q 55,78 68,67 Q 78,50 80,35 Q 65,28 55,24"/>
+ <path d="M 0,120 L -3,95 Q -25,93 -42,82 Q -50,84 -60,81"/>
+ <path d="M -90,-48 Q -80,-52 -68,-49 Q -52,-71 -35,-77 Q -35,-100 -40,-100 H -100"/>
+ <path d="M 100,-55 L 87,-37 Q 98,-10 97,5 L 100,6"/>
+ </g>
+ <g fill="none">
+ <path d="M 6,-32 Q -18,-12 -26,-2
+ M 46,-19 Q 54,5 55,24
+ M 64,-47 Q 77,-44 87,-37
+ M 37,-76 Q 39,-90 36,-100
+ M 1,-68 Q -13,-77 -35,-77
+ M -62,-11 Q -67,-25 -68,-49
+ M -76,22 Q -85,24 -95,22
+ M -50,54 Q -49,70 -42,82
+ M -17,39 Q 0,48 24,52
+ M 31,79 Q 20,92 -3,95
+ M 68,67 L 80,80
+ M 80,35 Q 90,25 97,5
+ "/>
+ </g>
+ </g>
+ </defs>
+ <circle r="100" fill="white" stroke="none"/>
+ <circle r="100" fill="url(#shadow1)" stroke="none"/>
+ <g><animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="360" begin="0s" dur="3s" repeatCount="indefinite"/>
+ <use xlink:href="#black_stuff" stroke="#EEE" stroke-width="7"/>
+ <use xlink:href="#black_stuff" stroke="#DDD" stroke-width="4"/>
+ <use xlink:href="#black_stuff" stroke="#999" stroke-width="2"/>
+ <use xlink:href="#black_stuff" stroke="black" stroke-width="1"/>
+ </g>
+ <circle r="100" fill="url(#shadow2)" stroke="none"/>
+</svg>
diff --git a/tests/phpunit/data/media/Tux.svg b/tests/phpunit/data/media/Tux.svg
index 39561078..e48b7353 100644
--- a/tests/phpunit/data/media/Tux.svg
+++ b/tests/phpunit/data/media/Tux.svg
@@ -1,902 +1,902 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 349.46883 405.12272">
- <title>Tux</title>
- <desc>For more information see: http://commons.wikimedia.org/wiki/Image:Tux.svg</desc>
- <radialGradient id="ag" gradientUnits="userSpaceOnUse" cy="-551.04" cx="274.822" gradientTransform="matrix(.5671 0 0 -.2835 81.263 201.645)" r="165.384">
- <stop stop-opacity=".502" offset="0"/>
- <stop stop-opacity="0" offset="1"/>
- </radialGradient>
- <path fill="url(#ag)" d="m330.892 357.885c0 25.898-41.989 46.893-93.785 46.893-51.795 0-93.784-20.994-93.784-46.893s41.989-46.893 93.784-46.893c51.795 0.001 93.785 20.995 93.785 46.893z"/>
- <radialGradient id="ak" gradientUnits="userSpaceOnUse" cy="-551.042" cx="268.794" gradientTransform="matrix(.5823 0 0 -.2835 -61.6052 201.14)" r="165.383">
- <stop stop-opacity=".502" offset="0"/>
- <stop stop-opacity="0" offset="1"/>
- </radialGradient>
- <path fill="url(#ak)" d="m191.223 357.381c0 25.897-43.117 46.892-96.306 46.892-53.188 0-96.305-20.994-96.305-46.892s43.117-46.893 96.305-46.893c53.188 0.001 96.306 20.995 96.306 46.893z"/>
- <g transform="translate(8.99996 9.00046)">
- <path d="m292.327 256.606c-4.752 19.584-28.872 60.48-41.688 78.48-12.815 18.072-11.231 34.344-34.92 28.008-23.616-6.336-30.24-5.184-54.647-3.744-24.265 1.439-19.009-0.721-34.2 6.12-15.12 6.84-65.88-82.944-69.984-99.647-4.031-16.705-5.976-14.689 4.536-32.761 10.513-18.071 12.024-35.928 25.92-57.816 13.896-21.96 29.952-33.12 28.8-49.896-4.535-62.28-8.136-93.384 19.513-107.784 26.352-13.68 48.384-5.544 57.096-0.864 3.744 2.016 11.376 5.904 17.064 12.744 5.688 6.696 10.8 16.848 13.68 29.664 5.904 25.704-2.448 17.208 4.248 46.656 6.624 29.375 20.088 43.775 36.504 67.031 16.414 23.257 33.55 61.633 28.078 83.809z"/>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#666" d="m148.47 94.049c4.319-1.728 3.592-1.958 6.472-8.222 2.304-4.824 4.328-6.898 4.256-14.242 0-7.2-2.232-9.648-5.616-14.328-3.24-4.464-8.424-4.68-11.664-4.104-1.872 0.288-4.319 2.664-5.976 6.192-1.08 2.376-1.944 5.4-2.017 8.568-0.216 8.496 0.505 11.736 2.448 17.496 2.305 6.769 7.921 10.297 12.097 8.64z"/>
- <path fill="#6d6d6d" d="m148.47 94.023c4.293-1.717 3.563-1.954 6.425-8.178 2.289-4.793 4.312-6.861 4.271-14.164 0.027-7.152-2.162-9.702-5.488-14.201-3.296-4.345-8.376-4.509-11.593-3.953-1.916 0.283-4.354 2.569-6.038 5.968-1.159 2.31-2.016 5.353-2.087 8.535-0.212 8.438 0.547 11.691 2.46 17.417 2.268 6.731 7.901 10.221 12.05 8.576z"/>
- <path fill="#757575" d="m148.471 93.996c4.264-1.706 3.533-1.95 6.377-8.133 2.273-4.762 4.296-6.823 4.288-14.085 0.053-7.105-2.093-9.756-5.363-14.075-3.35-4.225-8.327-4.338-11.52-3.801-1.961 0.278-4.389 2.474-6.099 5.744-1.242 2.245-2.089 5.305-2.16 8.501-0.207 8.38 0.591 11.647 2.473 17.34 2.231 6.691 7.881 10.144 12.004 8.509z"/>
- <path fill="#7c7c7c" d="m148.471 93.969c4.235-1.694 3.506-1.946 6.329-8.089 2.26-4.731 4.28-6.786 4.304-14.006 0.081-7.058-2.021-9.811-5.236-13.948-3.403-4.105-8.278-4.167-11.446-3.649-2.006 0.273-4.424 2.379-6.16 5.519-1.322 2.179-2.161 5.257-2.232 8.468-0.202 8.323 0.636 11.603 2.486 17.261 2.191 6.654 7.859 10.068 11.955 8.444z"/>
- <path fill="#848484" d="m148.471 93.943c4.209-1.684 3.477-1.942 6.282-8.045 2.245-4.7 4.266-6.749 4.319-13.928 0.107-7.01-1.95-9.864-5.109-13.821-3.458-3.985-8.23-3.996-11.375-3.498-2.049 0.268-4.458 2.284-6.222 5.295-1.403 2.114-2.233 5.21-2.303 8.435-0.198 8.265 0.679 11.559 2.498 17.183 2.156 6.615 7.842 9.992 11.91 8.379z"/>
- <path fill="#8c8c8c" d="m148.471 93.916c4.181-1.672 3.448-1.938 6.235-8 2.23-4.668 4.249-6.711 4.335-13.85 0.134-6.962-1.88-9.918-4.982-13.695-3.513-3.865-8.183-3.825-11.303-3.347-2.094 0.263-4.492 2.189-6.283 5.07-1.484 2.049-2.306 5.163-2.375 8.401-0.193 8.207 0.723 11.515 2.511 17.105 2.118 6.58 7.821 9.919 11.862 8.316z"/>
- <path fill="#939393" d="m148.472 93.889c4.152-1.661 3.419-1.934 6.188-7.956 2.215-4.638 4.233-6.674 4.35-13.771 0.161-6.915-1.809-9.972-4.854-13.568-3.567-3.746-8.134-3.654-11.23-3.195-2.138 0.259-4.527 2.094-6.345 4.847-1.564 1.983-2.378 5.115-2.447 8.368-0.188 8.149 0.767 11.47 2.523 17.026 2.079 6.54 7.8 9.841 11.815 8.249z"/>
- <path fill="#9b9b9b" d="m148.472 93.863c4.125-1.65 3.391-1.93 6.141-7.912 2.2-4.607 4.217-6.637 4.366-13.693 0.188-6.868-1.739-10.026-4.729-13.441-3.621-3.626-8.085-3.484-11.157-3.044-2.183 0.253-4.562 1.999-6.406 4.622-1.646 1.918-2.45 5.068-2.52 8.335-0.185 8.091 0.811 11.426 2.535 16.948 2.044 6.502 7.782 9.766 11.77 8.185z"/>
- <path fill="#a3a3a3" d="m148.472 93.836c4.097-1.639 3.361-1.926 6.094-7.867 2.185-4.576 4.201-6.599 4.382-13.614 0.214-6.82-1.669-10.081-4.603-13.315-3.676-3.506-8.036-3.313-11.084-2.893-2.229 0.249-4.598 1.904-6.47 4.398-1.726 1.852-2.521 5.021-2.591 8.301-0.18 8.034 0.854 11.382 2.548 16.87 2.008 6.465 7.763 9.691 11.724 8.12z"/>
- <path fill="#aaa" d="m148.472 93.809c4.069-1.628 3.334-1.922 6.047-7.823 2.17-4.544 4.185-6.562 4.396-13.536 0.242-6.772-1.597-10.134-4.475-13.188-3.73-3.387-7.989-3.142-11.013-2.741-2.271 0.243-4.632 1.809-6.53 4.173-1.808 1.787-2.594 4.974-2.662 8.268-0.176 7.976 0.897 11.337 2.56 16.792 1.97 6.427 7.743 9.615 11.677 8.055z"/>
- <path fill="#b2b2b2" d="m148.473 93.782c4.041-1.617 3.304-1.918 5.999-7.778 2.154-4.514 4.169-6.524 4.412-13.458 0.269-6.725-1.526-10.188-4.349-13.062-3.784-3.267-7.939-2.971-10.939-2.589-2.316 0.238-4.666 1.714-6.592 3.949-1.888 1.721-2.667 4.926-2.734 8.234-0.171 7.918 0.941 11.293 2.572 16.713 1.933 6.391 7.723 9.541 11.631 7.991z"/>
- <path fill="#bababa" d="m148.473 93.756c4.014-1.606 3.275-1.914 5.951-7.734 2.141-4.482 4.153-6.487 4.43-13.379 0.295-6.678-1.457-10.243-4.223-12.935-3.839-3.147-7.892-2.8-10.867-2.438-2.36 0.233-4.701 1.619-6.653 3.725-1.969 1.656-2.739 4.879-2.806 8.201-0.167 7.86 0.984 11.249 2.585 16.636 1.895 6.35 7.702 9.462 11.583 7.924z"/>
- <path fill="#c1c1c1" d="m148.473 93.729c3.985-1.595 3.247-1.91 5.904-7.69 2.125-4.451 4.138-6.45 4.445-13.3 0.321-6.63-1.387-10.297-4.096-12.808-3.894-3.028-7.844-2.629-10.795-2.287-2.405 0.229-4.735 1.524-6.716 3.5-2.049 1.59-2.811 4.831-2.878 8.167-0.161 7.802 1.029 11.205 2.599 16.557 1.859 6.314 7.683 9.389 11.537 7.861z"/>
- <path fill="#c9c9c9" d="m148.473 93.702c3.958-1.583 3.219-1.906 5.857-7.646 2.11-4.42 4.121-6.412 4.46-13.222 0.35-6.583-1.315-10.351-3.969-12.682-3.947-2.908-7.794-2.458-10.722-2.135-2.45 0.224-4.771 1.429-6.777 3.276-2.13 1.525-2.883 4.784-2.95 8.135-0.157 7.745 1.073 11.16 2.611 16.479 1.821 6.276 7.663 9.313 11.49 7.795z"/>
- <path fill="#d1d1d1" d="m148.474 93.676c3.93-1.573 3.188-1.902 5.809-7.601 2.097-4.389 4.107-6.375 4.477-13.144 0.375-6.535-1.245-10.404-3.842-12.555-4.002-2.788-7.747-2.287-10.65-1.984-2.493 0.219-4.805 1.334-6.837 3.052-2.213 1.459-2.957 4.736-3.022 8.101-0.153 7.687 1.116 11.116 2.623 16.401 1.782 6.237 7.642 9.237 11.442 7.73z"/>
- <path fill="#d8d8d8" d="m148.474 93.649c3.901-1.562 3.16-1.898 5.762-7.557 2.082-4.358 4.091-6.338 4.493-13.065 0.401-6.487-1.176-10.458-3.716-12.428-4.057-2.668-7.698-2.116-10.578-1.832-2.538 0.214-4.839 1.239-6.899 2.827-2.292 1.394-3.029 4.689-3.094 8.068-0.148 7.629 1.16 11.072 2.636 16.322 1.746 6.2 7.623 9.161 11.396 7.665z"/>
- <path fill="#e0e0e0" d="m148.474 93.622c3.875-1.55 3.132-1.894 5.715-7.512 2.066-4.327 4.075-6.3 4.508-12.987 0.429-6.44-1.104-10.513-3.588-12.302-4.111-2.549-7.65-1.945-10.506-1.681-2.582 0.209-4.874 1.144-6.961 2.604-2.373 1.328-3.102 4.642-3.165 8.034-0.145 7.571 1.204 11.027 2.647 16.244 1.709 6.162 7.604 9.086 11.35 7.6z"/>
- <path fill="#e8e8e8" d="m148.474 93.596c3.847-1.54 3.104-1.89 5.668-7.468 2.052-4.296 4.059-6.263 4.523-12.908 0.456-6.393-1.034-10.567-3.462-12.175-4.165-2.429-7.601-1.774-10.433-1.529-2.627 0.204-4.908 1.049-7.023 2.379-2.453 1.263-3.173 4.594-3.236 8.001-0.141 7.514 1.247 10.983 2.659 16.166 1.673 6.123 7.585 9.008 11.304 7.534z"/>
- <path fill="#efefef" d="m148.475 93.569c3.817-1.528 3.073-1.886 5.62-7.424 2.036-4.265 4.043-6.226 4.539-12.83 0.482-6.345-0.964-10.621-3.336-12.048-4.219-2.31-7.552-1.604-10.359-1.378-2.672 0.199-4.943 0.954-7.084 2.155-2.535 1.197-3.246 4.546-3.311 7.967-0.135 7.456 1.292 10.939 2.673 16.087 1.636 6.087 7.565 8.935 11.258 7.471z"/>
- <path fill="#f7f7f7" d="m148.475 93.542c3.791-1.517 3.046-1.882 5.572-7.379 2.022-4.234 4.027-6.188 4.556-12.751 0.51-6.297-0.894-10.675-3.208-11.921-4.274-2.19-7.505-1.433-10.289-1.227-2.715 0.194-4.978 0.859-7.146 1.93-2.614 1.132-3.317 4.5-3.381 7.935-0.131 7.398 1.335 10.895 2.686 16.009 1.597 6.047 7.544 8.858 11.21 7.404z"/>
- <path fill="#fff" d="m148.475 93.516c3.763-1.506 3.017-1.878 5.525-7.335 2.007-4.203 4.012-6.151 4.571-12.673 0.536-6.25-0.823-10.729-3.082-11.795-4.328-2.07-7.456-1.262-10.216-1.075-2.76 0.189-5.012 0.764-7.207 1.706-2.696 1.066-3.39 4.452-3.453 7.901-0.126 7.34 1.379 10.85 2.698 15.931 1.561 6.01 7.525 8.782 11.164 7.34z"/>
- </g>
- <path d="m132.033 74.7465c2.16 0 4.896 1.44 6.191 3.384 1.368 1.944 2.376 4.68 2.376 7.776 0 4.608-0.504 9.72-3.239 11.304-0.864 0.504-2.736 0.936-3.816 0.936-2.448 0-2.664-1.584-4.968-3.96-0.792-0.864-3.168-5.04-3.168-8.496 0-2.16-0.504-5.256 1.368-7.992 1.296-2.016 2.952-2.952 5.256-2.952z"/>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m143.862 68.608c0.844-1.305 4.222-0.69 5.45 1.996 1.229 2.687 0.998 8.522 0.153 8.829-2.226 0.691-1.535-2.534-3.454-5.451-1.919-2.762-2.994-4.067-2.149-5.374z"/>
- <path fill="#070707" d="m143.916 68.664c0.833-1.289 4.169-0.681 5.381 1.971 1.215 2.653 0.985 8.414 0.152 8.717-2.198 0.682-1.516-2.502-3.411-5.382-1.895-2.728-2.956-4.017-2.122-5.306z"/>
- <path fill="#0f0f0f" d="m143.97 68.719c0.822-1.272 4.114-0.673 5.312 1.945 1.198 2.619 0.973 8.306 0.15 8.605-2.169 0.673-1.497-2.47-3.367-5.313-1.871-2.692-2.918-3.964-2.095-5.237z"/>
- <path fill="#161616" d="m144.024 68.774c0.812-1.255 4.062-0.664 5.243 1.92 1.182 2.585 0.96 8.198 0.147 8.493-2.141 0.665-1.477-2.438-3.323-5.244-1.846-2.657-2.88-3.913-2.067-5.169z"/>
- <path fill="#1e1e1e" d="m144.078 68.829c0.801-1.239 4.008-0.655 5.174 1.895 1.167 2.551 0.947 8.09 0.146 8.381-2.113 0.656-1.458-2.405-3.28-5.174-1.821-2.623-2.842-3.863-2.04-5.102z"/>
- <path fill="#262626" d="m144.132 68.884c0.791-1.222 3.955-0.646 5.105 1.87 1.151 2.517 0.935 7.982 0.144 8.27-2.085 0.647-1.438-2.374-3.235-5.105-1.798-2.589-2.805-3.812-2.014-5.035z"/>
- <path fill="#2d2d2d" d="m144.186 68.939c0.779-1.206 3.9-0.638 5.036 1.844 1.135 2.483 0.922 7.874 0.142 8.158-2.057 0.639-1.419-2.341-3.192-5.037-1.773-2.552-2.766-3.758-1.986-4.965z"/>
- <path fill="#353535" d="m144.24 68.994c0.769-1.189 3.848-0.629 4.967 1.819 1.12 2.449 0.909 7.766 0.141 8.046-2.028 0.629-1.399-2.31-3.148-4.967-1.75-2.518-2.73-3.708-1.96-4.898z"/>
- <path fill="#3d3d3d" d="m144.294 69.049c0.76-1.172 3.794-0.621 4.898 1.793 1.104 2.415 0.896 7.658 0.138 7.934-2 0.621-1.38-2.277-3.104-4.898-1.725-2.482-2.691-3.655-1.932-4.829z"/>
- <path fill="#444" d="m144.348 69.104c0.748-1.156 3.74-0.612 4.829 1.768 1.088 2.38 0.884 7.55 0.136 7.822-1.973 0.612-1.36-2.245-3.062-4.829-1.699-2.448-2.651-3.604-1.903-4.761z"/>
- <path fill="#4c4c4c" d="m144.402 69.16c0.737-1.14 3.687-0.603 4.76 1.743 1.073 2.347 0.871 7.442 0.134 7.71-1.943 0.604-1.341-2.213-3.017-4.76-1.676-2.414-2.614-3.554-1.877-4.693z"/>
- <path fill="#545454" d="m144.456 69.215c0.727-1.123 3.634-0.595 4.691 1.717 1.057 2.313 0.857 7.334 0.132 7.598-1.916 0.595-1.321-2.181-2.973-4.691-1.652-2.378-2.577-3.501-1.85-4.624z"/>
- <path fill="#5b5b5b" d="m144.51 69.27c0.717-1.106 3.58-0.585 4.622 1.692 1.041 2.278 0.847 7.226 0.131 7.486-1.888 0.586-1.303-2.149-2.93-4.622-1.628-2.343-2.539-3.45-1.823-4.556z"/>
- <path fill="#636363" d="m144.564 69.325c0.705-1.09 3.526-0.577 4.553 1.667 1.026 2.245 0.833 7.118 0.128 7.375-1.858 0.577-1.282-2.117-2.885-4.553-1.604-2.309-2.501-3.399-1.796-4.489z"/>
- <path fill="#6b6b6b" d="m144.618 69.38c0.694-1.073 3.473-0.568 4.483 1.642 1.011 2.21 0.82 7.01 0.127 7.263-1.831 0.568-1.264-2.084-2.842-4.484-1.578-2.274-2.462-3.347-1.768-4.421z"/>
- <path fill="#727272" d="m144.672 69.435c0.685-1.057 3.42-0.56 4.414 1.617 0.995 2.176 0.81 6.902 0.125 7.15-1.803 0.56-1.243-2.053-2.798-4.415-1.554-2.238-2.425-3.295-1.741-4.352z"/>
- <path fill="#7a7a7a" d="m144.726 69.49c0.673-1.041 3.365-0.551 4.345 1.591 0.979 2.143 0.796 6.794 0.123 7.039-1.775 0.551-1.224-2.021-2.754-4.346-1.53-2.203-2.387-3.244-1.714-4.284z"/>
- <path fill="#828282" d="m144.78 69.545c0.662-1.023 3.313-0.542 4.276 1.566 0.964 2.108 0.782 6.686 0.121 6.926-1.746 0.542-1.204-1.988-2.711-4.276-1.505-2.167-2.348-3.192-1.686-4.216z"/>
- <path fill="#898989" d="m144.834 69.6c0.652-1.007 3.259-0.533 4.207 1.541s0.771 6.578 0.119 6.815c-1.718 0.534-1.185-1.956-2.666-4.207-1.482-2.134-2.311-3.142-1.66-4.149z"/>
- <path fill="#919191" d="m144.888 69.655c0.641-0.99 3.206-0.524 4.138 1.516 0.933 2.04 0.758 6.47 0.117 6.703-1.69 0.525-1.165-1.924-2.623-4.138-1.457-2.098-2.273-3.09-1.632-4.081z"/>
- <path fill="#999" d="m144.942 69.71c0.63-0.974 3.152-0.516 4.069 1.49s0.744 6.362 0.114 6.591c-1.662 0.516-1.146-1.892-2.579-4.069-1.432-2.062-2.234-3.037-1.604-4.012z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#666" d="m193.11 94.985c10.8-1.152 14.616-5.328 16.56-12.6 1.729-6.48 1.801-13.68-3.023-22.104-4.536-8.063-7.128-9.36-13.681-9.864-10.079-0.864-14.832 6.192-17.063 11.232-2.376 5.472-1.872 4.68-1.729 11.592 0.145 7.272 4.245 9.299 6.766 13.835 2.519 4.465 10.946 7.982 12.17 7.909z"/>
- <path fill="#6d6d6d" d="m193.115 94.944c10.759-1.131 14.618-5.354 16.515-12.569 1.701-6.525 1.785-13.686-3.002-21.912-4.434-7.797-7.038-9.081-13.512-9.581-10.049-0.861-14.941 5.873-17.181 10.874-2.304 5.28-1.878 4.718-1.726 11.539 0.16 7.268 4.268 9.223 6.784 13.76 2.521 4.475 10.898 7.962 12.122 7.889z"/>
- <path fill="#757575" d="m193.12 94.902c10.718-1.11 14.62-5.379 16.469-12.538 1.676-6.57 1.771-13.692-2.979-21.721-4.331-7.53-6.947-8.801-13.344-9.297-10.018-0.858-15.05 5.553-17.298 10.516-2.229 5.087-1.885 4.757-1.722 11.487 0.176 7.264 4.289 9.146 6.803 13.686 2.52 4.485 10.848 7.942 12.071 7.867z"/>
- <path fill="#7c7c7c" d="m193.126 94.861c10.675-1.09 14.621-5.405 16.423-12.507 1.648-6.616 1.756-13.698-2.958-21.529-4.229-7.263-6.856-8.522-13.176-9.014-9.985-0.854-15.158 5.234-17.414 10.158-2.156 4.895-1.891 4.795-1.719 11.434 0.193 7.26 4.31 9.07 6.822 13.611 2.52 4.495 10.798 7.922 12.022 7.847z"/>
- <path fill="#848484" d="m193.131 94.82c10.635-1.069 14.623-5.431 16.377-12.476 1.622-6.661 1.741-13.704-2.936-21.337-4.126-6.996-6.767-8.242-13.008-8.73-9.955-0.852-15.267 4.915-17.53 9.8-2.084 4.703-1.896 4.833-1.716 11.38 0.209 7.256 4.332 8.995 6.841 13.537 2.52 4.505 10.748 7.902 11.972 7.826z"/>
- <path fill="#8c8c8c" d="m193.136 94.778c10.593-1.048 14.625-5.457 16.331-12.445 1.596-6.706 1.726-13.709-2.913-21.145-4.025-6.729-6.678-7.963-12.841-8.447-9.924-0.848-15.375 4.595-17.647 9.441-2.01 4.51-1.903 4.872-1.712 11.328 0.225 7.251 4.354 8.918 6.858 13.462 2.521 4.517 10.7 7.883 11.924 7.806z"/>
- <path fill="#939393" d="m193.141 94.737c10.552-1.027 14.627-5.482 16.286-12.414 1.568-6.751 1.711-13.715-2.893-20.954-3.922-6.462-6.586-7.683-12.672-8.163-9.892-0.845-15.483 4.276-17.764 9.083-1.938 4.318-1.909 4.91-1.709 11.275 0.24 7.247 4.375 8.842 6.878 13.387 2.521 4.528 10.651 7.863 11.874 7.786z"/>
- <path fill="#9b9b9b" d="m193.146 94.695c10.51-1.007 14.63-5.508 16.241-12.382 1.542-6.796 1.694-13.721-2.87-20.762-3.82-6.195-6.496-7.404-12.504-7.879-9.861-0.842-15.592 3.956-17.882 8.725-1.863 4.126-1.915 4.949-1.706 11.223 0.258 7.243 4.397 8.766 6.897 13.313 2.521 4.535 10.601 7.841 11.824 7.762z"/>
- <path fill="#a3a3a3" d="m193.151 94.654c10.469-0.986 14.632-5.534 16.196-12.351 1.515-6.842 1.68-13.727-2.85-20.57-3.717-5.928-6.405-7.125-12.335-7.596-9.83-0.839-15.7 3.637-17.998 8.367-1.791 3.933-1.922 4.987-1.703 11.169 0.273 7.239 4.419 8.689 6.916 13.238 2.521 4.547 10.551 7.822 11.774 7.743z"/>
- <path fill="#aaa" d="m193.157 94.612c10.427-0.965 14.633-5.56 16.149-12.32 1.488-6.887 1.666-13.733-2.826-20.379-3.615-5.661-6.316-6.845-12.168-7.313-9.799-0.835-15.809 3.317-18.114 8.009-1.718 3.741-1.928 5.025-1.7 11.117 0.29 7.235 4.44 8.613 6.936 13.163 2.519 4.558 10.499 7.804 11.723 7.723z"/>
- <path fill="#b2b2b2" d="m193.162 94.571c10.386-0.944 14.635-5.585 16.104-12.289 1.462-6.932 1.649-13.739-2.806-20.188-3.512-5.394-6.225-6.565-11.999-7.029-9.768-0.833-15.917 2.998-18.23 7.651-1.646 3.549-1.935 5.064-1.697 11.064 0.306 7.231 4.462 8.537 6.954 13.088 2.52 4.569 10.451 7.784 11.674 7.703z"/>
- <path fill="#bababa" d="m193.167 94.529c10.345-0.923 14.638-5.611 16.059-12.258 1.436-6.977 1.636-13.744-2.782-19.995-3.41-5.127-6.135-6.286-11.832-6.746-9.736-0.829-16.025 2.679-18.347 7.293-1.572 3.356-1.941 5.103-1.694 11.011 0.322 7.227 4.484 8.461 6.973 13.014 2.519 4.579 10.4 7.764 11.623 7.681z"/>
- <path fill="#c1c1c1" d="m193.172 94.488c10.304-0.903 14.64-5.637 16.014-12.227 1.409-7.022 1.62-13.75-2.762-19.804-3.308-4.86-6.044-6.006-11.662-6.462-9.705-0.826-16.135 2.359-18.466 6.935-1.498 3.164-1.945 5.141-1.689 10.958 0.338 7.223 4.506 8.385 6.991 12.939 2.519 4.59 10.351 7.744 11.574 7.661z"/>
- <path fill="#c9c9c9" d="m193.177 94.447c10.262-0.882 14.641-5.663 15.967-12.196 1.383-7.068 1.605-13.756-2.738-19.612-3.206-4.593-5.954-5.727-11.496-6.179-9.673-0.823-16.242 2.04-18.581 6.577-1.425 2.972-1.952 5.179-1.687 10.906 0.354 7.219 4.526 8.308 7.01 12.865 2.52 4.598 10.302 7.723 11.525 7.639z"/>
- <path fill="#d1d1d1" d="m193.182 94.405c10.221-0.861 14.643-5.688 15.922-12.165 1.355-7.113 1.591-13.762-2.717-19.42-3.104-4.326-5.864-5.448-11.327-5.895-9.644-0.82-16.352 1.721-18.698 6.219-1.353 2.779-1.959 5.217-1.684 10.853 0.369 7.214 4.549 8.232 7.028 12.79 2.521 4.609 10.254 7.703 11.476 7.618z"/>
- <path fill="#d8d8d8" d="m193.187 94.364c10.179-0.841 14.645-5.714 15.876-12.133 1.33-7.158 1.576-13.768-2.694-19.229-3.001-4.059-5.773-5.168-11.16-5.612-9.61-0.817-16.459 1.401-18.813 5.861-1.279 2.586-1.965 5.256-1.682 10.8 0.387 7.21 4.571 8.156 7.049 12.715 2.519 4.619 10.202 7.684 11.424 7.598z"/>
- <path fill="#e0e0e0" d="m193.193 94.322c10.137-0.82 14.646-5.74 15.83-12.103 1.303-7.203 1.561-13.773-2.673-19.037-2.898-3.792-5.684-4.889-10.991-5.328-9.58-0.813-16.568 1.082-18.931 5.502-1.206 2.395-1.972 5.294-1.679 10.747 0.403 7.207 4.592 8.08 7.067 12.641 2.521 4.631 10.154 7.666 11.377 7.578z"/>
- <path fill="#e8e8e8" d="m193.198 94.281c10.096-0.799 14.648-5.766 15.785-12.071 1.275-7.249 1.545-13.779-2.651-18.845-2.796-3.525-5.593-4.609-10.823-5.044-9.549-0.81-16.677 0.762-19.048 5.145-1.133 2.202-1.978 5.333-1.675 10.694 0.419 7.202 4.614 8.003 7.086 12.566 2.52 4.638 10.103 7.643 11.326 7.555z"/>
- <path fill="#efefef" d="m193.203 94.239c10.055-0.778 14.65-5.792 15.739-12.04 1.25-7.293 1.531-13.785-2.629-18.653-2.694-3.258-5.502-4.33-10.655-4.761-9.517-0.807-16.785 0.443-19.165 4.786-1.059 2.01-1.983 5.372-1.671 10.642 0.435 7.198 4.636 7.928 7.104 12.492 2.52 4.649 10.055 7.624 11.277 7.534z"/>
- <path fill="#f7f7f7" d="m193.208 94.198c10.014-0.757 14.652-5.817 15.694-12.009 1.223-7.339 1.516-13.792-2.607-18.462-2.592-2.991-5.413-4.05-10.486-4.478-9.487-0.804-16.895 0.124-19.282 4.428-0.986 1.817-1.989 5.41-1.668 10.589 0.451 7.194 4.657 7.851 7.123 12.417 2.519 4.661 10.004 7.605 11.226 7.515z"/>
- <path fill="#fff" d="m193.213 94.156c9.973-0.737 14.654-5.843 15.648-11.978 1.197-7.384 1.501-13.797-2.585-18.27-2.489-2.724-5.322-3.771-10.319-4.194-9.455-0.801-17.002-0.196-19.397 4.07-0.913 1.625-1.996 5.448-1.665 10.536 0.467 7.19 4.679 7.775 7.142 12.342 2.519 4.671 9.954 7.586 11.176 7.494z"/>
- </g>
- <path d="m179.841 74.4585c5.4 0 8.568 4.824 9.648 11.016 0.432 2.808-0.216 6.048-1.944 8.28-1.944 2.592-5.4 4.176-8.208 4.176-2.664 0-5.688 0.432-7.271-1.728-1.584-2.232-1.944-7.2-1.944-10.728 0-3.96 1.152-6.768 3.168-9 1.511-1.657 4.247-2.016 6.551-2.016z"/>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m192.591 66.68c0.98-0.653 2.612 0 4.489 2.122 2.039 2.285 2.938 4.08 0.489 5.385-1.877 0.98-2.448-1.958-3.59-3.182-1.795-1.959-3.346-3.02-1.388-4.325z"/>
- <path fill="#070707" d="m192.631 66.738c0.96-0.649 2.573 0 4.423 2.09 2.009 2.251 2.864 4.02 0.481 5.305-1.837 0.977-2.403-1.929-3.525-3.135-1.768-1.925-3.296-2.965-1.379-4.26z"/>
- <path fill="#0f0f0f" d="m192.671 66.797c0.939-0.645 2.534 0 4.356 2.059 1.978 2.217 2.792 3.958 0.474 5.225-1.798 0.974-2.357-1.9-3.46-3.087-1.742-1.895-3.247-2.913-1.37-4.197z"/>
- <path fill="#161616" d="m192.711 66.855c0.919-0.641 2.495 0 4.289 2.027 1.948 2.184 2.721 3.898 0.467 5.146-1.759 0.971-2.313-1.871-3.396-3.041-1.715-1.861-3.197-2.858-1.36-4.132z"/>
- <path fill="#1e1e1e" d="m192.751 66.914c0.899-0.637 2.457 0 4.223 1.996 1.918 2.149 2.647 3.838 0.46 5.065-1.72 0.968-2.269-1.842-3.331-2.993-1.689-1.83-3.148-2.805-1.352-4.068z"/>
- <path fill="#262626" d="m192.791 66.973c0.878-0.633 2.418 0 4.155 1.964 1.888 2.116 2.576 3.777 0.453 4.986-1.68 0.965-2.224-1.813-3.267-2.946-1.661-1.798-3.097-2.752-1.341-4.004z"/>
- <path fill="#2d2d2d" d="m192.831 67.031c0.858-0.629 2.379 0 4.089 1.933 1.857 2.082 2.503 3.717 0.445 4.906-1.641 0.961-2.178-1.784-3.201-2.898-1.636-1.767-3.048-2.7-1.333-3.941z"/>
- <path fill="#353535" d="m192.87 67.09c0.838-0.625 2.341 0 4.023 1.902 1.827 2.047 2.431 3.656 0.438 4.826-1.601 0.958-2.133-1.755-3.137-2.852-1.608-1.735-2.998-2.646-1.324-3.876z"/>
- <path fill="#3d3d3d" d="m192.91 67.148c0.818-0.621 2.302 0 3.956 1.87 1.797 2.014 2.359 3.596 0.431 4.746-1.562 0.956-2.088-1.726-3.071-2.804-1.583-1.702-2.95-2.592-1.316-3.812z"/>
- <path fill="#444" d="m192.95 67.207c0.798-0.617 2.263 0 3.889 1.839 1.768 1.98 2.287 3.535 0.425 4.666-1.523 0.952-2.043-1.697-3.008-2.757-1.556-1.671-2.899-2.539-1.306-3.748z"/>
- <path fill="#4c4c4c" d="m192.99 67.266c0.777-0.614 2.224 0 3.823 1.807 1.735 1.946 2.214 3.474 0.416 4.586-1.483 0.949-1.998-1.667-2.942-2.709-1.529-1.639-2.85-2.486-1.297-3.684z"/>
- <path fill="#545454" d="m193.03 67.325c0.757-0.61 2.185 0 3.756 1.775 1.706 1.912 2.143 3.414 0.409 4.506-1.444 0.946-1.953-1.639-2.878-2.663-1.502-1.606-2.799-2.431-1.287-3.618z"/>
- <path fill="#5b5b5b" d="m193.07 67.383c0.736-0.605 2.146 0 3.688 1.744 1.677 1.878 2.07 3.353 0.402 4.426-1.405 0.943-1.908-1.609-2.813-2.615-1.475-1.575-2.749-2.378-1.277-3.555z"/>
- <path fill="#636363" d="m193.11 67.442c0.716-0.602 2.106 0 3.622 1.712 1.646 1.844 1.998 3.293 0.395 4.347-1.364 0.94-1.862-1.581-2.748-2.568-1.449-1.543-2.701-2.326-1.269-3.491z"/>
- <path fill="#6b6b6b" d="m193.15 67.5c0.696-0.598 2.069 0 3.556 1.681 1.615 1.811 1.925 3.232 0.387 4.267-1.325 0.937-1.818-1.552-2.683-2.521-1.423-1.511-2.651-2.272-1.26-3.427z"/>
- <path fill="#727272" d="m193.19 67.559c0.675-0.594 2.03 0 3.489 1.649 1.585 1.777 1.853 3.172 0.38 4.187-1.287 0.935-1.774-1.522-2.619-2.473-1.396-1.48-2.601-2.219-1.25-3.363z"/>
- <path fill="#7a7a7a" d="m193.23 67.618c0.654-0.59 1.991 0 3.422 1.618 1.555 1.743 1.781 3.111 0.373 4.107-1.247 0.931-1.729-1.494-2.554-2.426-1.369-1.448-2.551-2.166-1.241-3.299z"/>
- <path fill="#828282" d="m193.269 67.677c0.635-0.586 1.953 0 3.355 1.586 1.525 1.708 1.709 3.05 0.366 4.026-1.208 0.928-1.684-1.464-2.489-2.378-1.342-1.416-2.501-2.112-1.232-3.234z"/>
- <path fill="#898989" d="m193.309 67.735c0.614-0.582 1.914 0 3.29 1.555 1.493 1.675 1.636 2.99 0.357 3.947-1.169 0.925-1.639-1.435-2.424-2.332-1.316-1.384-2.452-2.058-1.223-3.17z"/>
- <path fill="#919191" d="m193.349 67.794c0.595-0.578 1.875 0 3.223 1.523 1.464 1.641 1.564 2.93 0.351 3.867-1.129 0.922-1.594-1.406-2.359-2.284-1.29-1.352-2.403-2.005-1.215-3.106z"/>
- <path fill="#999" d="m193.389 67.853c0.573-0.574 1.836 0 3.155 1.492 1.435 1.607 1.492 2.869 0.345 3.787-1.091 0.919-1.55-1.377-2.295-2.237-1.263-1.32-2.353-1.953-1.205-3.042z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m165.498 69.906c1.693-0.654 3.012-0.69 5.63 1.036 3.166 2.088 1.705 5.245-0.779 4.601-2.146-0.556-2.417-0.681-4.391-1.086-3.101-0.648-3.641-3.322-0.46-4.551z"/>
- <path fill="#050505" d="m165.564 70.033c1.658-0.629 2.973-0.656 5.555 1.026 3.066 2.009 1.654 5.012-0.805 4.38-2.131-0.547-2.345-0.656-4.284-1.052-3.055-0.634-3.587-3.173-0.466-4.354z"/>
- <path fill="#0a0a0a" d="m165.63 70.16c1.623-0.604 2.935-0.622 5.481 1.015 2.965 1.93 1.602 4.779-0.83 4.159-2.119-0.539-2.274-0.63-4.179-1.018-3.009-0.618-3.533-3.022-0.472-4.156z"/>
- <path fill="#0f0f0f" d="m165.696 70.287c1.587-0.579 2.895-0.587 5.406 1.005 2.864 1.851 1.551 4.546-0.855 3.938-2.105-0.53-2.203-0.605-4.073-0.983-2.963-0.604-3.48-2.873-0.478-3.96z"/>
- <path fill="#141414" d="m165.761 70.413c1.553-0.553 2.856-0.553 5.331 0.995 2.766 1.772 1.5 4.313-0.88 3.717-2.092-0.521-2.131-0.58-3.967-0.949-2.916-0.588-3.425-2.723-0.484-3.763z"/>
- <path fill="#191919" d="m165.827 70.54c1.519-0.528 2.818-0.519 5.258 0.984 2.664 1.693 1.448 4.079-0.905 3.497-2.079-0.513-2.06-0.554-3.861-0.915-2.873-0.573-3.373-2.573-0.492-3.566z"/>
- <path fill="#1e1e1e" d="m165.893 70.667c1.482-0.503 2.778-0.484 5.183 0.974 2.564 1.614 1.397 3.846-0.93 3.276-2.067-0.504-1.989-0.529-3.756-0.88-2.826-0.559-3.319-2.425-0.497-3.37z"/>
- <path fill="#232323" d="m165.959 70.793c1.447-0.478 2.74-0.45 5.108 0.964 2.464 1.535 1.345 3.613-0.955 3.055-2.053-0.496-1.917-0.503-3.651-0.846-2.779-0.543-3.264-2.274-0.502-3.173z"/>
- <path fill="#282828" d="m166.025 70.92c1.412-0.453 2.701-0.416 5.034 0.954 2.362 1.456 1.293 3.38-0.981 2.834-2.04-0.487-1.845-0.478-3.545-0.812-2.733-0.528-3.21-2.125-0.508-2.976z"/>
- <path fill="#2d2d2d" d="m166.09 71.047c1.378-0.428 2.663-0.382 4.96 0.943 2.264 1.377 1.242 3.146-1.006 2.613-2.026-0.478-1.773-0.453-3.438-0.777-2.688-0.513-3.158-1.974-0.516-2.779z"/>
- <path fill="#333" d="m166.156 71.173c1.343-0.402 2.624-0.347 4.885 0.933 2.163 1.298 1.191 2.914-1.029 2.392-2.015-0.47-1.703-0.428-3.334-0.743-2.642-0.498-3.104-1.824-0.522-2.582z"/>
- <path fill="#383838" d="m166.222 71.3c1.307-0.377 2.585-0.313 4.81 0.922 2.063 1.219 1.14 2.681-1.055 2.171-2.001-0.461-1.631-0.402-3.229-0.708-2.594-0.483-3.048-1.674-0.526-2.385z"/>
- <path fill="#3d3d3d" d="m166.288 71.427c1.272-0.352 2.546-0.279 4.736 0.913 1.962 1.14 1.088 2.447-1.081 1.95-1.988-0.452-1.56-0.377-3.122-0.674-2.55-0.469-2.995-1.526-0.533-2.189z"/>
- <path fill="#424242" d="m166.354 71.554c1.236-0.327 2.507-0.245 4.661 0.902 1.861 1.061 1.037 2.214-1.106 1.729-1.974-0.444-1.488-0.352-3.016-0.64-2.504-0.453-2.942-1.375-0.539-1.991z"/>
- <path fill="#474747" d="m166.419 71.68c1.203-0.302 2.469-0.21 4.587 0.892 1.762 0.982 0.986 1.98-1.13 1.508-1.962-0.435-1.417-0.326-2.911-0.606-2.458-0.437-2.888-1.224-0.546-1.794z"/>
- <path fill="#4c4c4c" d="m166.485 71.807c1.167-0.276 2.429-0.176 4.513 0.882 1.66 0.903 0.935 1.748-1.156 1.288-1.948-0.426-1.345-0.301-2.805-0.572-2.412-0.423-2.834-1.076-0.552-1.598z"/>
- <path fill="#515151" d="m166.551 71.934c1.133-0.251 2.391-0.142 4.438 0.871 1.56 0.824 0.883 1.515-1.181 1.067-1.936-0.417-1.274-0.275-2.699-0.537-2.366-0.408-2.781-0.926-0.558-1.401z"/>
- <path fill="#565656" d="m166.617 72.061c1.097-0.227 2.351-0.108 4.363 0.861 1.46 0.745 0.831 1.281-1.206 0.846-1.922-0.409-1.202-0.25-2.594-0.503-2.319-0.393-2.726-0.777-0.563-1.204z"/>
- <path fill="#5b5b5b" d="m166.683 72.187c1.062-0.201 2.312-0.073 4.289 0.851 1.358 0.666 0.778 1.048-1.231 0.625-1.91-0.4-1.131-0.225-2.489-0.469-2.274-0.377-2.672-0.626-0.569-1.007z"/>
- <path fill="#606060" d="m166.748 72.314c1.027-0.176 2.274-0.04 4.215 0.84 1.26 0.587 0.729 0.815-1.256 0.404-1.896-0.392-1.06-0.2-2.383-0.435-2.228-0.361-2.619-0.475-0.576-0.809z"/>
- <path fill="#666" d="m166.814 72.44c0.992-0.151 2.234-0.005 4.14 0.83 1.159 0.508 0.677 0.582-1.281 0.183-1.883-0.383-0.987-0.174-2.276-0.4-2.183-0.346-2.566-0.325-0.583-0.613z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#666" d="m159.99 128.249c-9.36 0.36-24.192-25.848-24.552-14.976-0.288 9.216 0.216 9.072 0.216 18 0 5.976-2.736 6.408-8.64 15.408-3.024 4.752-5.4 9.864-7.272 15.048-1.152 3.096-2.232 6.336-3.096 9.504-0.36 1.584-1.008 3.24-1.368 4.824-2.952 10.872-13.464 24.264-15.912 35.136-2.448 10.8-5.328 17.712-4.968 32.185 0.36 14.472 0.504 10.295 4.896 13.896 4.32 3.601 8.784 6.983 15.624 13.032 7.2 6.264 22.177 17.208 24.192 20.592 2.16 3.456 2.088 11.232 0.792 13.752-1.296 2.448-12.6 3.816-12.528 3.816-0.071 0 9.864 13.68 11.809 15.623 1.872 1.873 9.936 10.873 42.768 4.752 18.504-3.455 32.832-13.823 43.2-23.832 13.392-13.031 6.624-16.775 8.352-23.327 2.521-9.433 10.729-12.96 12.601-23.616 0.216-1.512 0.72-2.664 2.088-4.896 2.088-3.168 1.584-9.432 1.584-15.191 0-14.977-1.729-30.24-5.185-41.472-3.168-10.512-8.208-17.856-12.527-27.36-8.641-18.936-8.208-27.432-15.912-39.528-8.784-13.968-4.464-23.256-16.128-22.68-14.546 0.79-26.282 20.734-40.034 21.31z"/>
- <path fill="#6d6d6d" d="m159.973 129.334c-9.281 0.353-23.746-25.511-24.242-15.179-0.316 8.755 0.1 8.678 0.03 17.247-0.15 5.87-2.953 6.637-8.727 15.481-3.013 4.763-5.273 9.812-6.993 14.877-0.968 3.253-1.56 6.422-2.43 9.526-0.415 1.642-1.497 3.187-2.185 5.042-3.254 10.78-13.545 24.182-15.961 34.877-2.466 10.81-5.37 17.694-4.961 32.141 0.366 14 0.395 10.177 4.773 13.816 4.283 3.616 8.839 7.069 15.662 13.103 7.183 6.248 22.237 17.216 24.243 20.588 2.149 3.444 2.131 11.317 0.844 13.823-1.284 2.439-12.579 3.875-12.508 3.875-0.071 0 9.815 13.566 11.757 15.508 1.87 1.87 9.902 10.809 42.678 4.704 18.524-3.455 33.124-13.753 43.078-23.856 12.789-12.762 6.107-16.773 7.826-23.291 2.513-9.416 11.277-12.961 13.143-23.602 0.216-1.508 0.754-2.654 2.113-4.876 2.096-3.202 1.561-9.447 1.582-15.185 0.067-15.027-1.705-30.234-5.159-41.434-3.171-10.483-8.204-17.817-12.515-27.305-8.624-18.906-8.221-27.415-15.933-39.474-8.586-13.613-4.601-22.583-16.011-21.99-14.374 0.826-26.375 21.016-40.104 21.584z"/>
- <path fill="#757575" d="m159.955 130.419c-9.201 0.346-23.299-25.175-23.931-15.383-0.344 8.295-0.017 8.284-0.156 16.494-0.301 5.764-3.17 6.867-8.812 15.555-3.002 4.774-5.148 9.76-6.714 14.706-0.784 3.41-0.889 6.508-1.764 9.548-0.471 1.699-1.986 3.133-3.003 5.259-3.554 10.688-13.624 24.1-16.009 34.619-2.483 10.82-5.411 17.678-4.954 32.097 0.373 13.528 0.285 10.058 4.651 13.739 4.244 3.632 8.893 7.154 15.699 13.171 7.167 6.233 22.299 17.224 24.294 20.585 2.142 3.432 2.175 11.404 0.896 13.896-1.271 2.428-12.558 3.932-12.486 3.932-0.071 0 9.768 13.453 11.705 15.392 1.867 1.867 9.867 10.744 42.588 4.655 18.545-3.453 33.415-13.682 42.956-23.879 12.187-12.492 5.591-16.771 7.3-23.258 2.507-9.398 11.826-12.959 13.687-23.586 0.215-1.5 0.788-2.643 2.138-4.854 2.104-3.235 1.538-9.462 1.58-15.178 0.133-15.076-1.681-30.228-5.135-41.394-3.173-10.455-8.199-17.779-12.501-27.25-8.609-18.877-8.234-27.399-15.952-39.42-8.389-13.258-4.739-21.911-15.895-21.301-14.21 0.859-26.474 21.295-40.182 21.855z"/>
- <path fill="#7c7c7c" d="m159.938 131.504c-9.122 0.338-22.854-24.838-23.622-15.586-0.37 7.833-0.131 7.89-0.341 15.741-0.452 5.657-3.388 7.096-8.899 15.628-2.99 4.785-5.021 9.708-6.433 14.535-0.602 3.566-0.218 6.594-1.099 9.57-0.526 1.756-2.475 3.08-3.82 5.477-3.854 10.596-13.703 24.016-16.057 34.361-2.501 10.829-5.453 17.66-4.948 32.052 0.38 13.059 0.177 9.939 4.529 13.66 4.208 3.648 8.948 7.239 15.739 13.242 7.149 6.217 22.358 17.232 24.345 20.581 2.13 3.42 2.216 11.489 0.946 13.968-1.259 2.417-12.538 3.99-12.466 3.99-0.072 0 9.718 13.34 11.653 15.275 1.865 1.864 9.833 10.681 42.498 4.607 18.565-3.453 33.706-13.609 42.834-23.902 11.583-12.223 5.074-16.771 6.774-23.223 2.499-9.382 12.375-12.959 14.229-23.57 0.215-1.496 0.821-2.633 2.162-4.834 2.111-3.271 1.516-9.478 1.578-15.173 0.199-15.125-1.657-30.221-5.109-41.354-3.177-10.427-8.196-17.741-12.488-27.195-8.594-18.848-8.247-27.383-15.972-39.366-8.192-12.903-4.877-21.239-15.779-20.612-14.041 0.894-26.569 21.576-40.254 22.128z"/>
- <path fill="#848484" d="m159.921 132.589c-9.043 0.331-22.406-24.502-23.312-15.79-0.398 7.373-0.247 7.496-0.527 14.988-0.602 5.551-3.604 7.326-8.984 15.702-2.98 4.796-4.896 9.656-6.154 14.364-0.417 3.723 0.455 6.679-0.432 9.592-0.582 1.813-2.964 3.026-4.639 5.694-4.153 10.504-13.782 23.936-16.104 34.104-2.519 10.838-5.495 17.643-4.941 32.008 0.387 12.586 0.067 9.819 4.407 13.582 4.171 3.664 9.002 7.324 15.777 13.311 7.132 6.201 22.419 17.24 24.396 20.576 2.12 3.41 2.259 11.578 0.998 14.041-1.247 2.408-12.517 4.049-12.446 4.049-0.07 0 9.67 13.227 11.604 15.16 1.861 1.861 9.798 10.615 42.409 4.558 18.584-3.45 33.996-13.538 42.711-23.926 10.979-11.952 4.557-16.769 6.248-23.187 2.491-9.367 12.924-12.959 14.771-23.557 0.215-1.49 0.856-2.622 2.188-4.813 2.118-3.305 1.491-9.494 1.575-15.166 0.267-15.174-1.635-30.215-5.086-41.314-3.179-10.399-8.19-17.703-12.473-27.141-8.579-18.818-8.262-27.366-15.994-39.312-7.993-12.547-5.013-20.565-15.661-19.922-13.876 0.927-26.669 21.855-40.331 22.399z"/>
- <path fill="#8c8c8c" d="m159.903 133.674c-8.963 0.323-21.961-24.165-23.001-15.994-0.426 6.912-0.363 7.102-0.713 14.236-0.753 5.445-3.821 7.554-9.071 15.775-2.969 4.807-4.768 9.604-5.875 14.192-0.232 3.881 1.128 6.766 0.234 9.615-0.638 1.87-3.452 2.972-5.455 5.911-4.455 10.413-13.862 23.853-16.153 33.845-2.537 10.849-5.537 17.625-4.935 31.963 0.393 12.115-0.042 9.701 4.285 13.505 4.133 3.68 9.057 7.409 15.814 13.38 7.116 6.188 22.48 17.248 24.447 20.574 2.109 3.398 2.301 11.662 1.049 14.113-1.235 2.396-12.496 4.104-12.425 4.104-0.071 0 9.622 13.114 11.552 15.045 1.86 1.858 9.763 10.552 42.319 4.509 18.604-3.449 34.288-13.467 42.589-23.949 10.377-11.682 4.04-16.766 5.721-23.15 2.486-9.35 13.474-12.959 15.316-23.542 0.214-1.483 0.89-2.611 2.213-4.793 2.126-3.339 1.468-9.507 1.573-15.158 0.333-15.224-1.611-30.208-5.062-41.276-3.181-10.37-8.186-17.664-12.459-27.085-8.563-18.789-8.275-27.35-16.014-39.258-7.796-12.192-5.151-19.893-15.545-19.233-13.707 0.961-26.763 22.134-40.404 22.671z"/>
- <path fill="#939393" d="m159.886 134.759c-8.885 0.316-21.516-23.829-22.691-16.197-0.454 6.451-0.479 6.708-0.899 13.482-0.903 5.339-4.038 7.784-9.157 15.849-2.957 4.818-4.642 9.552-5.595 14.021-0.05 4.037 1.799 6.852 0.9 9.637-0.693 1.928-3.941 2.919-6.273 6.129-4.756 10.32-13.941 23.77-16.201 33.587-2.555 10.858-5.579 17.608-4.928 31.92 0.399 11.644-0.151 9.581 4.162 13.424 4.096 3.697 9.111 7.494 15.854 13.451 7.099 6.17 22.541 17.256 24.498 20.569 2.1 3.387 2.344 11.75 1.101 14.186-1.223 2.387-12.476 4.163-12.404 4.163-0.071 0 9.573 13.001 11.5 14.929 1.857 1.856 9.729 10.488 42.229 4.461 18.625-3.449 34.579-13.396 42.467-23.973 9.774-11.412 3.523-16.764 5.195-23.115 2.479-9.334 14.022-12.959 15.858-23.527 0.214-1.479 0.924-2.601 2.238-4.772 2.134-3.373 1.445-9.522 1.571-15.151 0.399-15.273-1.587-30.201-5.036-41.237-3.185-10.342-8.184-17.625-12.446-27.03-8.548-18.76-8.288-27.333-16.034-39.204-7.598-11.837-5.289-19.221-15.428-18.544-13.543 0.994-26.863 22.413-40.481 22.942z"/>
- <path fill="#9b9b9b" d="m159.868 135.844c-8.805 0.308-21.068-23.492-22.381-16.401-0.481 5.991-0.594 6.314-1.085 12.73-1.053 5.232-4.253 8.013-9.243 15.922-2.946 4.829-4.515 9.5-5.314 13.85 0.133 4.194 2.471 6.937 1.565 9.658-0.749 1.986-4.43 2.866-7.091 6.347-5.056 10.229-14.021 23.689-16.249 33.329-2.572 10.868-5.621 17.591-4.921 31.876 0.405 11.172-0.261 9.463 4.04 13.346 4.058 3.713 9.166 7.58 15.892 13.521 7.082 6.155 22.601 17.265 24.548 20.567 2.092 3.373 2.388 11.834 1.152 14.256-1.21 2.377-12.454 4.222-12.383 4.222-0.071 0 9.523 12.888 11.45 14.813 1.854 1.854 9.692 10.424 42.138 4.412 18.645-3.447 34.871-13.324 42.345-23.996 9.171-11.143 3.007-16.762 4.669-23.08 2.472-9.317 14.572-12.959 16.401-23.514 0.214-1.473 0.958-2.588 2.265-4.75 2.142-3.408 1.421-9.539 1.568-15.145 0.466-15.324-1.564-30.196-5.012-41.198-3.187-10.313-8.179-17.587-12.433-26.976-8.533-18.73-8.301-27.316-16.054-39.149-7.401-11.482-5.426-18.548-15.313-17.855-13.373 1.029-26.958 22.694-40.554 23.215z"/>
- <path fill="#a3a3a3" d="m159.851 136.929c-8.727 0.301-20.622-23.156-22.071-16.604-0.509 5.529-0.71 5.919-1.271 11.976-1.203 5.126-4.47 8.243-9.328 15.996-2.936 4.84-4.39 9.448-5.036 13.679 0.316 4.351 3.143 7.023 2.231 9.68-0.804 2.043-4.919 2.812-7.908 6.563-5.356 10.137-14.101 23.607-16.298 33.072-2.589 10.877-5.661 17.574-4.913 31.832 0.412 10.699-0.37 9.342 3.918 13.268 4.021 3.729 9.221 7.664 15.93 13.59 7.064 6.139 22.661 17.271 24.599 20.563 2.081 3.363 2.43 11.922 1.204 14.33-1.198 2.365-12.434 4.278-12.363 4.278-0.07 0 9.477 12.774 11.399 14.697 1.851 1.851 9.659 10.36 42.048 4.364 18.666-3.447 35.162-13.254 42.223-24.021 8.568-10.873 2.49-16.761 4.144-23.045 2.464-9.301 15.121-12.958 16.943-23.498 0.215-1.467 0.992-2.579 2.29-4.729 2.148-3.441 1.398-9.553 1.566-15.139 0.532-15.373-1.541-30.189-4.987-41.158-3.188-10.285-8.174-17.549-12.419-26.921-8.518-18.701-8.313-27.3-16.073-39.096-7.204-11.126-5.564-17.875-15.196-17.165-13.21 1.064-27.058 22.975-40.632 23.488z"/>
- <path fill="#aaa" d="m159.834 138.014c-8.646 0.293-20.176-22.819-21.761-16.808-0.536 5.069-0.826 5.526-1.457 11.224-1.354 5.02-4.687 8.472-9.416 16.069-2.924 4.851-4.262 9.396-4.756 13.508 0.501 4.507 3.814 7.109 2.897 9.702-0.858 2.1-5.406 2.759-8.725 6.782-5.657 10.045-14.181 23.524-16.347 32.812-2.606 10.888-5.703 17.557-4.906 31.787 0.418 10.229-0.479 9.225 3.795 13.189 3.984 3.745 9.275 7.749 15.968 13.66 7.048 6.124 22.723 17.279 24.651 20.559 2.07 3.352 2.472 12.008 1.255 14.402-1.186 2.355-12.414 4.337-12.343 4.337-0.071 0 9.428 12.66 11.348 14.581 1.85 1.848 9.624 10.297 41.958 4.314 18.687-3.444 35.453-13.18 42.102-24.043 7.965-10.602 1.973-16.758 3.616-23.01 2.457-9.283 15.67-12.957 17.487-23.482 0.214-1.461 1.026-2.568 2.315-4.709 2.155-3.477 1.375-9.568 1.563-15.131 0.6-15.424-1.518-30.184-4.963-41.119-3.192-10.257-8.17-17.511-12.405-26.866-8.502-18.672-8.328-27.284-16.095-39.042-7.005-10.771-5.701-17.203-15.078-16.476-13.04 1.098-27.152 23.255-40.703 23.76z"/>
- <path fill="#b2b2b2" d="m159.816 139.099c-8.567 0.286-19.729-22.483-21.45-17.012-0.563 4.608-0.942 5.132-1.643 10.471-1.506 4.914-4.904 8.701-9.502 16.143-2.913 4.862-4.137 9.344-4.477 13.336 0.685 4.665 4.486 7.195 3.564 9.725-0.915 2.157-5.897 2.705-9.543 6.999-5.958 9.953-14.262 23.443-16.396 32.554-2.624 10.898-5.745 17.54-4.9 31.744 0.426 9.757-0.588 9.105 3.674 13.111 3.945 3.761 9.33 7.834 16.006 13.729 7.032 6.109 22.783 17.288 24.702 20.557 2.06 3.338 2.515 12.094 1.306 14.473-1.173 2.346-12.392 4.395-12.321 4.395-0.07 0 9.379 12.549 11.296 14.465 1.847 1.848 9.591 10.234 41.868 4.268 18.706-3.444 35.745-13.11 41.979-24.066 7.361-10.332 1.456-16.757 3.091-22.974 2.45-9.269 16.219-12.958 18.03-23.47 0.213-1.455 1.06-2.557 2.34-4.688 2.164-3.509 1.352-9.583 1.562-15.124 0.665-15.473-1.494-30.177-4.938-41.08-3.195-10.228-8.166-17.472-12.393-26.811-8.486-18.642-8.341-27.267-16.114-38.987-6.809-10.416-5.838-16.531-14.962-15.787-12.873 1.129-27.25 23.531-40.779 24.029z"/>
- <path fill="#bababa" d="m159.799 140.184c-8.487 0.279-19.282-22.146-21.141-17.215-0.591 4.147-1.057 4.737-1.828 9.717-1.656 4.808-5.121 8.931-9.588 16.217-2.902 4.873-4.01 9.292-4.197 13.165 0.868 4.822 5.158 7.281 4.23 9.747-0.971 2.215-6.385 2.651-10.361 7.216-6.258 9.861-14.339 23.36-16.442 32.297-2.643 10.906-5.787 17.521-4.894 31.699 0.432 9.285-0.697 8.986 3.552 13.032 3.908 3.776 9.384 7.919 16.043 13.799 7.016 6.093 22.845 17.296 24.753 20.552 2.051 3.328 2.559 12.18 1.358 14.547-1.161 2.334-12.372 4.451-12.301 4.451-0.071 0 9.33 12.436 11.245 14.35 1.844 1.844 9.555 10.17 41.777 4.219 18.727-3.443 36.036-13.039 41.857-24.09 6.759-10.063 0.939-16.756 2.565-22.939 2.442-9.25 16.768-12.957 18.572-23.453 0.213-1.451 1.095-2.547 2.365-4.668 2.171-3.543 1.329-9.599 1.56-15.117 0.732-15.522-1.471-30.172-4.913-41.042-3.197-10.2-8.161-17.433-12.379-26.756-8.471-18.612-8.354-27.25-16.135-38.933-6.609-10.061-5.976-15.858-14.845-15.098-12.706 1.165-27.347 23.813-40.853 24.303z"/>
- <path fill="#c1c1c1" d="m159.781 141.269c-8.408 0.271-18.837-21.81-20.83-17.419-0.619 3.687-1.173 4.344-2.014 8.965-1.808 4.701-5.338 9.16-9.674 16.29-2.892 4.884-3.885 9.24-3.918 12.994 1.052 4.978 5.829 7.367 4.896 9.769-1.026 2.272-6.874 2.598-11.178 7.434-6.56 9.769-14.419 23.277-16.491 32.039-2.66 10.916-5.829 17.504-4.887 31.656 0.438 8.813-0.807 8.867 3.43 12.953 3.87 3.793 9.438 8.004 16.082 13.868 6.997 6.077 22.904 17.304 24.803 20.55 2.041 3.314 2.601 12.266 1.409 14.617-1.149 2.324-12.351 4.51-12.28 4.51-0.07 0 9.282 12.321 11.194 14.233 1.841 1.842 9.521 10.106 41.688 4.17 18.746-3.44 36.326-12.967 41.734-24.112 6.156-9.793 0.423-16.754 2.038-22.904 2.438-9.235 17.318-12.957 19.117-23.438 0.212-1.444 1.128-2.536 2.39-4.647 2.18-3.578 1.306-9.613 1.558-15.11 0.799-15.571-1.447-30.165-4.889-41.002-3.2-10.172-8.156-17.395-12.364-26.701-8.456-18.583-8.367-27.234-16.155-38.88-6.413-9.705-6.114-15.185-14.729-14.408-12.541 1.197-27.445 24.091-40.93 24.573z"/>
- <path fill="#c9c9c9" d="m159.764 142.354c-8.329 0.264-18.392-21.473-20.521-17.622-0.646 3.225-1.289 3.949-2.2 8.211-1.957 4.596-5.555 9.39-9.761 16.364-2.879 4.895-3.757 9.188-3.638 12.823 1.235 5.135 6.502 7.453 5.562 9.791-1.081 2.329-7.362 2.544-11.995 7.651-6.859 9.677-14.499 23.195-16.54 31.78-2.677 10.927-5.87 17.488-4.879 31.611 0.444 8.344-0.916 8.748 3.307 12.875 3.834 3.81 9.492 8.09 16.121 13.939 6.98 6.061 22.965 17.311 24.854 20.545 2.031 3.303 2.643 12.352 1.461 14.69-1.137 2.313-12.33 4.567-12.26 4.567-0.07 0 9.233 12.209 11.143 14.117 1.839 1.84 9.486 10.043 41.599 4.122 18.767-3.44 36.618-12.896 41.612-24.137 5.554-9.522-0.094-16.751 1.513-22.868 2.43-9.219 17.866-12.957 19.659-23.424 0.213-1.439 1.162-2.525 2.415-4.627 2.188-3.612 1.282-9.629 1.556-15.104 0.865-15.621-1.424-30.158-4.864-40.962-3.202-10.144-8.153-17.357-12.351-26.646-8.441-18.554-8.381-27.218-16.176-38.826-6.216-9.35-6.251-14.513-14.612-13.719-12.374 1.235-27.543 24.375-41.005 24.849z"/>
- <path fill="#d1d1d1" d="m159.747 143.439c-8.25 0.256-17.944-21.137-20.21-17.826-0.675 2.765-1.406 3.555-2.386 7.459-2.108 4.489-5.772 9.619-9.847 16.437-2.869 4.906-3.631 9.136-3.358 12.652 1.419 5.292 7.174 7.538 6.228 9.812-1.137 2.387-7.852 2.491-12.813 7.869-7.161 9.586-14.579 23.114-16.588 31.522-2.695 10.938-5.912 17.471-4.873 31.568 0.451 7.871-1.025 8.629 3.185 12.797 3.796 3.824 9.547 8.174 16.158 14.008 6.964 6.047 23.026 17.32 24.905 20.541 2.021 3.292 2.686 12.439 1.513 14.764-1.125 2.303-12.31 4.625-12.239 4.625-0.07 0 9.186 12.094 11.092 14.002 1.836 1.836 9.45 9.978 41.509 4.072 18.786-3.439 36.909-12.824 41.49-24.16 4.948-9.252-0.611-16.748 0.985-22.832 2.423-9.203 18.415-12.957 20.203-23.41 0.212-1.434 1.196-2.514 2.44-4.605 2.193-3.646 1.259-9.645 1.553-15.098 0.932-15.67-1.4-30.151-4.84-40.922-3.205-10.115-8.148-17.319-12.336-26.592-8.427-18.524-8.396-27.201-16.197-38.771-6.017-8.995-6.388-13.84-14.495-13.03-12.207 1.266-27.64 24.652-41.079 25.118z"/>
- <path fill="#d8d8d8" d="m159.729 144.524c-8.17 0.249-17.498-20.8-19.9-18.03-0.702 2.304-1.521 3.162-2.571 6.706-2.259 4.383-5.988 9.848-9.933 16.511-2.858 4.917-3.504 9.084-3.079 12.48 1.604 5.449 7.846 7.625 6.895 9.835-1.193 2.444-8.342 2.438-13.631 8.087-7.461 9.493-14.658 23.031-16.637 31.262-2.712 10.947-5.953 17.455-4.865 31.524 0.458 7.399-1.135 8.511 3.063 12.718 3.758 3.842 9.601 8.26 16.196 14.078 6.946 6.031 23.087 17.328 24.956 20.538 2.011 3.28 2.729 12.524 1.563 14.835-1.112 2.293-12.289 4.684-12.218 4.684-0.071 0 9.136 11.981 11.04 13.886 1.834 1.834 9.417 9.913 41.419 4.024 18.807-3.438 37.2-12.752 41.368-24.184 4.346-8.982-1.128-16.747 0.46-22.798 2.416-9.187 18.964-12.956 20.746-23.394 0.211-1.429 1.229-2.504 2.465-4.586 2.202-3.681 1.236-9.658 1.551-15.091 0.998-15.72-1.377-30.146-4.814-40.884-3.208-10.086-8.145-17.28-12.323-26.536-8.411-18.495-8.408-27.185-16.217-38.717-5.82-8.64-6.526-13.168-14.38-12.341-12.04 1.303-27.736 24.934-41.154 25.393z"/>
- <path fill="#e0e0e0" d="m159.712 145.609c-8.091 0.241-17.052-20.464-19.59-18.233-0.729 1.843-1.637 2.767-2.757 5.953-2.409 4.276-6.206 10.077-10.02 16.584-2.847 4.928-3.378 9.032-2.8 12.309 1.787 5.606 8.519 7.711 7.561 9.857-1.248 2.502-8.829 2.384-14.448 8.304-7.761 9.402-14.738 22.95-16.684 31.006-2.731 10.955-5.996 17.436-4.859 31.48 0.464 6.928-1.244 8.389 2.939 12.639 3.722 3.857 9.656 8.344 16.234 14.148 6.932 6.014 23.148 17.336 25.008 20.533 2 3.268 2.771 12.611 1.615 14.907-1.1 2.282-12.268 4.741-12.198 4.741-0.069 0 9.089 11.867 10.989 13.77 1.831 1.831 9.382 9.85 41.329 3.977 18.827-3.438 37.492-12.683 41.246-24.207 3.743-8.715-1.646-16.746-0.066-22.762 2.409-9.171 19.514-12.957 21.289-23.381 0.211-1.422 1.265-2.494 2.49-4.564 2.21-3.715 1.213-9.674 1.549-15.084 1.065-15.77-1.354-30.139-4.791-40.844-3.21-10.058-8.14-17.241-12.309-26.481-8.396-18.466-8.421-27.168-16.237-38.664-5.622-8.284-6.663-12.495-14.262-11.651-11.872 1.335-27.833 25.212-41.228 25.663z"/>
- <path fill="#e8e8e8" d="m159.694 146.694c-8.012 0.234-16.605-20.127-19.279-18.437-0.757 1.383-1.753 2.373-2.943 5.2-2.56 4.171-6.423 10.307-10.105 16.658-2.835 4.939-3.251 8.979-2.52 12.138 1.97 5.763 9.189 7.796 8.226 9.879-1.303 2.559-9.318 2.33-15.265 8.521-8.063 9.31-14.818 22.867-16.733 30.748-2.748 10.967-6.037 17.419-4.853 31.436 0.472 6.457-1.353 8.271 2.818 12.562 3.685 3.873 9.711 8.429 16.273 14.218 6.913 6 23.207 17.344 25.058 20.529 1.991 3.257 2.814 12.697 1.666 14.98-1.087 2.271-12.247 4.799-12.177 4.799-0.07 0 9.04 11.755 10.938 13.654 1.829 1.828 9.349 9.785 41.239 3.926 18.847-3.435 37.783-12.609 41.124-24.229 3.14-8.444-2.161-16.743-0.592-22.728 2.401-9.152 20.062-12.955 21.831-23.364 0.211-1.417 1.298-2.483 2.516-4.544 2.217-3.748 1.19-9.689 1.547-15.076 1.132-15.82-1.331-30.133-4.766-40.806-3.213-10.03-8.136-17.203-12.296-26.427-8.38-18.436-8.435-27.151-16.257-38.609-5.425-7.929-6.802-11.822-14.146-10.962-11.706 1.368-27.931 25.491-41.304 25.934z"/>
- <path fill="#efefef" d="m159.677 147.779c-7.934 0.226-16.16-19.791-18.97-18.64-0.785 0.921-1.869 1.979-3.13 4.447-2.71 4.064-6.639 10.536-10.19 16.731-2.824 4.95-3.125 8.928-2.24 11.967 2.152 5.919 9.86 7.882 8.892 9.901-1.358 2.616-9.808 2.277-16.083 8.739-8.363 9.218-14.896 22.784-16.781 30.489-2.766 10.977-6.079 17.402-4.846 31.393 0.478 5.984-1.462 8.152 2.696 12.482 3.646 3.889 9.765 8.514 16.311 14.287 6.896 5.983 23.269 17.352 25.109 20.526 1.98 3.245 2.855 12.782 1.718 15.052-1.076 2.262-12.227 4.857-12.156 4.857-0.07 0 8.991 11.641 10.887 13.537 1.826 1.826 9.313 9.723 41.148 3.879 18.868-3.434 38.074-12.538 41.002-24.254 2.537-8.174-2.678-16.741-1.119-22.69 2.396-9.138 20.612-12.957 22.375-23.351 0.212-1.412 1.332-2.473 2.541-4.523 2.226-3.783 1.166-9.704 1.545-15.07 1.197-15.869-1.307-30.125-4.741-40.766-3.215-10.002-8.131-17.165-12.282-26.372-8.365-18.407-8.447-27.135-16.277-38.555-5.228-7.574-6.938-11.15-14.029-10.272-11.541 1.402-28.029 25.771-41.38 26.206z"/>
- <path fill="#f7f7f7" d="m159.66 148.864c-7.854 0.219-15.714-19.454-18.66-18.844-0.812 0.461-1.983 1.585-3.314 3.694-2.86 3.958-6.856 10.766-10.278 16.805-2.813 4.961-2.998 8.876-1.96 11.796 2.337 6.076 10.533 7.968 9.558 9.923-1.415 2.673-10.296 2.223-16.899 8.956-8.664 9.126-14.978 22.702-16.83 30.23-2.783 10.986-6.121 17.386-4.839 31.349 0.484 5.515-1.571 8.033 2.573 12.403 3.609 3.906 9.82 8.6 16.35 14.357 6.88 5.969 23.329 17.36 25.16 20.523 1.971 3.232 2.898 12.869 1.77 15.124-1.063 2.252-12.206 4.915-12.136 4.915-0.07 0 8.942 11.527 10.835 13.422 1.824 1.822 9.279 9.658 41.059 3.83 18.889-3.434 38.366-12.467 40.881-24.278 1.934-7.903-3.195-16.739-1.646-22.655 2.388-9.121 21.161-12.955 22.918-23.336 0.211-1.404 1.366-2.461 2.566-4.502 2.232-3.816 1.143-9.719 1.542-15.063 1.265-15.92-1.283-30.12-4.717-40.727-3.219-9.974-8.128-17.127-12.269-26.317-8.349-18.378-8.461-27.119-16.298-38.501-5.029-7.219-7.075-10.478-13.912-9.584-11.373 1.438-28.126 26.053-41.454 26.48z"/>
- <path fill="#fff" d="m159.642 149.949c-7.774 0.211-15.268-19.118-18.35-19.048-0.84 0-2.1 1.191-3.501 2.941-3.011 3.852-7.072 10.995-10.363 16.878-2.803 4.972-2.872 8.824-1.682 11.625 2.521 6.233 11.205 8.054 10.225 9.945-1.471 2.731-10.785 2.17-17.719 9.174-8.964 9.034-15.056 22.621-16.877 29.973-2.801 10.995-6.163 17.368-4.832 31.304 0.49 5.043-1.681 7.914 2.451 12.325 3.571 3.923 9.874 8.685 16.387 14.427 6.863 5.953 23.391 17.368 25.211 20.521 1.962 3.221 2.942 12.954 1.821 15.196-1.051 2.24-12.185 4.972-12.115 4.972-0.069 0 8.895 11.416 10.784 13.307 1.821 1.82 9.244 9.595 40.97 3.781 18.907-3.431 38.656-12.396 40.758-24.302 1.331-7.633-3.712-16.736-2.171-22.619 2.381-9.104 21.71-12.956 23.461-23.321 0.21-1.399 1.399-2.45 2.591-4.481 2.24-3.852 1.12-9.734 1.54-15.057 1.331-15.968-1.26-30.113-4.692-40.688-3.221-9.945-8.123-17.088-12.255-26.262-8.334-18.348-8.474-27.102-16.318-38.447-4.832-6.863-7.213-9.805-13.796-8.894-11.205 1.469-28.222 26.33-41.528 26.75z"/>
- </g>
- <path fill="#995900" d="m152.553 88.8575c5.256-0.648 12.456 0.648 15.769 3.096 3.096 2.304 5.256 3.528 8.063 4.464 9.433 3.096 21.816 4.536 21.24 13.032-0.648 10.151-3.6 14.688-12.024 17.351-6.768 2.088-18.863 13.824-28.224 13.824-4.176 0-10.008 0.216-13.392-1.008-3.24-1.152-7.776-6.624-13.104-11.016-5.328-4.32-10.296-8.928-10.439-14.976-0.217-6.407 3.96-8.496 9.863-13.607 3.097-2.736 8.712-7.272 12.601-9.288 3.599-1.799 5.903-1.439 9.647-1.872z"/>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#9e5f00" d="m165.068 78.951c5.225-0.644 12.384 0.645 15.677 3.079 3.078 2.29 5.227 3.51 8.018 4.438 9.375 3.078 21.729 4.529 21.159 12.973-0.641 10.09-3.669 14.581-12.041 17.223-6.723 2.073-18.768 13.589-28.07 13.64-4.21 0.032-9.926 0.234-13.287-0.977-3.215-1.142-7.737-6.608-13.031-10.969-5.291-4.292-10.26-8.774-10.317-14.765-0.153-6.252 3.912-8.411 9.773-13.488 3.071-2.71 8.594-7.303 12.463-9.333 3.563-1.803 5.933-1.392 9.656-1.821z"/>
- <path fill="#a36400" d="m165.177 79.044c5.195-0.641 12.313 0.64 15.587 3.06 3.06 2.278 5.194 3.494 7.971 4.413 9.317 3.06 21.641 4.522 21.078 12.914-0.634 10.027-3.737 14.474-12.058 17.094-6.678 2.057-18.673 13.352-27.919 13.454-4.241 0.064-9.842 0.252-13.18-0.945-3.19-1.133-7.7-6.592-12.96-10.921-5.254-4.264-10.222-8.622-10.192-14.555-0.093-6.099 3.863-8.329 9.681-13.369 3.048-2.685 8.478-7.335 12.328-9.379 3.526-1.804 5.963-1.338 9.664-1.766z"/>
- <path fill="#a86a00" d="m165.287 79.138c5.165-0.637 12.241 0.637 15.496 3.043 3.042 2.264 5.165 3.476 7.924 4.387 9.26 3.042 21.556 4.515 20.998 12.854-0.627 9.968-3.805 14.368-12.074 16.967-6.633 2.042-18.576 13.117-27.766 13.27-4.276 0.096-9.759 0.27-13.075-0.914-3.165-1.123-7.661-6.577-12.887-10.874-5.217-4.236-10.187-8.468-10.069-14.345-0.03-5.943 3.815-8.244 9.589-13.249 3.023-2.66 8.36-7.366 12.191-9.424 3.49-1.808 5.993-1.291 9.673-1.715z"/>
- <path fill="#ad7000" d="m165.396 79.23c5.135-0.633 12.17 0.633 15.404 3.025 3.025 2.251 5.137 3.46 7.88 4.361 9.201 3.025 21.467 4.508 20.917 12.796-0.62 9.905-3.874 14.26-12.093 16.837-6.586 2.027-18.479 12.882-27.611 13.086-4.311 0.127-9.677 0.287-12.971-0.883-3.14-1.113-7.622-6.561-12.814-10.826-5.18-4.208-10.148-8.315-9.945-14.135 0.031-5.789 3.768-8.16 9.497-13.129 2.999-2.635 8.244-7.398 12.055-9.47 3.454-1.808 6.023-1.24 9.681-1.662z"/>
- <path fill="#b27600" d="m165.506 79.325c5.105-0.63 12.099 0.629 15.314 3.007 3.007 2.237 5.104 3.442 7.832 4.335 9.145 3.007 21.38 4.501 20.837 12.737-0.614 9.844-3.943 14.154-12.109 16.709-6.541 2.011-18.385 12.645-27.46 12.9-4.342 0.16-9.592 0.306-12.862-0.851-3.115-1.103-7.584-6.545-12.743-10.779-5.144-4.18-10.112-8.162-9.821-13.924 0.092-5.634 3.718-8.076 9.405-13.009 2.975-2.609 8.126-7.429 11.919-9.514 3.416-1.812 6.052-1.192 9.688-1.611z"/>
- <path fill="#b77b00" d="m165.615 79.417c5.075-0.626 12.026 0.626 15.224 2.989 2.989 2.225 5.075 3.425 7.786 4.31 9.087 2.989 21.292 4.494 20.756 12.678-0.606 9.781-4.012 14.046-12.126 16.581-6.496 1.997-18.289 12.41-27.307 12.716-4.376 0.191-9.51 0.323-12.758-0.82-3.09-1.094-7.546-6.53-12.671-10.732-5.106-4.152-10.074-8.008-9.697-13.713 0.155-5.479 3.67-7.992 9.313-12.889 2.951-2.585 8.011-7.461 11.783-9.56 3.38-1.814 6.083-1.143 9.697-1.56z"/>
- <path fill="#bc8100" d="m165.725 79.511c5.044-0.622 11.954 0.622 15.133 2.972 2.971 2.211 5.045 3.408 7.739 4.284 9.029 2.971 21.205 4.487 20.675 12.619-0.6 9.719-4.079 13.939-12.143 16.451-6.45 1.982-18.192 12.175-27.153 12.532-4.41 0.223-9.428 0.341-12.653-0.789-3.065-1.084-7.507-6.514-12.598-10.684-5.069-4.124-10.038-7.855-9.574-13.504 0.217-5.324 3.622-7.908 9.222-12.77 2.926-2.559 7.894-7.492 11.646-9.605 3.344-1.816 6.113-1.092 9.706-1.506z"/>
- <path fill="#c18700" d="m165.834 79.604c5.015-0.618 11.883 0.619 15.043 2.954 2.953 2.198 5.015 3.391 7.693 4.259 8.972 2.953 21.118 4.48 20.594 12.559-0.593 9.66-4.147 13.833-12.159 16.324-6.405 1.967-18.098 11.94-27.002 12.347-4.441 0.255-9.343 0.359-12.546-0.757-3.04-1.074-7.469-6.498-12.526-10.637-5.032-4.096-10-7.701-9.45-13.293 0.278-5.169 3.574-7.823 9.13-12.649 2.903-2.534 7.776-7.524 11.511-9.651 3.306-1.821 6.141-1.044 9.712-1.456z"/>
- <path fill="#c68d00" d="m165.944 79.697c4.984-0.615 11.811 0.614 14.952 2.936 2.935 2.184 4.983 3.374 7.646 4.233 8.915 2.935 21.031 4.473 20.515 12.5-0.586 9.597-4.218 13.726-12.177 16.195-6.36 1.951-18.002 11.703-26.849 12.162-4.476 0.287-9.261 0.377-12.441-0.726-3.015-1.064-7.431-6.482-12.453-10.589-4.995-4.068-9.965-7.549-9.326-13.083 0.34-5.015 3.524-7.741 9.038-12.531 2.878-2.508 7.658-7.555 11.374-9.696 3.269-1.82 6.171-0.992 9.721-1.401z"/>
- <path fill="#cc9200" d="m166.054 79.791c4.952-0.61 11.738 0.611 14.86 2.918 2.918 2.172 4.954 3.357 7.601 4.207 8.857 2.918 20.942 4.466 20.432 12.442-0.578 9.536-4.285 13.62-12.192 16.066-6.314 1.936-17.906 11.468-26.696 11.978-4.509 0.319-9.178 0.394-12.335-0.696-2.989-1.054-7.393-6.466-12.382-10.541-4.959-4.04-9.928-7.395-9.202-12.873 0.401-4.859 3.477-7.655 8.945-12.411 2.854-2.482 7.542-7.586 11.239-9.741 3.233-1.824 6.201-0.943 9.73-1.349z"/>
- <path fill="#d19800" d="m166.163 79.883c4.923-0.606 11.668 0.608 14.771 2.901 2.9 2.158 4.924 3.339 7.554 4.181 8.801 2.9 20.855 4.459 20.352 12.383-0.571 9.474-4.353 13.512-12.21 15.938-6.269 1.921-17.81 11.233-26.543 11.793-4.542 0.351-9.094 0.413-12.229-0.664-2.965-1.044-7.354-6.45-12.311-10.494-4.921-4.012-9.89-7.241-9.079-12.662 0.465-4.705 3.431-7.571 8.855-12.29 2.83-2.458 7.425-7.618 11.102-9.787 3.197-1.827 6.231-0.893 9.738-1.299z"/>
- <path fill="#d69e00" d="m166.273 79.978c4.893-0.603 11.596 0.603 14.679 2.882 2.883 2.145 4.895 3.323 7.507 4.156 8.744 2.882 20.77 4.452 20.272 12.324-0.565 9.412-4.422 13.406-12.228 15.81-6.224 1.905-17.714 10.996-26.39 11.608-4.576 0.383-9.012 0.431-12.124-0.633-2.94-1.034-7.316-6.434-12.237-10.446-4.884-3.984-9.854-7.089-8.955-12.452 0.525-4.551 3.382-7.489 8.764-12.171 2.805-2.432 7.307-7.649 10.965-9.832 3.16-1.829 6.261-0.845 9.747-1.246z"/>
- <path fill="#dba300" d="m166.382 80.07c4.863-0.599 11.525 0.6 14.59 2.865 2.864 2.131 4.862 3.305 7.461 4.13 8.686 2.864 20.682 4.445 20.19 12.264-0.559 9.352-4.491 13.299-12.244 15.681-6.179 1.89-17.619 10.761-26.237 11.423-4.608 0.415-8.929 0.449-12.018-0.601-2.915-1.024-7.277-6.418-12.166-10.399-4.847-3.956-9.815-6.935-8.831-12.241 0.587-4.396 3.333-7.404 8.671-12.051 2.782-2.407 7.191-7.681 10.83-9.878 3.123-1.829 6.29-0.793 9.754-1.193z"/>
- <path fill="#e0a900" d="m166.492 80.164c4.832-0.595 11.453 0.596 14.498 2.847 2.847 2.118 4.833 3.289 7.414 4.104 8.629 2.846 20.595 4.438 20.111 12.205-0.553 9.29-4.56 13.193-12.262 15.553-6.134 1.875-17.522 10.526-26.085 11.239-4.642 0.447-8.845 0.467-11.912-0.57-2.89-1.015-7.238-6.402-12.093-10.351-4.81-3.928-9.78-6.782-8.708-12.032 0.649-4.241 3.285-7.32 8.58-11.932 2.757-2.381 7.073-7.712 10.693-9.923 3.088-1.831 6.321-0.743 9.764-1.14z"/>
- <path fill="#e5af00" d="m166.601 80.257c4.803-0.592 11.382 0.592 14.407 2.829 2.829 2.105 4.804 3.271 7.368 4.079 8.571 2.828 20.507 4.431 20.029 12.146-0.544 9.228-4.627 13.085-12.277 15.423-6.089 1.861-17.427 10.29-25.932 11.055-4.676 0.478-8.763 0.484-11.807-0.539-2.865-1.005-7.2-6.387-12.021-10.304-4.772-3.9-9.742-6.629-8.583-11.821 0.711-4.085 3.236-7.236 8.487-11.812 2.732-2.357 6.957-7.744 10.557-9.968 3.052-1.834 6.351-0.694 9.772-1.088z"/>
- <path fill="#eab500" d="m166.711 80.351c4.772-0.588 11.31 0.589 14.317 2.811 2.811 2.092 4.771 3.254 7.321 4.054 8.514 2.81 20.42 4.424 19.948 12.087-0.538 9.165-4.695 12.979-12.294 15.295-6.044 1.845-17.332 10.054-25.779 10.869-4.708 0.511-8.68 0.503-11.7-0.507-2.84-0.995-7.163-6.371-11.949-10.257-4.736-3.872-9.706-6.475-8.46-11.61 0.773-3.931 3.188-7.152 8.396-11.692 2.709-2.331 6.839-7.775 10.421-10.013 3.013-1.839 6.38-0.645 9.779-1.037z"/>
- <path fill="#efba00" d="m166.82 80.443c4.742-0.584 11.238 0.585 14.226 2.794 2.794 2.078 4.743 3.237 7.276 4.027 8.456 2.793 20.332 4.417 19.868 12.029-0.531 9.104-4.766 12.872-12.313 15.167-5.997 1.83-17.234 9.819-25.626 10.685-4.742 0.542-8.596 0.52-11.595-0.476-2.815-0.985-7.124-6.355-11.877-10.209-4.699-3.844-9.668-6.322-8.336-11.4 0.835-3.778 3.14-7.068 8.304-11.573 2.686-2.306 6.724-7.807 10.285-10.059 2.978-1.84 6.411-0.595 9.788-0.985z"/>
- <path fill="#f4c000" d="m166.93 80.537c4.711-0.58 11.166 0.582 14.135 2.776 2.775 2.066 4.713 3.22 7.229 4.002 8.399 2.775 20.246 4.41 19.787 11.969-0.522 9.043-4.832 12.765-12.328 15.039-5.952 1.815-17.139 9.584-25.473 10.501-4.776 0.574-8.513 0.538-11.49-0.445-2.79-0.976-7.085-6.34-11.804-10.162-4.662-3.816-9.632-6.168-8.213-11.189 0.896-3.623 3.092-6.984 8.213-11.454 2.66-2.281 6.604-7.838 10.147-10.104 2.942-1.844 6.441-0.547 9.797-0.933z"/>
- <path fill="#f9c600" d="m167.039 80.63c4.683-0.577 11.095 0.577 14.045 2.758 2.758 2.052 4.683 3.203 7.184 3.976 8.341 2.757 20.157 4.403 19.706 11.91-0.518 8.981-4.901 12.659-12.346 14.911-5.906 1.799-17.044 9.347-25.32 10.315-4.809 0.606-8.431 0.556-11.384-0.413-2.765-0.966-7.048-6.324-11.732-10.114-4.625-3.788-9.594-6.016-8.088-10.98 0.958-3.467 3.043-6.9 8.12-11.333 2.637-2.256 6.488-7.87 10.013-10.15 2.902-1.844 6.468-0.495 9.802-0.88z"/>
- </g>
- <path fill="#fc0" d="m154.744 90.7245c4.65-0.573 11.022 0.574 13.954 2.74 2.739 2.039 4.651 3.186 7.136 3.951 8.284 2.739 20.071 4.396 19.626 11.851-0.51 8.919-4.97 12.551-12.362 14.781-5.861 1.784-16.947 9.112-25.168 10.131-4.842 0.638-8.347 0.574-11.277-0.382-2.74-0.956-7.01-6.308-11.66-10.067-4.588-3.76-9.559-5.862-7.965-10.769 1.02-3.313 2.995-6.816 8.028-11.213 2.612-2.23 6.371-7.901 9.876-10.195 2.867-1.847 6.499-0.447 9.812-0.828z"/>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fc0" d="m167.982 83.609c1.008 2.088 3.6 2.376 5.328 3.312 1.655 0.936 2.592 1.152 3.239 0.792 1.44-0.792 0.36-3.384-1.079-4.32-1.368-0.935-8.064-1.151-7.488 0.216z"/>
- <path fill="#f9c600" d="m168.125 83.631c0.982 2.035 3.508 2.316 5.193 3.229 1.614 0.912 2.526 1.123 3.158 0.771 1.402-0.771 0.35-3.298-1.054-4.21-1.332-0.913-7.859-1.123-7.297 0.21z"/>
- <path fill="#f4c000" d="m168.267 83.653c0.957 1.982 3.418 2.255 5.058 3.144 1.572 0.889 2.461 1.094 3.076 0.752 1.367-0.752 0.342-3.213-1.025-4.101-1.299-0.889-7.656-1.094-7.109 0.205z"/>
- <path fill="#efba00" d="m168.409 83.674c0.932 1.929 3.327 2.195 4.924 3.06 1.53 0.865 2.395 1.064 2.993 0.732 1.331-0.732 0.333-3.127-0.998-3.992-1.264-0.864-7.451-1.064-6.919 0.2z"/>
- <path fill="#eab500" d="m168.552 83.696c0.905 1.876 3.234 2.135 4.787 2.977 1.488 0.841 2.329 1.035 2.912 0.711 1.294-0.711 0.323-3.041-0.971-3.882-1.228-0.841-7.246-1.036-6.728 0.194z"/>
- <path fill="#e5af00" d="m168.694 83.718c0.881 1.823 3.144 2.075 4.653 2.892 1.446 0.818 2.264 1.006 2.83 0.692 1.257-0.692 0.313-2.956-0.943-3.773-1.195-0.818-7.043-1.007-6.54 0.189z"/>
- <path fill="#e0a900" d="m168.837 83.739c0.855 1.771 3.053 2.015 4.519 2.809 1.403 0.793 2.198 0.977 2.747 0.671 1.221-0.671 0.306-2.87-0.916-3.664-1.161-0.793-6.839-0.976-6.35 0.184z"/>
- <path fill="#dba300" d="m168.979 83.761c0.829 1.718 2.962 1.955 4.383 2.725 1.363 0.77 2.132 0.948 2.666 0.651 1.184-0.651 0.296-2.784-0.889-3.554-1.125-0.77-6.634-0.948-6.16 0.178z"/>
- <path fill="#d69e00" d="m169.121 83.782c0.804 1.665 2.871 1.895 4.249 2.641 1.32 0.747 2.066 0.918 2.583 0.631 1.148-0.631 0.287-2.698-0.861-3.444-1.091-0.746-6.43-0.919-5.971 0.172z"/>
- <path fill="#d19800" d="m169.264 83.804c0.777 1.612 2.778 1.834 4.112 2.557 1.279 0.723 2.001 0.889 2.501 0.611 1.112-0.611 0.278-2.612-0.834-3.335-1.055-0.722-6.224-0.889-5.779 0.167z"/>
- <path fill="#cc9200" d="m169.406 83.826c0.753 1.559 2.688 1.774 3.979 2.473 1.236 0.699 1.936 0.86 2.42 0.591 1.074-0.591 0.269-2.527-0.808-3.226-1.021-0.699-6.021-0.86-5.591 0.162z"/>
- <path fill="#c68c00" d="m169.549 83.847c0.728 1.506 2.597 1.714 3.844 2.389 1.194 0.675 1.869 0.831 2.337 0.571 1.039-0.571 0.26-2.441-0.779-3.116-0.988-0.675-5.818-0.831-5.402 0.156z"/>
- <path fill="#c18700" d="m169.691 83.869c0.702 1.453 2.506 1.654 3.709 2.305 1.152 0.652 1.803 0.802 2.254 0.551 1.002-0.551 0.251-2.355-0.751-3.006-0.953-0.652-5.613-0.802-5.212 0.15z"/>
- <path fill="#bc8100" d="m169.833 83.89c0.677 1.4 2.415 1.594 3.574 2.221 1.111 0.628 1.738 0.772 2.173 0.531 0.965-0.531 0.241-2.27-0.725-2.897-0.917-0.627-5.408-0.772-5.022 0.145z"/>
- <path fill="#b77b00" d="m169.976 83.912c0.65 1.347 2.322 1.533 3.438 2.137 1.069 0.604 1.673 0.743 2.091 0.511 0.93-0.511 0.233-2.184-0.696-2.788-0.884-0.603-5.205-0.743-4.833 0.14z"/>
- <path fill="#b27500" d="m170.118 83.934c0.626 1.294 2.232 1.473 3.304 2.053 1.027 0.581 1.606 0.714 2.009 0.491 0.893-0.491 0.224-2.098-0.669-2.678-0.85-0.58-5.001-0.715-4.644 0.134z"/>
- <path fill="#ad7000" d="m170.261 83.955c0.6 1.242 2.14 1.413 3.168 1.97 0.984 0.557 1.541 0.685 1.927 0.47 0.855-0.47 0.214-2.012-0.644-2.569-0.812-0.555-4.794-0.684-4.451 0.129z"/>
- <path fill="#a86a00" d="m170.403 83.977c0.574 1.189 2.05 1.353 3.034 1.886 0.942 0.533 1.475 0.656 1.844 0.45 0.82-0.45 0.205-1.926-0.615-2.459-0.779-0.533-4.591-0.656-4.263 0.123z"/>
- <path fill="#a36400" d="m170.545 83.998c0.55 1.136 1.959 1.292 2.899 1.802 0.901 0.509 1.41 0.626 1.762 0.43 0.783-0.43 0.197-1.841-0.587-2.35-0.745-0.508-4.387-0.626-4.074 0.118z"/>
- <path fill="#9e5e00" d="m170.688 84.02c0.522 1.083 1.867 1.232 2.764 1.718 0.859 0.486 1.343 0.597 1.68 0.41 0.746-0.41 0.188-1.755-0.561-2.241-0.709-0.484-4.182-0.597-3.883 0.113z"/>
- <path fill="#995900" d="m170.83 84.042c0.498 1.03 1.776 1.172 2.629 1.634 0.817 0.462 1.278 0.568 1.599 0.39 0.71-0.39 0.178-1.669-0.533-2.131-0.676-0.461-3.979-0.568-3.695 0.107z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fc0" d="m152.875 86.29c-0.325 0.813 1.952 2.359 3.091 1.301 1.222-1.057 2.686-2.033 3.175-2.359 2.195-1.465 1.383-2.522-2.278-1.871-3.663 0.651-3.663 2.115-3.988 2.929z"/>
- <path fill="#f9c600" d="m152.934 86.279c-0.318 0.794 1.906 2.304 3.019 1.271 1.193-1.033 2.623-1.986 3.102-2.305 2.145-1.431 1.351-2.463-2.226-1.828-3.578 0.637-3.578 2.067-3.895 2.862z"/>
- <path fill="#f4c000" d="m152.993 86.269c-0.31 0.775 1.861 2.25 2.948 1.241 1.164-1.008 2.56-1.939 3.026-2.25 2.095-1.397 1.319-2.405-2.173-1.784-3.491 0.62-3.491 2.017-3.801 2.793z"/>
- <path fill="#efba00" d="m153.051 86.258c-0.302 0.757 1.817 2.195 2.878 1.211 1.136-0.984 2.497-1.892 2.952-2.195 2.044-1.363 1.287-2.347-2.118-1.741-3.409 0.606-3.409 1.968-3.712 2.725z"/>
- <path fill="#eab500" d="m153.11 86.248c-0.295 0.738 1.771 2.141 2.805 1.181 1.108-0.959 2.437-1.845 2.88-2.141 1.993-1.329 1.255-2.289-2.066-1.698-3.324 0.591-3.324 1.92-3.619 2.658z"/>
- <path fill="#e5af00" d="m153.169 86.238c-0.287 0.719 1.727 2.086 2.733 1.151 1.08-0.935 2.374-1.798 2.807-2.086 1.942-1.296 1.224-2.23-2.015-1.655s-3.238 1.87-3.525 2.59z"/>
- <path fill="#e0a900" d="m153.228 86.228c-0.28 0.7 1.681 2.032 2.661 1.121 1.052-0.91 2.312-1.751 2.732-2.031 1.893-1.262 1.191-2.172-1.961-1.611-3.152 0.559-3.152 1.82-3.432 2.521z"/>
- <path fill="#dba300" d="m153.286 86.217c-0.271 0.681 1.636 1.977 2.591 1.09 1.023-0.886 2.25-1.704 2.659-1.977 1.84-1.228 1.159-2.114-1.909-1.568-3.068 0.547-3.068 1.773-3.341 2.455z"/>
- <path fill="#d69e00" d="m153.345 86.207c-0.265 0.662 1.591 1.922 2.519 1.061 0.995-0.862 2.188-1.657 2.586-1.922 1.789-1.194 1.127-2.055-1.855-1.525-2.985 0.53-2.985 1.723-3.25 2.386z"/>
- <path fill="#d19800" d="m153.404 86.197c-0.257 0.643 1.546 1.868 2.447 1.03 0.967-0.837 2.126-1.61 2.512-1.868 1.739-1.16 1.095-1.997-1.803-1.481-2.899 0.516-2.899 1.674-3.156 2.319z"/>
- <path fill="#cc9200" d="m153.463 86.187c-0.25 0.625 1.5 1.813 2.375 1 0.939-0.813 2.064-1.563 2.439-1.813 1.688-1.126 1.063-1.938-1.75-1.438-2.814 0.5-2.814 1.625-3.064 2.251z"/>
- <path fill="#c68c00" d="m153.521 86.176c-0.242 0.605 1.456 1.758 2.304 0.97 0.911-0.788 2.002-1.516 2.366-1.758 1.637-1.092 1.031-1.88-1.698-1.395-2.729 0.486-2.729 1.576-2.972 2.183z"/>
- <path fill="#c18700" d="m153.58 86.166c-0.233 0.587 1.41 1.704 2.233 0.939 0.882-0.763 1.938-1.469 2.292-1.704 1.586-1.058 0.999-1.822-1.646-1.352-2.644 0.472-2.644 1.529-2.879 2.117z"/>
- <path fill="#bc8100" d="m153.639 86.156c-0.228 0.568 1.364 1.649 2.16 0.91 0.854-0.739 1.878-1.422 2.219-1.649 1.536-1.024 0.967-1.764-1.593-1.308s-2.559 1.477-2.786 2.047z"/>
- <path fill="#b77b00" d="m153.698 86.146c-0.22 0.549 1.32 1.594 2.089 0.879 0.825-0.715 1.815-1.375 2.146-1.595 1.484-0.99 0.935-1.705-1.54-1.265s-2.475 1.43-2.695 1.981z"/>
- <path fill="#b27500" d="m153.756 86.135c-0.211 0.53 1.275 1.54 2.019 0.85 0.797-0.69 1.753-1.328 2.072-1.54 1.434-0.957 0.902-1.646-1.487-1.221s-2.391 1.38-2.604 1.911z"/>
- <path fill="#ad7000" d="m153.815 86.125c-0.204 0.512 1.229 1.486 1.946 0.82 0.769-0.666 1.69-1.281 1.997-1.486 1.385-0.922 0.871-1.588-1.434-1.178s-2.304 1.331-2.509 1.844z"/>
- <path fill="#a86a00" d="m153.874 86.114c-0.196 0.493 1.185 1.431 1.875 0.79 0.74-0.642 1.628-1.234 1.924-1.431 1.332-0.889 0.84-1.53-1.381-1.135s-2.221 1.283-2.418 1.776z"/>
- <path fill="#a36400" d="m153.933 86.104c-0.189 0.474 1.139 1.376 1.803 0.759 0.712-0.617 1.566-1.187 1.851-1.376 1.281-0.855 0.808-1.472-1.329-1.092-2.135 0.38-2.135 1.234-2.325 1.709z"/>
- <path fill="#9e5e00" d="m153.991 86.094c-0.181 0.455 1.095 1.322 1.732 0.729 0.684-0.592 1.504-1.14 1.776-1.321 1.231-0.821 0.775-1.414-1.274-1.048-2.051 0.364-2.051 1.184-2.234 1.64z"/>
- <path fill="#995900" d="m154.05 86.083c-0.174 0.436 1.05 1.267 1.66 0.699 0.656-0.568 1.442-1.093 1.704-1.267 1.181-0.787 0.743-1.355-1.223-1.005s-1.966 1.136-2.141 1.573z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fc0" d="m156.951 107.887c-0.229 2.858 6.343-4.286 6.743-4.915 0.856-1.543 3.715-5.886 4.172-7.715 0.857-3.2 2.401-5.543 1.429-8.915-0.343-1.086-2.742-1.372-3.829-0.687-3.086 1.829-2.629 4.058-2.972 6.115-1.143 5.831-5.143 11.717-5.543 16.117z"/>
- <path fill="#ffcc02" d="m157.22 107.441c-0.22 2.787 6.178-4.188 6.566-4.802 0.833-1.506 3.614-5.745 4.056-7.529 0.831-3.122 2.333-5.408 1.382-8.695-0.337-1.058-2.678-1.333-3.735-0.663-3.006 1.788-2.557 3.96-2.889 5.967-1.105 5.685-4.997 11.431-5.38 15.722z"/>
- <path fill="#ffcc05" d="m157.488 106.995c-0.209 2.715 6.014-4.091 6.392-4.69 0.811-1.469 3.513-5.603 3.941-7.342 0.804-3.043 2.264-5.273 1.331-8.474-0.329-1.031-2.61-1.295-3.64-0.64-2.927 1.747-2.486 3.863-2.806 5.818-1.068 5.541-4.851 11.146-5.218 15.328z"/>
- <path fill="#ffcc07" d="m157.757 106.548c-0.198 2.645 5.85-3.993 6.217-4.577 0.785-1.431 3.409-5.461 3.824-7.156 0.779-2.964 2.196-5.138 1.282-8.253-0.322-1.003-2.543-1.257-3.545-0.618-2.847 1.706-2.414 3.766-2.722 5.67-1.031 5.398-4.706 10.862-5.056 14.934z"/>
- <path fill="#ffcd0a" d="m158.026 106.102c-0.189 2.573 5.684-3.896 6.04-4.465 0.762-1.394 3.309-5.32 3.709-6.969 0.753-2.886 2.129-5.004 1.233-8.033-0.315-0.976-2.478-1.219-3.45-0.595-2.768 1.665-2.343 3.668-2.64 5.522-0.993 5.254-4.558 10.577-4.892 14.54z"/>
- <path fill="#ffcd0c" d="m158.294 105.655c-0.179 2.503 5.52-3.798 5.865-4.351 0.738-1.357 3.207-5.179 3.594-6.783 0.727-2.807 2.061-4.869 1.185-7.813-0.309-0.948-2.411-1.18-3.356-0.572-2.687 1.623-2.271 3.571-2.556 5.374-0.958 5.11-4.414 10.291-4.732 14.145z"/>
- <path fill="#ffcd0f" d="m158.563 105.209c-0.169 2.431 5.354-3.701 5.688-4.239 0.715-1.319 3.106-5.037 3.479-6.596 0.7-2.728 1.992-4.734 1.135-7.592-0.301-0.92-2.344-1.142-3.261-0.549-2.608 1.583-2.199 3.474-2.473 5.226-0.919 4.965-4.267 10.005-4.568 13.75z"/>
- <path fill="#ffcd11" d="m158.831 104.762c-0.159 2.361 5.19-3.602 5.515-4.126 0.69-1.282 3.004-4.896 3.361-6.409 0.674-2.649 1.924-4.599 1.087-7.372-0.295-0.893-2.277-1.104-3.167-0.526-2.527 1.541-2.128 3.376-2.389 5.077-0.883 4.822-4.122 9.721-4.407 13.356z"/>
- <path fill="#ffce14" d="m159.1 104.316c-0.149 2.289 5.024-3.505 5.338-4.014 0.667-1.244 2.901-4.754 3.247-6.223 0.646-2.571 1.854-4.464 1.037-7.151-0.287-0.865-2.211-1.065-3.072-0.504-2.448 1.5-2.056 3.279-2.306 4.929-0.845 4.679-3.976 9.437-4.244 12.963z"/>
- <path fill="#ffce16" d="m159.369 103.869c-0.139 2.219 4.86-3.407 5.162-3.9 0.643-1.208 2.801-4.613 3.131-6.037 0.622-2.492 1.787-4.329 0.988-6.93-0.28-0.838-2.146-1.027-2.978-0.481-2.368 1.459-1.983 3.182-2.223 4.781-0.807 4.533-3.829 9.151-4.08 12.567z"/>
- <path fill="#ffce19" d="m159.637 103.423c-0.13 2.147 4.695-3.31 4.986-3.788 0.62-1.17 2.699-4.471 3.016-5.85 0.596-2.414 1.719-4.195 0.939-6.71-0.273-0.81-2.079-0.989-2.883-0.458-2.289 1.418-1.913 3.084-2.139 4.632-0.77 4.391-3.684 8.866-3.919 12.174z"/>
- <path fill="#ffce1c" d="m159.906 102.977c-0.119 2.076 4.531-3.213 4.811-3.676 0.597-1.133 2.599-4.33 2.899-5.664 0.57-2.335 1.651-4.06 0.891-6.49-0.267-0.782-2.012-0.95-2.787-0.435-2.21 1.377-1.842 2.987-2.057 4.484-0.734 4.247-3.539 8.582-3.757 11.781z"/>
- <path fill="#ffcf1e" d="m160.174 102.53c-0.108 2.005 4.366-3.115 4.637-3.563 0.571-1.096 2.496-4.189 2.784-5.478 0.543-2.256 1.581-3.925 0.841-6.269-0.26-0.754-1.945-0.912-2.693-0.412-2.129 1.336-1.77 2.889-1.973 4.336-0.697 4.103-3.394 8.297-3.596 11.386z"/>
- <path fill="#ffcf21" d="m160.443 102.084c-0.099 1.934 4.201-3.018 4.46-3.45 0.548-1.059 2.394-4.047 2.668-5.291 0.517-2.178 1.514-3.79 0.793-6.049-0.253-0.727-1.879-0.874-2.599-0.39-2.051 1.295-1.698 2.792-1.891 4.188-0.658 3.959-3.246 8.012-3.431 10.992z"/>
- <path fill="#ffcf23" d="m160.712 101.637c-0.089 1.863 4.036-2.919 4.283-3.337 0.526-1.021 2.294-3.905 2.553-5.104 0.491-2.099 1.447-3.655 0.744-5.828-0.246-0.699-1.813-0.835-2.505-0.367-1.969 1.253-1.625 2.694-1.805 4.04-0.623 3.814-3.101 7.726-3.27 10.596z"/>
- <path fill="#ffcf26" d="m160.98 101.191c-0.079 1.792 3.872-2.822 4.107-3.225 0.502-0.984 2.192-3.764 2.438-4.918 0.464-2.02 1.378-3.52 0.694-5.607-0.238-0.672-1.746-0.797-2.41-0.344-1.89 1.212-1.555 2.597-1.723 3.891-0.583 3.671-2.953 7.442-3.106 10.203z"/>
- <path fill="#ffd028" d="m161.249 100.744c-0.068 1.721 3.707-2.724 3.933-3.112 0.478-0.947 2.091-3.623 2.321-4.731 0.439-1.942 1.311-3.386 0.646-5.387-0.232-0.645-1.68-0.758-2.316-0.321-1.81 1.171-1.481 2.5-1.639 3.743-0.548 3.527-2.809 7.156-2.945 9.808z"/>
- <path fill="#ffd02b" d="m161.517 100.298c-0.06 1.65 3.543-2.627 3.757-2.999 0.454-0.91 1.989-3.481 2.206-4.545 0.413-1.863 1.242-3.25 0.597-5.167-0.225-0.617-1.613-0.72-2.221-0.298-1.73 1.13-1.411 2.402-1.557 3.595-0.509 3.383-2.662 6.871-2.782 9.414z"/>
- <path fill="#ffd02d" d="m161.786 99.852c-0.049 1.579 3.377-2.529 3.581-2.887 0.431-0.872 1.887-3.34 2.091-4.359 0.387-1.784 1.173-3.116 0.547-4.946-0.217-0.589-1.546-0.682-2.126-0.275-1.649 1.089-1.339 2.305-1.472 3.446-0.474 3.24-2.518 6.587-2.621 9.021z"/>
- <path fill="#ffd030" d="m162.055 99.405c-0.039 1.508 3.212-2.432 3.404-2.773 0.407-0.835 1.786-3.199 1.976-4.172 0.359-1.706 1.104-2.981 0.499-4.726-0.211-0.562-1.481-0.644-2.032-0.253-1.571 1.048-1.268 2.208-1.389 3.298-0.436 3.096-2.372 6.302-2.458 8.626z"/>
- <path fill="#ffd133" d="m162.323 98.958c-0.029 1.437 3.048-2.334 3.23-2.661 0.383-0.798 1.684-3.057 1.858-3.986 0.334-1.627 1.037-2.846 0.45-4.505-0.204-0.534-1.414-0.605-1.938-0.23-1.49 1.007-1.195 2.11-1.306 3.15-0.397 2.953-2.224 6.018-2.294 8.232z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fc0" d="m179.646 95.994c-3.168 3.456-5.4 6.767-7.2 9-1.872 2.304-6.48 5.04-4.176 7.704 1.943 2.376 9.936-1.944 16.128-6.552 6.12-4.608 15.696-8.711 11.016-13.967-2.448-2.664-8.208-2.088-10.439-0.648-1.729 1.078-2.737 1.655-5.329 4.463z"/>
- <path fill="#ffcc02" d="m179.782 96.147c-3.118 3.378-5.313 6.628-7.086 8.809-1.841 2.249-6.375 4.945-4.13 7.534 1.893 2.31 9.724-1.943 15.795-6.469 6.001-4.525 15.38-8.574 10.82-13.682-2.387-2.588-8.022-1.998-10.209-0.584-1.692 1.062-2.665 1.67-5.19 4.392z"/>
- <path fill="#ffcc05" d="m179.919 96.3c-3.068 3.3-5.227 6.488-6.973 8.619-1.81 2.193-6.271 4.85-4.085 7.364 1.843 2.243 9.513-1.943 15.463-6.386 5.882-4.442 15.064-8.437 10.623-13.396-2.323-2.513-7.835-1.907-9.978-0.52-1.655 1.044-2.593 1.684-5.05 4.319z"/>
- <path fill="#ffcc07" d="m180.055 96.454c-3.02 3.222-5.14 6.347-6.859 8.428-1.78 2.138-6.166 4.754-4.04 7.194 1.793 2.177 9.302-1.942 15.131-6.303 5.762-4.359 14.748-8.299 10.427-13.11-2.261-2.437-7.648-1.817-9.747-0.456-1.619 1.025-2.522 1.698-4.912 4.247z"/>
- <path fill="#ffcd0a" d="m180.191 96.607c-2.97 3.143-5.052 6.207-6.745 8.237-1.749 2.082-6.063 4.659-3.994 7.023 1.743 2.111 9.09-1.941 14.798-6.219 5.644-4.276 14.433-8.162 10.231-12.824-2.199-2.361-7.463-1.727-9.518-0.392-1.581 1.008-2.45 1.713-4.772 4.175z"/>
- <path fill="#ffcd0c" d="m180.327 96.761c-2.92 3.065-4.965 6.066-6.631 8.047-1.718 2.027-5.957 4.564-3.949 6.853 1.693 2.044 8.878-1.94 14.466-6.136 5.524-4.194 14.116-8.024 10.034-12.538-2.137-2.286-7.275-1.636-9.285-0.328-1.546 0.988-2.38 1.726-4.635 4.102z"/>
- <path fill="#ffcd0f" d="m180.464 96.914c-2.871 2.987-4.879 5.926-6.518 7.857-1.688 1.971-5.854 4.468-3.903 6.683 1.643 1.978 8.666-1.94 14.133-6.053 5.404-4.111 13.801-7.887 9.839-12.251-2.075-2.21-7.091-1.546-9.056-0.264-1.509 0.969-2.308 1.738-4.495 4.028z"/>
- <path fill="#ffcd11" d="m180.6 97.067c-2.821 2.909-4.792 5.786-6.404 7.667-1.657 1.916-5.748 4.373-3.858 6.512 1.593 1.912 8.455-1.938 13.802-5.969 5.284-4.028 13.484-7.75 9.641-11.966-2.012-2.134-6.902-1.456-8.823-0.199-1.474 0.951-2.238 1.752-4.358 3.955z"/>
- <path fill="#ffce14" d="m180.736 97.221c-2.771 2.83-4.705 5.645-6.29 7.476-1.626 1.86-5.644 4.278-3.813 6.342 1.542 1.845 8.244-1.938 13.47-5.886 5.166-3.945 13.169-7.612 9.444-11.68-1.949-2.059-6.716-1.365-8.592-0.135-1.437 0.933-2.166 1.766-4.219 3.883z"/>
- <path fill="#ffce16" d="m180.872 97.375c-2.722 2.752-4.617 5.504-6.176 7.286-1.595 1.805-5.539 4.182-3.767 6.172 1.49 1.779 8.031-1.937 13.136-5.803 5.046-3.862 12.853-7.475 9.249-11.394-1.889-1.983-6.53-1.274-8.362-0.071-1.4 0.914-2.095 1.779-4.08 3.81z"/>
- <path fill="#ffce19" d="m181.009 97.528c-2.673 2.674-4.53 5.364-6.063 7.095-1.564 1.749-5.435 4.087-3.722 6.001 1.44 1.713 7.82-1.936 12.804-5.719 4.927-3.78 12.537-7.338 9.052-11.108-1.825-1.907-6.343-1.185-8.13-0.007-1.364 0.896-2.024 1.793-3.941 3.738z"/>
- <path fill="#ffce1c" d="m181.145 97.682c-2.623 2.595-4.444 5.225-5.949 6.904-1.534 1.693-5.33 3.992-3.676 5.831 1.39 1.646 7.608-1.935 12.471-5.636 4.808-3.697 12.221-7.2 8.856-10.822-1.764-1.832-6.157-1.094-7.9 0.057-1.327 0.878-1.952 1.807-3.802 3.666z"/>
- <path fill="#ffcf1e" d="m181.281 97.835c-2.573 2.517-4.357 5.084-5.835 6.714-1.503 1.638-5.226 3.896-3.631 5.661 1.34 1.58 7.396-1.935 12.139-5.553 4.689-3.614 11.905-7.063 8.659-10.536-1.701-1.756-5.97-1.004-7.668 0.121-1.291 0.86-1.881 1.821-3.664 3.593z"/>
- <path fill="#ffcf21" d="m181.417 97.988c-2.522 2.439-4.27 4.944-5.721 6.524-1.472 1.582-5.121 3.801-3.586 5.491 1.29 1.513 7.186-1.934 11.807-5.47 4.569-3.531 11.589-6.926 8.463-10.25-1.639-1.68-5.783-0.914-7.438 0.186-1.254 0.84-1.809 1.834-3.525 3.519z"/>
- <path fill="#ffcf23" d="m181.554 98.142c-2.476 2.361-4.185 4.803-5.608 6.333-1.441 1.527-5.017 3.706-3.54 5.32 1.24 1.447 6.974-1.933 11.474-5.386 4.45-3.448 11.273-6.788 8.268-9.964-1.577-1.605-5.599-0.823-7.207 0.25-1.22 0.822-1.74 1.848-3.387 3.447z"/>
- <path fill="#ffcf26" d="m181.69 98.295c-2.425 2.283-4.098 4.663-5.494 6.143-1.411 1.471-4.912 3.61-3.495 5.15 1.19 1.381 6.763-1.932 11.142-5.303 4.331-3.366 10.957-6.65 8.07-9.679-1.514-1.529-5.411-0.732-6.976 0.313-1.182 0.805-1.667 1.863-3.247 3.376z"/>
- <path fill="#ffd028" d="m181.826 98.449c-2.375 2.204-4.009 4.522-5.38 5.952-1.38 1.416-4.808 3.515-3.449 4.98 1.14 1.314 6.551-1.932 10.81-5.22 4.211-3.283 10.641-6.513 7.874-9.393-1.452-1.454-5.226-0.642-6.745 0.378-1.147 0.786-1.597 1.876-3.11 3.303z"/>
- <path fill="#ffd02b" d="m181.962 98.602c-2.324 2.127-3.922 4.382-5.266 5.762-1.349 1.36-4.703 3.42-3.404 4.809 1.089 1.248 6.34-1.93 10.478-5.136 4.092-3.2 10.325-6.376 7.677-9.106-1.389-1.378-5.038-0.552-6.513 0.441-1.111 0.768-1.526 1.89-2.972 3.23z"/>
- <path fill="#ffd02d" d="m182.099 98.756c-2.276 2.048-3.836 4.241-5.153 5.571-1.318 1.305-4.599 3.324-3.359 4.639 1.039 1.182 6.128-1.93 10.146-5.053 3.973-3.117 10.009-6.238 7.48-8.82-1.328-1.303-4.852-0.462-6.282 0.506-1.074 0.748-1.454 1.903-2.832 3.157z"/>
- <path fill="#ffd030" d="m182.235 98.909c-2.228 1.97-3.749 4.101-5.039 5.381-1.288 1.249-4.494 3.229-3.313 4.469 0.988 1.115 5.916-1.929 9.813-4.97 3.853-3.034 9.693-6.101 7.285-8.535-1.267-1.227-4.666-0.371-6.052 0.57-1.038 0.731-1.384 1.918-2.694 3.085z"/>
- <path fill="#ffd133" d="m182.371 99.063c-2.177 1.892-3.662 3.96-4.925 5.19-1.257 1.193-4.39 3.133-3.268 4.298 0.938 1.049 5.704-1.928 9.479-4.886 3.734-2.952 9.377-5.963 7.088-8.249-1.203-1.151-4.479-0.281-5.821 0.634-0.999 0.713-1.31 1.931-2.553 3.013z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fff" d="m186.414 168.569c0.864-2.808 28.872-9.432 33.48-7.272 4.536 2.16 26.279 33.768 22.392 35.496-3.888 1.657-12.24-10.512-24.408-16.128s-32.328-9.216-31.464-12.096z"/>
- <path fill="#f9f9f9" d="m187.239 168.626c0.848-2.761 28.145-9.076 32.69-6.997 4.476 2.079 25.768 32.897 21.943 34.591-3.824 1.625-11.965-10.346-23.94-15.874-11.976-5.527-31.541-8.89-30.693-11.72z"/>
- <path fill="#f4f4f4" d="m188.063 168.683c0.832-2.714 27.418-8.72 31.899-6.722 4.417 1.998 25.259 32.026 21.497 33.685-3.76 1.595-11.689-10.18-23.474-15.619-11.782-5.438-30.754-8.565-29.922-11.344z"/>
- <path fill="#efefef" d="m188.888 168.74c0.814-2.668 26.69-8.364 31.109-6.447 4.357 1.917 24.746 31.155 21.049 32.779-3.695 1.563-11.416-10.014-23.007-15.364-11.59-5.349-29.967-8.239-29.151-10.968z"/>
- <path fill="#eaeaea" d="m189.712 168.797c0.801-2.621 25.964-8.009 30.32-6.173 4.299 1.837 24.235 30.285 20.603 31.874-3.633 1.532-11.142-9.847-22.54-15.109-11.4-5.261-29.182-7.914-28.383-10.592z"/>
- <path fill="#e5e5e5" d="m190.537 168.853c0.783-2.573 25.236-7.652 29.53-5.897 4.239 1.756 23.723 29.414 20.155 30.968-3.569 1.501-10.867-9.681-22.074-14.854-11.206-5.172-28.395-7.589-27.611-10.217z"/>
- <path fill="#e0e0e0" d="m191.361 168.91c0.768-2.527 24.51-7.296 28.74-5.622 4.18 1.675 23.212 28.543 19.708 30.063-3.505 1.469-10.593-9.516-21.607-14.6-11.014-5.083-27.608-7.263-26.841-9.841z"/>
- <path fill="#dbdbdb" d="m192.186 168.967c0.751-2.48 23.781-6.941 27.95-5.347 4.119 1.593 22.7 27.671 19.26 29.157-3.441 1.438-10.318-9.349-21.141-14.345-10.821-4.994-26.821-6.938-26.069-9.465z"/>
- <path fill="#d6d6d6" d="m193.01 169.024c0.735-2.433 23.057-6.585 27.16-5.073 4.062 1.513 22.19 26.801 18.813 28.252-3.377 1.407-10.043-9.183-20.673-14.09-10.629-4.906-26.035-6.612-25.3-9.089z"/>
- <path fill="#d1d1d1" d="m193.835 169.081c0.72-2.387 22.328-6.229 26.37-4.798 4.001 1.432 21.678 25.93 18.365 27.346-3.313 1.376-9.768-9.017-20.206-13.835-10.437-4.817-25.248-6.287-24.529-8.713z"/>
- <path fill="#ccc" d="m194.659 169.137c0.703-2.339 21.603-5.873 25.58-4.521 3.942 1.351 21.167 25.059 17.918 26.44-3.249 1.345-9.493-8.851-19.739-13.58-10.245-4.729-24.462-5.963-23.759-8.339z"/>
- <path fill="#c6c6c6" d="m195.484 169.194c0.687-2.292 20.874-5.517 24.79-4.247 3.882 1.27 20.655 24.188 17.47 25.535-3.185 1.314-9.219-8.685-19.271-13.326-10.054-4.639-23.676-5.636-22.989-7.962z"/>
- <path fill="#c1c1c1" d="m196.308 169.251c0.671-2.246 20.147-5.161 24-3.973 3.822 1.19 20.145 23.318 17.022 24.63-3.121 1.283-8.943-8.519-18.805-13.071-9.859-4.551-22.888-5.311-22.217-7.586z"/>
- <path fill="#bcbcbc" d="m197.133 169.308c0.654-2.199 19.421-4.805 23.21-3.698 3.764 1.109 19.634 22.447 16.575 23.724-3.057 1.252-8.669-8.353-18.338-12.816-9.668-4.462-22.102-4.985-21.447-7.21z"/>
- <path fill="#b7b7b7" d="m197.957 169.365c0.64-2.152 18.693-4.45 22.42-3.423 3.705 1.027 19.122 21.575 16.129 22.818-2.993 1.221-8.395-8.186-17.872-12.561-9.476-4.373-21.315-4.66-20.677-6.834z"/>
- <path fill="#b2b2b2" d="m198.782 169.421c0.622-2.105 17.966-4.093 21.63-3.147 3.646 0.946 18.61 20.704 15.681 21.912-2.93 1.19-8.12-8.02-17.404-12.306-9.284-4.284-20.53-4.335-19.907-6.459z"/>
- <path fill="#adadad" d="m199.606 169.478c0.606-2.058 17.239-3.737 20.84-2.873 3.586 0.866 18.099 19.834 15.234 21.008-2.866 1.158-7.847-7.855-16.938-12.052-9.091-4.196-19.742-4.009-19.136-6.083z"/>
- <path fill="#a8a8a8" d="m200.431 169.535c0.59-2.011 16.512-3.382 20.05-2.598 3.525 0.785 17.588 18.963 14.786 20.102-2.803 1.127-7.571-7.688-16.472-11.797-8.898-4.107-18.955-3.684-18.364-5.707z"/>
- <path fill="#a3a3a3" d="m201.255 169.592c0.574-1.965 15.785-3.026 19.261-2.323 3.467 0.704 17.076 18.092 14.339 19.196-2.738 1.096-7.296-7.522-16.004-11.542-8.707-4.018-18.17-3.358-17.596-5.331z"/>
- <path fill="#9e9e9e" d="m202.08 169.649c0.559-1.918 15.059-2.67 18.47-2.048 3.407 0.623 16.565 17.221 13.892 18.29-2.674 1.065-7.022-7.356-15.537-11.287-8.515-3.929-17.383-3.033-16.825-4.955z"/>
- <path fill="#999" d="m202.904 169.705c0.542-1.871 14.331-2.314 17.68-1.773 3.349 0.542 16.055 16.35 13.444 17.385-2.61 1.034-6.747-7.19-15.07-11.032-8.322-3.841-16.596-2.708-16.054-4.58z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fff" d="m151.134 211.625c2.881 0.144 0.145 16.271 0.145 32.903s2.231 22.464 0.144 24.552-5.688-5.399-5.688-22.031c-0.001-16.632 2.519-35.568 5.399-35.424z"/>
- <path fill="#f9f9f9" d="m151.105 212.016c2.783 0.162 0.109 16.052 0.097 32.419-0.012 16.366 2.188 22.208 0.164 24.237-2.02 2.029-5.561-5.383-5.546-21.752 0.012-16.367 2.502-35.065 5.285-34.904z"/>
- <path fill="#f4f4f4" d="m151.075 212.407c2.687 0.18 0.076 15.832 0.051 31.934-0.023 16.102 2.143 21.951 0.185 23.924-1.953 1.968-5.435-5.367-5.405-21.473 0.024-16.103 2.484-34.564 5.169-34.385z"/>
- <path fill="#efefef" d="m151.046 212.797c2.588 0.197 0.041 15.613 0.004 31.449-0.036 15.836 2.098 21.694 0.204 23.609-1.886 1.907-5.308-5.352-5.263-21.195 0.037-15.835 2.467-34.058 5.055-33.863z"/>
- <path fill="#eaeaea" d="m151.017 213.189c2.49 0.214 0.007 15.392-0.043 30.962-0.05 15.571 2.052 21.439 0.224 23.297-1.818 1.848-5.181-5.334-5.122-20.916 0.049-15.571 2.45-33.557 4.941-33.343z"/>
- <path fill="#e5e5e5" d="m150.987 213.581c2.394 0.23-0.027 15.17-0.089 30.477s2.007 21.182 0.244 22.982c-1.751 1.787-5.055-5.32-4.98-20.638 0.061-15.305 2.431-33.053 4.825-32.821z"/>
- <path fill="#e0e0e0" d="m150.958 213.971c2.297 0.248-0.062 14.951-0.136 29.99-0.074 15.041 1.962 20.927 0.264 22.668-1.683 1.728-4.928-5.301-4.839-20.356 0.074-15.04 2.414-32.551 4.711-32.302z"/>
- <path fill="#dbdbdb" d="m150.928 214.362c2.199 0.266-0.096 14.73-0.182 29.506-0.087 14.775 1.915 20.67 0.282 22.354-1.615 1.667-4.8-5.286-4.696-20.078 0.087-14.776 2.397-32.048 4.596-31.782z"/>
- <path fill="#d6d6d6" d="m150.899 214.752c2.102 0.283-0.13 14.511-0.229 29.021-0.099 14.511 1.87 20.413 0.303 22.04-1.549 1.607-4.674-5.27-4.556-19.799 0.1-14.51 2.38-31.545 4.482-31.262z"/>
- <path fill="#d1d1d1" d="m150.87 215.144c2.005 0.301-0.165 14.29-0.274 28.535-0.112 14.245 1.824 20.155 0.321 21.725-1.479 1.548-4.547-5.252-4.413-19.519 0.11-14.245 2.361-31.043 4.366-30.741z"/>
- <path fill="#ccc" d="m150.84 215.536c1.908 0.317-0.197 14.069-0.32 28.049-0.124 13.979 1.779 19.899 0.342 21.412-1.413 1.486-4.42-5.238-4.272-19.242 0.122-13.979 2.343-30.54 4.25-30.219z"/>
- <path fill="#c6c6c6" d="m150.811 215.926c1.811 0.334-0.233 13.85-0.368 27.564-0.136 13.713 1.735 19.643 0.362 21.096-1.346 1.428-4.293-5.219-4.131-18.961 0.136-13.712 2.327-30.035 4.137-29.699z"/>
- <path fill="#c1c1c1" d="m150.781 216.317c1.714 0.354-0.267 13.629-0.414 27.078s1.69 19.387 0.382 20.783c-1.277 1.367-4.166-5.203-3.989-18.682 0.148-13.449 2.308-29.533 4.021-29.179z"/>
- <path fill="#bcbcbc" d="m150.752 216.708c1.616 0.371-0.301 13.41-0.461 26.594-0.161 13.184 1.646 19.13 0.402 20.469-1.211 1.307-4.04-5.188-3.847-18.402 0.16-13.185 2.29-29.033 3.906-28.661z"/>
- <path fill="#b7b7b7" d="m150.723 217.099c1.519 0.387-0.336 13.188-0.509 26.106-0.173 12.92 1.601 18.875 0.423 20.156-1.144 1.246-3.913-5.171-3.706-18.123 0.172-12.919 2.273-28.529 3.792-28.139z"/>
- <path fill="#b2b2b2" d="m150.693 217.491c1.422 0.404-0.37 12.969-0.554 25.621-0.186 12.653 1.555 18.617 0.441 19.842-1.076 1.187-3.786-5.156-3.563-17.846 0.184-12.652 2.255-28.024 3.676-27.617z"/>
- <path fill="#adadad" d="m150.664 217.881c1.325 0.422-0.404 12.748-0.601 25.136-0.198 12.388 1.51 18.36 0.462 19.528-1.008 1.125-3.66-5.139-3.423-17.566 0.197-12.389 2.238-27.521 3.562-27.098z"/>
- <path fill="#a8a8a8" d="m150.634 218.272c1.229 0.439-0.438 12.527-0.646 24.65-0.21 12.123 1.464 18.104 0.48 19.213-0.939 1.066-3.531-5.121-3.279-17.285 0.208-12.123 2.219-27.019 3.445-26.578z"/>
- <path fill="#a3a3a3" d="m150.605 218.663c1.13 0.457-0.474 12.309-0.694 24.166-0.222 11.857 1.419 17.848 0.501 18.899-0.873 1.006-3.405-5.106-3.139-17.009 0.222-11.855 2.202-26.515 3.332-26.056z"/>
- <path fill="#9e9e9e" d="m150.576 219.054c1.033 0.474-0.507 12.088-0.741 23.68-0.234 11.593 1.374 17.591 0.521 18.585-0.806 0.946-3.279-5.089-2.997-16.729 0.233-11.591 2.184-26.011 3.217-25.536z"/>
- <path fill="#999" d="m150.546 219.444c0.937 0.492-0.541 11.868-0.787 23.195-0.246 11.326 1.329 17.335 0.541 18.271-0.737 0.885-3.151-5.074-2.855-16.449 0.245-11.328 2.166-25.509 3.101-25.017z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fff" d="m157.434 167.161c1.735 0.192 12.437-2.218 12.822-1.254 0.386 0.772-6.651 2.893-8.966 5.303-0.771 0.771-2.796 2.603-4.049 2.41-0.964-0.096-1.543-2.121-2.989-3.664-3.471-3.47-5.688-3.181-5.013-4.531 0.579-1.06 5.207 1.446 8.195 1.736z"/>
- <path fill="#fbfbfb" d="m157.479 167.201c1.7 0.188 12.176-2.171 12.554-1.227 0.377 0.755-6.512 2.832-8.778 5.191-0.755 0.755-2.736 2.549-3.964 2.36-0.942-0.094-1.51-2.077-2.926-3.587-3.398-3.397-5.568-3.115-4.907-4.436 0.565-1.038 5.096 1.415 8.021 1.699z"/>
- <path fill="#f8f8f8" d="m157.525 167.241c1.663 0.184 11.914-2.124 12.283-1.201 0.369 0.739-6.372 2.771-8.589 5.08-0.738 0.739-2.679 2.494-3.879 2.309-0.924-0.092-1.479-2.032-2.863-3.51-3.325-3.324-5.449-3.048-4.803-4.341 0.555-1.015 4.988 1.385 7.851 1.663z"/>
- <path fill="#f5f5f5" d="m157.57 167.281c1.626 0.18 11.652-2.078 12.014-1.175 0.361 0.723-6.231 2.711-8.4 4.969-0.723 0.722-2.619 2.439-3.793 2.258-0.903-0.09-1.446-1.987-2.802-3.433-3.252-3.251-5.329-2.981-4.695-4.245 0.54-0.993 4.876 1.354 7.676 1.626z"/>
- <path fill="#f2f2f2" d="m157.615 167.321c1.59 0.176 11.391-2.031 11.745-1.148 0.352 0.706-6.093 2.649-8.212 4.856-0.707 0.707-2.562 2.385-3.709 2.208-0.883-0.088-1.413-1.943-2.738-3.356-3.179-3.178-5.209-2.914-4.591-4.15 0.529-0.971 4.768 1.324 7.505 1.59z"/>
- <path fill="#efefef" d="m157.66 167.361c1.554 0.172 11.13-1.985 11.475-1.122 0.346 0.69-5.952 2.589-8.022 4.745-0.69 0.69-2.503 2.33-3.624 2.157-0.863-0.086-1.381-1.898-2.675-3.279-3.106-3.105-5.09-2.847-4.486-4.055 0.517-0.948 4.658 1.294 7.332 1.554z"/>
- <path fill="#ebebeb" d="m157.705 167.401c1.518 0.168 10.868-1.938 11.206-1.096 0.336 0.674-5.813 2.528-7.835 4.634-0.674 0.674-2.444 2.275-3.539 2.106-0.842-0.084-1.348-1.853-2.612-3.202-3.032-3.032-4.97-2.78-4.38-3.959 0.505-0.926 4.549 1.263 7.16 1.517z"/>
- <path fill="#e8e8e8" d="m157.751 167.441c1.48 0.164 10.606-1.892 10.936-1.069 0.329 0.657-5.673 2.467-7.646 4.522-0.658 0.657-2.385 2.22-3.453 2.055-0.822-0.082-1.315-1.809-2.549-3.124-2.96-2.96-4.851-2.714-4.275-3.865 0.491-0.904 4.438 1.233 6.987 1.481z"/>
- <path fill="#e5e5e5" d="m157.796 167.481c1.444 0.16 10.346-1.845 10.666-1.043 0.32 0.641-5.532 2.406-7.458 4.41-0.641 0.642-2.325 2.166-3.367 2.005-0.803-0.08-1.284-1.764-2.486-3.047-2.887-2.887-4.732-2.647-4.17-3.769 0.48-0.882 4.329 1.202 6.815 1.444z"/>
- <path fill="#e2e2e2" d="m157.841 167.521c1.407 0.156 10.083-1.799 10.397-1.017 0.312 0.625-5.394 2.346-7.271 4.299-0.625 0.625-2.267 2.111-3.282 1.954-0.782-0.078-1.251-1.719-2.423-2.97-2.814-2.814-4.612-2.58-4.065-3.674 0.469-0.859 4.221 1.172 6.644 1.408z"/>
- <path fill="#dfdfdf" d="m157.886 167.56c1.37 0.152 9.821-1.751 10.127-0.99 0.304 0.609-5.254 2.285-7.081 4.188-0.609 0.609-2.208 2.056-3.198 1.903-0.761-0.076-1.218-1.675-2.36-2.893-2.741-2.741-4.492-2.513-3.959-3.579 0.456-0.837 4.111 1.142 6.471 1.371z"/>
- <path fill="#dbdbdb" d="m157.931 167.6c1.335 0.148 9.561-1.704 9.857-0.963 0.296 0.592-5.114 2.223-6.893 4.076-0.593 0.593-2.149 2.001-3.113 1.853-0.741-0.074-1.186-1.631-2.297-2.817-2.668-2.667-4.373-2.446-3.854-3.483 0.445-0.815 4.003 1.111 6.3 1.334z"/>
- <path fill="#d8d8d8" d="m157.977 167.64c1.298 0.144 9.299-1.658 9.587-0.937 0.288 0.576-4.974 2.163-6.704 3.964-0.576 0.577-2.091 1.947-3.027 1.803-0.721-0.072-1.153-1.586-2.234-2.74-2.596-2.594-4.253-2.379-3.748-3.388 0.431-0.792 3.891 1.081 6.126 1.298z"/>
- <path fill="#d5d5d5" d="m158.022 167.68c1.261 0.14 9.037-1.611 9.317-0.911 0.28 0.56-4.834 2.102-6.516 3.853-0.56 0.561-2.032 1.892-2.942 1.752-0.7-0.07-1.12-1.541-2.172-2.663-2.521-2.521-4.133-2.312-3.643-3.292 0.421-0.77 3.784 1.05 5.956 1.261z"/>
- <path fill="#d2d2d2" d="m158.067 167.72c1.225 0.136 8.775-1.564 9.049-0.884 0.271 0.543-4.695 2.041-6.327 3.741-0.545 0.544-1.974 1.837-2.857 1.701-0.682-0.068-1.09-1.497-2.109-2.585-2.449-2.449-4.014-2.246-3.538-3.198 0.407-0.748 3.673 1.02 5.782 1.225z"/>
- <path fill="#cfcfcf" d="m158.112 167.76c1.188 0.132 8.515-1.518 8.779-0.858 0.264 0.527-4.555 1.98-6.139 3.63-0.527 0.528-1.915 1.782-2.772 1.65-0.66-0.066-1.057-1.452-2.046-2.508-2.376-2.376-3.895-2.179-3.433-3.103 0.397-0.725 3.565 0.99 5.611 1.189z"/>
- <path fill="#ccc" d="m158.157 167.8c1.152 0.128 8.253-1.472 8.51-0.832 0.255 0.511-4.415 1.92-5.95 3.518-0.512 0.512-1.855 1.728-2.688 1.6-0.64-0.064-1.023-1.407-1.983-2.431-2.303-2.303-3.773-2.112-3.326-3.007 0.383-0.703 3.454 0.959 5.437 1.152z"/>
- <path fill="#c8c8c8" d="m158.203 167.84c1.115 0.124 7.991-1.425 8.239-0.805 0.248 0.494-4.274 1.858-5.761 3.406-0.496 0.496-1.798 1.673-2.603 1.549-0.62-0.063-0.992-1.363-1.921-2.354-2.229-2.229-3.655-2.045-3.221-2.912 0.372-0.681 3.346 0.929 5.267 1.116z"/>
- <path fill="#c5c5c5" d="m158.248 167.88c1.079 0.12 7.73-1.379 7.97-0.779 0.239 0.478-4.135 1.798-5.572 3.295-0.479 0.479-1.739 1.618-2.518 1.498-0.6-0.06-0.959-1.318-1.857-2.277-2.157-2.157-3.535-1.978-3.116-2.816 0.359-0.659 3.235 0.898 5.093 1.079z"/>
- <path fill="#c2c2c2" d="m158.293 167.92c1.042 0.116 7.469-1.332 7.701-0.753 0.231 0.462-3.995 1.737-5.385 3.184-0.463 0.463-1.68 1.563-2.432 1.447-0.579-0.058-0.927-1.273-1.796-2.2-2.084-2.084-3.415-1.911-3.01-2.721 0.348-0.636 3.127 0.868 4.922 1.043z"/>
- <path fill="#bfbfbf" d="m158.338 167.959c1.007 0.112 7.207-1.285 7.432-0.726 0.223 0.446-3.855 1.676-5.196 3.072-0.447 0.447-1.621 1.509-2.347 1.397-0.56-0.056-0.895-1.229-1.732-2.123-2.011-2.011-3.296-1.844-2.905-2.626 0.334-0.614 3.016 0.838 4.748 1.006z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m194.253 11.922c-1.222 2.631-3.812 23.214-0.248 20.892 3.594-2.341 13.57-5.312 19.886-7.013 7.003-1.886-17.188-19.463-19.638-13.879z"/>
- <path fill="#060606" d="m194.485 12.307c-1.21 2.594-3.704 22.255-0.234 20.007 3.491-2.262 13.077-5.1 19.039-6.782 6.59-1.905-16.436-18.609-18.805-13.225z"/>
- <path fill="#0c0c0c" d="m194.717 12.691c-1.198 2.557-3.595 21.296-0.221 19.124 3.391-2.184 12.586-4.888 18.194-6.551 6.177-1.924-15.684-17.757-17.973-12.573z"/>
- <path fill="#131313" d="m194.949 13.076c-1.187 2.52-3.487 20.337-0.207 18.239 3.288-2.105 12.093-4.676 17.348-6.321 5.763-1.941-14.933-16.903-17.141-11.918z"/>
- <path fill="#191919" d="m195.181 13.46c-1.177 2.483-3.379 19.378-0.193 17.355 3.187-2.027 11.6-4.464 16.502-6.09 5.349-1.959-14.182-16.05-16.309-11.265z"/>
- <path fill="#1f1f1f" d="m195.413 13.845c-1.164 2.446-3.27 18.419-0.18 16.471 3.086-1.949 11.107-4.252 15.657-5.859 4.935-1.978-13.43-15.198-15.477-10.612z"/>
- <path fill="#262626" d="m195.645 14.229c-1.153 2.409-3.162 17.46-0.166 15.586 2.983-1.87 10.616-4.04 14.811-5.628 4.521-1.995-12.679-14.344-14.645-9.958z"/>
- <path fill="#2c2c2c" d="m195.878 14.614c-1.142 2.372-3.055 16.501-0.152 14.702 2.882-1.792 10.123-3.828 13.965-5.398 4.107-2.013-11.929-13.49-13.813-9.304z"/>
- <path fill="#333" d="m196.11 14.999c-1.131 2.335-2.946 15.542-0.14 13.817 2.78-1.713 9.631-3.616 13.119-5.167 3.695-2.031-11.175-12.637-12.979-8.65z"/>
- <path fill="#393939" d="m196.342 15.383c-1.118 2.299-2.838 14.583-0.126 12.934 2.68-1.636 9.139-3.404 12.274-4.937 3.28-2.049-10.425-11.784-12.148-7.997z"/>
- <path fill="#3f3f3f" d="m196.574 15.768c-1.108 2.261-2.729 13.624-0.112 12.049 2.577-1.557 8.646-3.192 11.429-4.706 2.865-2.068-9.675-10.931-11.317-7.343z"/>
- <path fill="#464646" d="m196.806 16.152c-1.097 2.225-2.622 12.665-0.1 11.165 2.477-1.479 8.154-2.98 10.583-4.475 2.453-2.086-8.922-10.078-10.483-6.69z"/>
- <path fill="#4c4c4c" d="m197.038 16.537c-1.085 2.188-2.513 11.706-0.085 10.28 2.374-1.4 7.661-2.768 9.737-4.244 2.039-2.104-8.171-9.225-9.652-6.036z"/>
- <path fill="#525252" d="m197.27 16.921c-1.073 2.151-2.405 10.747-0.071 9.396 2.272-1.322 7.168-2.556 8.891-4.013 1.625-2.122-7.42-8.371-8.82-5.383z"/>
- <path fill="#595959" d="m197.502 17.306c-1.062 2.113-2.297 9.788-0.058 8.512 2.172-1.244 6.677-2.344 8.046-3.783 1.211-2.14-6.669-7.518-7.988-4.729z"/>
- <path fill="#5f5f5f" d="m197.734 17.69c-1.05 2.077-2.188 8.829-0.044 7.627 2.069-1.165 6.184-2.132 7.2-3.552 0.797-2.157-5.917-6.664-7.156-4.075z"/>
- <path fill="#666" d="m197.966 18.075c-1.038 2.04-2.079 7.87-0.029 6.743 1.968-1.087 5.69-1.92 6.354-3.321 0.382-2.176-5.167-5.812-6.325-3.422z"/>
- <path fill="#6c6c6c" d="m198.198 18.459c-1.027 2.003-1.972 6.911-0.017 5.859 1.866-1.008 5.198-1.708 5.509-3.09-0.03-2.194-4.415-4.959-5.492-2.769z"/>
- <path fill="#727272" d="m198.43 18.844c-1.017 1.966-1.863 5.952-0.003 4.975 1.765-0.93 4.706-1.496 4.662-2.86-0.443-2.212-3.662-4.106-4.659-2.115z"/>
- <path fill="#797979" d="m198.662 19.228c-1.004 1.929-1.755 4.993 0.011 4.09 1.663-0.852 4.215-1.284 3.817-2.629-0.858-2.23-2.912-3.251-3.828-1.461z"/>
- <path fill="#7f7f7f" d="m198.894 19.612c-0.993 1.892-1.647 4.034 0.023 3.206 1.563-0.773 3.723-1.072 2.973-2.398-1.272-2.248-2.161-2.399-2.996-0.808z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m143.502 46.386c-0.72 2.16 8.712 5.112 10.801 6.984 2.808 2.52 3.023 7.488 6.336 5.472 2.159-1.296 0.504-4.176-3.456-8.568-5.833-6.481-13.033-5.689-13.681-3.888z"/>
- <path fill="#050505" d="m143.991 46.582c-0.716 2.073 8.275 4.9 10.336 6.741 2.745 2.457 2.961 7.249 6.146 5.313 2.094-1.254 0.449-4.072-3.343-8.28-5.574-6.203-12.491-5.505-13.139-3.774z"/>
- <path fill="#0a0a0a" d="m144.479 46.779c-0.71 1.987 7.839 4.688 9.873 6.498 2.682 2.394 2.897 7.009 5.956 5.154 2.028-1.212 0.395-3.968-3.228-7.993-5.319-5.926-11.953-5.321-12.601-3.659z"/>
- <path fill="#0f0f0f" d="m144.967 46.976c-0.704 1.9 7.403 4.476 9.41 6.254 2.62 2.33 2.835 6.77 5.766 4.995 1.964-1.171 0.342-3.864-3.112-7.706-5.064-5.647-11.415-5.137-12.064-3.543z"/>
- <path fill="#141414" d="m145.456 47.172c-0.701 1.813 6.966 4.263 8.946 6.011 2.557 2.266 2.772 6.53 5.575 4.835 1.897-1.129 0.287-3.76-2.998-7.418-4.807-5.369-10.874-4.952-11.523-3.428z"/>
- <path fill="#191919" d="m145.944 47.369c-0.696 1.726 6.53 4.051 8.483 5.768 2.493 2.203 2.71 6.291 5.385 4.676 1.833-1.087 0.231-3.656-2.884-7.13-4.551-5.093-10.335-4.769-10.984-3.314z"/>
- <path fill="#1e1e1e" d="m146.433 47.565c-0.692 1.64 6.093 3.839 8.019 5.525 2.431 2.14 2.647 6.052 5.194 4.517 1.768-1.046 0.179-3.552-2.77-6.843-4.293-4.814-9.794-4.585-10.443-3.199z"/>
- <path fill="#232323" d="m146.921 47.762c-0.686 1.553 5.657 3.627 7.558 5.282 2.367 2.076 2.583 5.813 5.003 4.357 1.702-1.003 0.124-3.448-2.654-6.555-4.04-4.537-9.257-4.401-9.907-3.084z"/>
- <path fill="#282828" d="m147.409 47.959c-0.681 1.466 5.221 3.415 7.094 5.039 2.305 2.013 2.521 5.573 4.813 4.198 1.637-0.962 0.07-3.344-2.54-6.268-3.782-4.26-8.717-4.218-9.367-2.969z"/>
- <path fill="#2d2d2d" d="m147.898 48.156c-0.677 1.379 4.784 3.203 6.63 4.795 2.242 1.949 2.457 5.333 4.622 4.039 1.572-0.92 0.016-3.24-2.425-5.98-3.526-3.983-8.177-4.034-8.827-2.854z"/>
- <path fill="#333" d="m148.386 48.353c-0.673 1.292 4.348 2.99 6.167 4.552 2.179 1.886 2.394 5.095 4.432 3.88 1.506-0.878-0.038-3.136-2.312-5.693-3.268-3.705-7.636-3.85-8.287-2.739z"/>
- <path fill="#383838" d="m148.875 48.549c-0.668 1.206 3.911 2.778 5.703 4.309 2.116 1.823 2.331 4.855 4.242 3.721 1.439-0.836-0.093-3.032-2.197-5.405-3.013-3.428-7.098-3.667-7.748-2.625z"/>
- <path fill="#3d3d3d" d="m149.363 48.746c-0.662 1.119 3.475 2.566 5.24 4.065 2.053 1.759 2.268 4.616 4.052 3.562 1.375-0.795-0.147-2.928-2.082-5.118-2.757-3.15-6.559-3.483-7.21-2.509z"/>
- <path fill="#424242" d="m149.851 48.942c-0.657 1.032 3.039 2.354 4.776 3.823 1.99 1.696 2.205 4.376 3.861 3.402 1.31-0.753-0.201-2.824-1.967-4.831-2.5-2.871-6.018-3.298-6.67-2.394z"/>
- <path fill="#474747" d="m150.34 49.139c-0.652 0.946 2.603 2.142 4.313 3.58 1.927 1.632 2.143 4.137 3.671 3.243 1.244-0.712-0.256-2.72-1.853-4.543-2.245-2.595-5.48-3.115-6.131-2.28z"/>
- <path fill="#4c4c4c" d="m150.828 49.336c-0.647 0.859 2.166 1.93 3.851 3.336 1.863 1.569 2.079 3.898 3.48 3.084 1.179-0.67-0.31-2.616-1.739-4.255-1.988-2.317-4.94-2.932-5.592-2.165z"/>
- <path fill="#515151" d="m151.317 49.533c-0.645 0.772 1.729 1.718 3.386 3.093 1.802 1.505 2.018 3.658 3.29 2.925 1.114-0.628-0.364-2.512-1.624-3.968-1.732-2.04-4.4-2.748-5.052-2.05z"/>
- <path fill="#565656" d="m151.805 49.729c-0.639 0.685 1.293 1.505 2.923 2.85 1.738 1.442 1.954 3.419 3.1 2.766 1.048-0.586-0.418-2.408-1.509-3.681-1.476-1.762-3.862-2.563-4.514-1.935z"/>
- <path fill="#5b5b5b" d="m152.293 49.926c-0.633 0.598 0.857 1.293 2.46 2.606 1.677 1.379 1.892 3.18 2.91 2.606 0.983-0.544-0.473-2.304-1.395-3.393-1.22-1.483-3.322-2.379-3.975-1.819z"/>
- <path fill="#606060" d="m152.782 50.123c-0.629 0.512 0.42 1.081 1.996 2.363 1.613 1.315 1.828 2.94 2.719 2.447 0.918-0.502-0.525-2.2-1.28-3.105-0.963-1.207-2.782-2.196-3.435-1.705z"/>
- <path fill="#666" d="m153.27 50.319c-0.624 0.425-0.017 0.869 1.533 2.12 1.55 1.252 1.765 2.701 2.528 2.288 0.853-0.461-0.581-2.096-1.166-2.818-0.706-0.929-2.242-2.012-2.895-1.59z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m193.47 45.594c-0.072 1.08 2.951 1.728 4.896 2.448 1.944 0.648 5.76 3.24 7.56 5.256 1.801 1.944 5.688 7.704 6.553 6.192 0.863-1.368-2.017-5.328-2.809-6.984s-3.239-5.256-7.128-6.48c-3.384-1.008-9-1.297-9.072-0.432z"/>
- <path fill="#060606" d="m193.779 45.67c-0.071 1.05 2.869 1.685 4.758 2.387 1.891 0.633 5.598 3.161 7.345 5.122 1.747 1.893 5.535 7.493 6.376 6.027 0.84-1.328-1.936-5.173-2.738-6.795-0.8-1.622-3.175-5.09-6.952-6.301-3.282-0.995-8.718-1.28-8.789-0.44z"/>
- <path fill="#0c0c0c" d="m194.088 45.747c-0.07 1.021 2.785 1.641 4.62 2.327 1.836 0.618 5.436 3.081 7.131 4.988 1.692 1.842 5.382 7.282 6.198 5.862 0.814-1.288-1.855-5.019-2.67-6.607-0.808-1.587-3.11-4.925-6.776-6.122-3.178-0.983-8.433-1.264-8.503-0.448z"/>
- <path fill="#131313" d="m194.397 45.824c-0.071 0.991 2.702 1.598 4.481 2.267 1.782 0.603 5.272 3.001 6.916 4.854 1.64 1.791 5.229 7.071 6.022 5.697 0.788-1.248-1.776-4.865-2.603-6.418-0.815-1.554-3.044-4.759-6.599-5.942-3.073-0.973-8.148-1.251-8.217-0.458z"/>
- <path fill="#191919" d="m194.706 45.9c-0.069 0.961 2.618 1.555 4.345 2.206 1.728 0.588 5.109 2.922 6.7 4.721 1.586 1.74 5.075 6.86 5.846 5.531 0.764-1.207-1.696-4.711-2.532-6.23-0.824-1.519-2.979-4.593-6.424-5.763-2.972-0.959-7.866-1.234-7.935-0.465z"/>
- <path fill="#1f1f1f" d="m195.015 45.977c-0.07 0.931 2.534 1.511 4.207 2.146 1.672 0.573 4.945 2.843 6.485 4.586 1.531 1.689 4.921 6.649 5.668 5.367 0.738-1.167-1.616-4.557-2.464-6.042-0.832-1.485-2.914-4.428-6.247-5.583-2.868-0.948-7.581-1.219-7.649-0.474z"/>
- <path fill="#262626" d="m195.324 46.054c-0.069 0.901 2.451 1.468 4.069 2.085 1.618 0.557 4.784 2.763 6.271 4.453 1.479 1.638 4.769 6.438 5.491 5.201 0.714-1.127-1.536-4.402-2.396-5.854-0.839-1.451-2.848-4.263-6.07-5.404-2.765-0.934-7.298-1.202-7.365-0.481z"/>
- <path fill="#2c2c2c" d="m195.632 46.13c-0.067 0.872 2.369 1.424 3.933 2.025 1.563 0.542 4.621 2.684 6.056 4.318 1.424 1.587 4.615 6.228 5.315 5.036 0.688-1.086-1.456-4.248-2.326-5.665-0.848-1.416-2.783-4.097-5.896-5.224-2.662-0.923-7.015-1.187-7.082-0.49z"/>
- <path fill="#333" d="m195.941 46.207c-0.068 0.842 2.285 1.381 3.794 1.964 1.51 0.527 4.458 2.605 5.842 4.185 1.37 1.536 4.461 6.016 5.138 4.871 0.662-1.046-1.377-4.093-2.258-5.476-0.855-1.382-2.718-3.932-5.718-5.045-2.56-0.911-6.732-1.172-6.798-0.499z"/>
- <path fill="#393939" d="m196.25 46.284c-0.066 0.813 2.202 1.338 3.656 1.904 1.456 0.512 4.296 2.525 5.627 4.051 1.317 1.485 4.308 5.805 4.961 4.706 0.638-1.006-1.296-3.939-2.188-5.288-0.863-1.348-2.652-3.766-5.542-4.866-2.457-0.899-6.449-1.157-6.514-0.507z"/>
- <path fill="#3f3f3f" d="m196.559 46.36c-0.067 0.783 2.118 1.295 3.518 1.844 1.402 0.497 4.133 2.446 5.412 3.917 1.263 1.434 4.155 5.594 4.785 4.541 0.612-0.966-1.217-3.785-2.12-5.1-0.872-1.313-2.587-3.6-5.366-4.687-2.353-0.886-6.165-1.141-6.229-0.515z"/>
- <path fill="#464646" d="m196.868 46.437c-0.065 0.753 2.035 1.251 3.38 1.783 1.349 0.482 3.972 2.367 5.197 3.783 1.21 1.383 4.002 5.383 4.608 4.375 0.588-0.926-1.137-3.63-2.052-4.911-0.879-1.279-2.521-3.435-5.189-4.507-2.25-0.874-5.881-1.125-5.944-0.523z"/>
- <path fill="#4c4c4c" d="m197.177 46.514c-0.066 0.723 1.95 1.208 3.241 1.723 1.293 0.467 3.809 2.287 4.983 3.649 1.155 1.332 3.848 5.172 4.431 4.21 0.563-0.885-1.057-3.476-1.982-4.723-0.888-1.245-2.456-3.269-5.014-4.328-2.146-0.862-5.597-1.109-5.659-0.531z"/>
- <path fill="#525252" d="m197.486 46.591c-0.066 0.693 1.868 1.164 3.104 1.662 1.239 0.452 3.646 2.208 4.769 3.515 1.102 1.281 3.695 4.961 4.254 4.045 0.537-0.845-0.976-3.321-1.913-4.534-0.896-1.21-2.391-3.103-4.838-4.148-2.044-0.851-5.315-1.095-5.376-0.54z"/>
- <path fill="#595959" d="m197.795 46.667c-0.064 0.664 1.784 1.121 2.968 1.602 1.184 0.437 3.481 2.128 4.552 3.381 1.049 1.23 3.542 4.75 4.078 3.88 0.512-0.805-0.897-3.167-1.846-4.346-0.902-1.176-2.325-2.938-4.66-3.969-1.942-0.838-5.031-1.078-5.092-0.548z"/>
- <path fill="#5f5f5f" d="m198.104 46.744c-0.065 0.634 1.701 1.078 2.829 1.541 1.13 0.421 3.318 2.049 4.338 3.248 0.994 1.179 3.388 4.539 3.899 3.715 0.487-0.765-0.815-3.013-1.775-4.157-0.911-1.142-2.261-2.772-4.485-3.79-1.837-0.826-4.746-1.064-4.806-0.557z"/>
- <path fill="#666" d="m198.413 46.821c-0.063 0.604 1.617 1.034 2.691 1.481 1.076 0.406 3.157 1.969 4.123 3.113 0.94 1.128 3.234 4.328 3.724 3.55 0.462-0.725-0.737-2.858-1.707-3.969-0.919-1.108-2.195-2.606-4.309-3.61-1.734-0.814-4.463-1.049-4.522-0.565z"/>
- <path fill="#6c6c6c" d="m198.721 46.897c-0.063 0.574 1.534 0.991 2.554 1.42 1.021 0.391 2.994 1.89 3.908 2.979 0.887 1.077 3.082 4.117 3.548 3.384 0.436-0.685-0.657-2.704-1.64-3.78-0.927-1.074-2.13-2.44-4.132-3.431-1.631-0.8-4.179-1.031-4.238-0.572z"/>
- <path fill="#727272" d="m199.03 46.974c-0.063 0.544 1.451 0.948 2.416 1.36 0.967 0.376 2.831 1.811 3.694 2.846 0.833 1.026 2.928 3.906 3.369 3.219 0.411-0.644-0.576-2.549-1.569-3.592-0.936-1.04-2.064-2.275-3.956-3.251-1.528-0.79-3.896-1.017-3.954-0.582z"/>
- <path fill="#797979" d="m199.339 47.051c-0.062 0.515 1.368 0.904 2.278 1.299 0.913 0.361 2.669 1.731 3.479 2.712 0.779 0.975 2.774 3.695 3.193 3.054 0.386-0.604-0.497-2.396-1.501-3.403-0.942-1.005-1.999-2.11-3.78-3.072-1.424-0.778-3.612-1.002-3.669-0.59z"/>
- <path fill="#7f7f7f" d="m199.648 47.127c-0.063 0.485 1.284 0.861 2.14 1.239 0.859 0.346 2.506 1.652 3.265 2.578 0.726 0.924 2.621 3.484 3.017 2.889 0.361-0.564-0.417-2.241-1.432-3.215-0.951-0.971-1.935-1.944-3.604-2.893-1.323-0.765-3.33-0.986-3.386-0.598z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#995900" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.017 11.592-31.104 19.152-13.968 9.576-18.792 13.824-23.328 18.359-7.056 7.057-13.752 9.432-24.48 9.432s-15.552-2.231-18.863-5.184c-3.313-2.88-6.984-10.225-6.624-21.168 0.288-10.872 3.744-20.809 5.399-37.729 0.721-7.271 0.648-16.271 0.648-24.264 0-10.08 0.144-18.648 2.304-19.943 3.889-2.448 4.752-2.592 9.36-2.592 4.607 0 6.696 0.287 8.208 1.799 1.439 1.44 0.864 4.752 0.359 9.433-0.432 4.681 1.801 6.192 4.032 8.136 2.232 1.872 4.248 4.248 11.305 4.824 7.056 0.504 9.647-0.648 12.96-2.736 3.312-2.088 7.991-5.832 9.72-7.992 1.656-2.088 5.76-9.287 6.552-9.287 0.719 0 5.472-1.656 8.136 2.232z"/>
- <path fill="#9e5e00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.12 11.556-31.26 19.008-13.885 9.371-18.903 13.54-23.521 17.902-6.912 6.74-13.414 9.084-23.915 9.019-10.411-0.047-15.116-2.181-18.414-5.118-3.297-2.867-6.931-9.966-6.613-20.578 0.205-10.851 3.701-20.683 5.256-37.279 0.666-7.379 0.407-16.303 0.335-24.375-0.076-10.068-0.072-18.627 2.084-19.922 3.889-2.444 4.752-2.592 9.36-2.592 4.607 0 6.7 0.291 8.208 1.799 1.491 1.492 0.767 4.887 0.205 9.408-0.63 4.658 1.458 6.486 3.795 8.607 2.34 2.059 4.489 4.471 11.534 5.021 7.232 0.482 10.015-0.832 13.362-3.106 3.303-2.207 7.773-5.903 9.513-8.168 1.641-2.132 5.727-9.386 6.519-9.386 0.719 0 5.472-1.656 8.136 2.232z"/>
- <path fill="#a36400" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.226 11.52-31.414 18.863-13.803 9.166-19.016 13.256-23.717 17.447-6.768 6.422-13.075 8.733-23.35 8.604-10.094-0.094-14.682-2.131-17.964-5.055-3.283-2.852-6.876-9.705-6.603-19.987 0.122-10.828 3.657-20.556 5.112-36.828 0.612-7.487 0.165-16.336 0.021-24.487-0.15-10.058-0.287-18.605 1.865-19.9 3.889-2.44 4.752-2.592 9.36-2.592 4.607 0 6.703 0.295 8.208 1.799 1.541 1.541 0.67 5.02 0.051 9.383-0.828 4.637 1.116 6.781 3.556 9.078 2.448 2.248 4.731 4.695 11.766 5.221 7.409 0.461 10.383-1.016 13.767-3.477 3.29-2.326 7.552-5.977 9.302-8.346 1.627-2.175 5.695-9.482 6.487-9.482 0.72-0.001 5.473-1.657 8.137 2.231z"/>
- <path fill="#a86a00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.329 11.484-31.568 18.72-13.721 8.961-19.127 12.972-23.911 16.989-6.624 6.105-12.737 8.384-22.785 8.189-9.777-0.141-14.245-2.08-17.514-4.99-3.27-2.836-6.822-9.445-6.591-19.396 0.038-10.807 3.613-20.43 4.968-36.378 0.558-7.597-0.076-16.368-0.292-24.599-0.228-10.047-0.504-18.584 1.645-19.879 3.889-2.438 4.752-2.592 9.36-2.592 4.607 0 6.707 0.299 8.208 1.799 1.591 1.593 0.573 5.152-0.104 9.357-1.025 4.615 0.774 7.077 3.319 9.551 2.556 2.434 4.972 4.918 11.995 5.418 7.585 0.439 10.75-1.199 14.17-3.849 3.279-2.444 7.333-6.048 9.093-8.521 1.613-2.219 5.663-9.58 6.455-9.58 0.719 0.001 5.472-1.655 8.136 2.233z"/>
- <path fill="#ad7000" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.434 11.447-31.724 18.576-13.637 8.756-19.238 12.687-24.106 16.531-6.479 5.789-12.397 8.035-22.219 7.776-9.461-0.188-13.809-2.03-17.063-4.925-3.254-2.823-6.769-9.188-6.581-18.807-0.043-10.785 3.571-20.305 4.824-35.928 0.504-7.705-0.316-16.402-0.604-24.711-0.303-10.037-0.72-18.563 1.425-19.857 3.889-2.434 4.752-2.592 9.36-2.592 4.607 0 6.711 0.303 8.208 1.799 1.642 1.643 0.475 5.285-0.259 9.332-1.225 4.594 0.432 7.373 3.082 10.022 2.664 2.621 5.212 5.142 12.225 5.616 7.762 0.418 11.117-1.383 14.573-4.219 3.269-2.563 7.113-6.121 8.885-8.698 1.598-2.261 5.63-9.677 6.422-9.677 0.719 0.002 5.472-1.654 8.136 2.234z"/>
- <path fill="#b27500" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.538 11.412-31.879 18.432-13.554 8.551-19.35 12.402-24.3 16.074-6.336 5.473-12.06 7.686-21.654 7.361-9.144-0.233-13.374-1.979-16.613-4.859-3.24-2.809-6.714-8.928-6.57-18.216-0.126-10.765 3.528-20.179 4.68-35.478 0.45-7.813-0.558-16.435-0.918-24.822-0.378-10.026-0.936-18.541 1.206-19.836 3.889-2.43 4.752-2.592 9.36-2.592 4.607 0 6.714 0.305 8.208 1.799 1.691 1.693 0.378 5.418-0.414 9.307-1.422 4.572 0.09 7.668 2.844 10.494 2.772 2.808 5.454 5.363 12.456 5.814 7.938 0.396 11.484-1.566 14.977-4.591 3.258-2.682 6.894-6.192 8.676-8.874 1.584-2.304 5.598-9.773 6.39-9.773 0.718 0 5.471-1.656 8.135 2.232z"/>
- <path fill="#b77b00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.643 11.376-32.033 18.288-13.472 8.345-19.461 12.118-24.494 15.616-6.192 5.156-11.723 7.338-21.089 6.949-8.827-0.281-12.938-1.93-16.164-4.795-3.226-2.795-6.66-8.67-6.56-17.627-0.209-10.742 3.485-20.052 4.536-35.027 0.396-7.92-0.799-16.467-1.23-24.934-0.454-10.015-1.152-18.52 0.985-19.814 3.889-2.426 4.752-2.592 9.36-2.592 4.607 0 6.718 0.31 8.208 1.799 1.743 1.744 0.281 5.553-0.569 9.281-1.62 4.551-0.252 7.963 2.607 10.967 2.88 2.994 5.694 5.586 12.686 6.012 8.115 0.373 11.852-1.75 15.379-4.961 3.248-2.801 6.676-6.264 8.469-9.051 1.568-2.348 5.564-9.871 6.356-9.871 0.72 0 5.473-1.656 8.137 2.232z"/>
- <path fill="#bc8100" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.747 11.34-32.188 18.145-13.389 8.139-19.574 11.834-24.689 15.159-6.048 4.839-11.383 6.988-20.523 6.534-8.51-0.328-12.503-1.879-15.714-4.73-3.211-2.779-6.606-8.41-6.549-17.035-0.292-10.721 3.441-19.926 4.393-34.578 0.342-8.028-1.041-16.498-1.545-25.045-0.529-10.004-1.368-18.498 0.767-19.793 3.889-2.422 4.752-2.592 9.36-2.592 4.607 0 6.721 0.313 8.208 1.799 1.793 1.793 0.184 5.686-0.723 9.256-1.818 4.529-0.595 8.259 2.367 11.438 2.988 3.184 5.938 5.811 12.917 6.211 8.291 0.352 12.22-1.934 15.783-5.332 3.236-2.92 6.454-6.336 8.258-9.227 1.556-2.391 5.533-9.969 6.325-9.969 0.72-0.001 5.473-1.657 8.137 2.231z"/>
- <path fill="#c18700" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.852 11.304-32.343 18-13.306 7.936-19.685 11.549-24.883 14.703-5.904 4.521-11.045 6.638-19.959 6.119-8.193-0.375-12.067-1.828-15.264-4.666-3.197-2.764-6.553-8.149-6.537-16.444-0.375-10.699 3.397-19.8 4.248-34.128 0.288-8.137-1.282-16.531-1.858-25.156-0.604-9.994-1.584-18.477 0.547-19.771 3.889-2.42 4.752-2.592 9.36-2.592 4.607 0 6.725 0.316 8.208 1.799 1.843 1.845 0.087 5.818-0.878 9.231-2.017 4.507-0.937 8.554 2.131 11.909 3.096 3.369 6.178 6.033 13.146 6.408 8.468 0.33 12.587-2.117 16.187-5.703 3.225-3.038 6.235-6.408 8.049-9.402 1.541-2.436 5.501-10.066 6.293-10.066 0.72-0.001 5.473-1.657 8.137 2.231z"/>
- <path fill="#c68c00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.955 11.268-32.498 17.855-13.223 7.73-19.796 11.266-25.077 14.246-5.761 4.204-10.706 6.289-19.394 5.707-7.877-0.423-11.631-1.779-14.813-4.602-3.183-2.751-6.498-7.891-6.527-15.855-0.457-10.677 3.355-19.674 4.104-33.678 0.234-8.244-1.521-16.563-2.17-25.268-0.681-9.983-1.8-18.455 0.327-19.75 3.889-2.416 4.752-2.592 9.36-2.592 4.607 0 6.729 0.32 8.208 1.799 1.894 1.895-0.011 5.951-1.033 9.207-2.214 4.484-1.278 8.848 1.895 12.379 3.203 3.558 6.418 6.258 13.377 6.607 8.644 0.309 12.952-2.301 16.589-6.074 3.215-3.156 6.016-6.479 7.841-9.58 1.526-2.477 5.468-10.162 6.26-10.162 0.718 0.001 5.471-1.655 8.135 2.233z"/>
- <path fill="#cc9200" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.061 11.232-32.652 17.712-13.141 7.524-19.908 10.979-25.272 13.788-5.616 3.888-10.368 5.939-18.828 5.292-7.56-0.468-11.195-1.728-14.363-4.536-3.168-2.736-6.444-7.632-6.517-15.264-0.54-10.656 3.313-19.549 3.96-33.229 0.181-8.352-1.764-16.596-2.483-25.38-0.757-9.972-2.017-18.433 0.107-19.728 3.889-2.412 4.752-2.592 9.36-2.592 4.607 0 6.731 0.323 8.208 1.799 1.944 1.945-0.108 6.084-1.188 9.181-2.412 4.464-1.62 9.144 1.656 12.853 3.313 3.744 6.66 6.479 13.608 6.803 8.819 0.289 13.319-2.483 16.991-6.443 3.204-3.275 5.797-6.553 7.633-9.756 1.512-2.52 5.436-10.26 6.228-10.26 0.719 0 5.472-1.656 8.136 2.232z"/>
- <path fill="#d19800" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.164 11.195-32.808 17.568-13.057 7.318-20.019 10.695-25.466 13.33-5.473 3.571-10.03 5.592-18.263 4.879-7.243-0.516-10.761-1.678-13.914-4.472-3.153-2.722-6.391-7.372-6.506-14.674-0.623-10.634 3.27-19.422 3.816-32.778 0.126-8.459-2.005-16.627-2.797-25.49-0.832-9.961-2.232-18.412-0.112-19.707 3.889-2.408 4.752-2.592 9.36-2.592 4.607 0 6.736 0.328 8.208 1.799 1.995 1.996-0.205 6.219-1.343 9.156-2.61 4.442-1.962 9.438 1.419 13.323 3.42 3.931 6.9 6.703 13.838 7.002 8.997 0.267 13.687-2.668 17.395-6.815 3.194-3.395 5.577-6.623 7.424-9.932 1.497-2.564 5.403-10.357 6.195-10.357 0.721 0 5.474-1.656 8.138 2.232z"/>
- <path fill="#d69e00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.27 11.16-32.962 17.424-12.975 7.114-20.132 10.412-25.661 12.874-5.327 3.254-9.69 5.242-17.697 4.464-6.927-0.563-10.325-1.627-13.464-4.406-3.14-2.707-6.337-7.113-6.494-14.084-0.706-10.611 3.225-19.295 3.672-32.328 0.072-8.567-2.247-16.66-3.111-25.603-0.907-9.95-2.448-18.39-0.331-19.685 3.889-2.404 4.752-2.592 9.36-2.592 4.607 0 6.739 0.332 8.208 1.799 2.045 2.045-0.302 6.352-1.497 9.131-2.808 4.421-2.304 9.734 1.18 13.795 3.528 4.119 7.144 6.927 14.069 7.199 9.173 0.246 14.055-2.851 17.799-7.185 3.182-3.514 5.356-6.696 7.214-10.108 1.483-2.607 5.371-10.455 6.163-10.455 0.719 0 5.472-1.656 8.136 2.232z"/>
- <path fill="#dba300" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.373 11.124-33.116 17.279-12.893 6.91-20.243 10.127-25.855 12.418-5.184 2.937-9.353 4.892-17.133 4.05-6.609-0.609-9.889-1.577-13.014-4.343-3.125-2.692-6.282-6.854-6.483-13.492-0.789-10.592 3.182-19.17 3.528-31.879 0.018-8.676-2.488-16.692-3.425-25.713-0.982-9.94-2.664-18.369-0.551-19.664 3.889-2.401 4.752-2.592 9.36-2.592 4.607 0 6.743 0.334 8.208 1.799 2.095 2.097-0.399 6.484-1.652 9.105-3.006 4.398-2.646 10.029 0.943 14.268 3.636 4.305 7.384 7.148 14.299 7.397 9.349 0.224 14.422-3.034 18.202-7.558 3.171-3.631 5.137-6.768 7.005-10.284 1.469-2.649 5.339-10.552 6.131-10.552 0.72 0.001 5.473-1.655 8.137 2.233z"/>
- <path fill="#e0a900" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.478 11.088-33.271 17.136-12.81 6.704-20.354 9.843-26.05 11.96-5.04 2.62-9.015 4.543-16.567 3.637-6.293-0.656-9.453-1.527-12.563-4.277-3.11-2.68-6.229-6.596-6.474-12.903-0.871-10.569 3.141-19.044 3.384-31.428-0.035-8.784-2.728-16.726-3.735-25.826-1.06-9.929-2.88-18.347-0.771-19.642 3.889-2.397 4.752-2.592 9.36-2.592 4.607 0 6.747 0.338 8.208 1.799 2.146 2.146-0.497 6.617-1.808 9.08-3.203 4.377-2.987 10.324 0.706 14.738 3.744 4.493 7.624 7.373 14.529 7.596 9.526 0.203 14.789-3.217 18.605-7.926 3.161-3.752 4.918-6.841 6.797-10.463 1.454-2.693 5.306-10.648 6.098-10.648 0.719-0.001 5.472-1.657 8.136 2.231z"/>
- <path fill="#e5af00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.582 11.052-33.427 16.992-12.726 6.498-20.466 9.558-26.244 11.502-4.896 2.304-8.676 4.193-16.002 3.222-5.976-0.702-9.018-1.476-12.114-4.212-3.096-2.664-6.174-6.336-6.462-12.313-0.953-10.547 3.097-18.918 3.24-30.978-0.09-8.892-2.97-16.758-4.05-25.938-1.134-9.918-3.096-18.324-0.99-19.619 3.889-2.395 4.752-2.592 9.36-2.592 4.607 0 6.75 0.342 8.208 1.799 2.196 2.197-0.594 6.75-1.962 9.055-3.402 4.355-3.33 10.619 0.468 15.21 3.852 4.681 7.866 7.597 14.76 7.794 9.702 0.18 15.156-3.402 19.008-8.298 3.15-3.87 4.698-6.912 6.589-10.638 1.439-2.736 5.273-10.746 6.065-10.746 0.72 0 5.473-1.656 8.137 2.232z"/>
- <path fill="#eab500" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.687 11.016-33.582 16.848-12.643 6.293-20.576 9.274-26.438 11.045-4.752 1.987-8.338 3.846-15.438 2.809-5.658-0.75-8.582-1.426-11.664-4.147-3.08-2.649-6.119-6.077-6.45-11.722-1.037-10.526 3.053-18.792 3.096-30.528-0.144-9-3.211-16.79-4.363-26.049-1.21-9.907-3.312-18.304-1.21-19.599 3.889-2.391 4.752-2.592 9.36-2.592 4.607 0 6.754 0.346 8.208 1.799 2.247 2.248-0.691 6.885-2.117 9.029-3.6 4.336-3.672 10.916 0.231 15.682 3.96 4.867 8.106 7.82 14.989 7.992 9.879 0.158 15.523-3.586 19.411-8.668 3.141-3.99 4.479-6.984 6.38-10.814 1.426-2.78 5.241-10.844 6.033-10.844 0.721-0.001 5.474-1.657 8.138 2.231z"/>
- <path fill="#efba00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.791 10.98-33.735 16.703-12.562 6.089-20.69 8.99-26.633 10.589-4.608 1.67-7.999 3.496-14.872 2.394-5.343-0.796-8.147-1.375-11.215-4.082-3.066-2.636-6.065-5.818-6.439-11.132-1.12-10.504 3.009-18.666 2.952-30.077-0.198-9.109-3.453-16.822-4.677-26.162-1.285-9.896-3.528-18.281-1.43-19.576 3.889-2.387 4.752-2.592 9.36-2.592 4.607 0 6.757 0.35 8.208 1.799 2.297 2.297-0.788 7.018-2.271 9.004-3.798 4.314-4.014 11.211-0.008 16.154 4.068 5.055 8.35 8.043 15.221 8.189 10.056 0.137 15.892-3.77 19.815-9.039 3.128-4.107 4.258-7.057 6.17-10.99 1.411-2.824 5.209-10.941 6.001-10.941 0.72-0.001 5.473-1.657 8.137 2.231z"/>
- <path fill="#f4c000" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.896 10.943-33.891 16.561-12.478 5.883-20.801 8.704-26.827 10.131-4.464 1.353-7.661 3.146-14.307 1.979-5.025-0.843-7.711-1.325-10.765-4.019-3.053-2.621-6.012-5.558-6.429-10.541-1.203-10.482 2.966-18.539 2.809-29.627-0.253-9.217-3.694-16.855-4.99-26.272-1.361-9.886-3.744-18.261-1.649-19.556 3.889-2.383 4.752-2.592 9.36-2.592 4.607 0 6.761 0.353 8.208 1.799 2.347 2.349-0.885 7.15-2.426 8.979-3.996 4.291-4.356 11.505-0.245 16.625 4.176 5.241 8.59 8.265 15.451 8.388 10.23 0.115 16.258-3.953 20.218-9.41 3.117-4.227 4.039-7.129 5.961-11.168 1.396-2.865 5.177-11.037 5.969-11.037 0.72 0 5.473-1.656 8.137 2.232z"/>
- <path fill="#f9c600" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.999 10.908-34.046 16.416-12.395 5.678-20.912 8.421-27.021 9.674-4.32 1.036-7.322 2.797-13.741 1.566-4.709-0.891-7.275-1.275-10.314-3.953-3.037-2.607-5.958-5.299-6.419-9.951-1.284-10.461 2.925-18.414 2.664-29.178-0.306-9.324-3.934-16.887-5.302-26.385-1.437-9.875-3.96-18.238-1.869-19.533 3.889-2.379 4.752-2.592 9.36-2.592 4.607 0 6.765 0.356 8.208 1.799 2.397 2.398-0.983 7.283-2.581 8.955-4.194 4.269-4.698 11.799-0.482 17.096 4.284 5.429 8.83 8.488 15.682 8.586 10.407 0.094 16.625-4.137 20.621-9.781 3.106-4.345 3.819-7.199 5.753-11.344 1.382-2.909 5.144-11.135 5.936-11.135 0.718 0 5.471-1.656 8.135 2.232z"/>
- <path fill="#fc0" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-22.104 10.872-34.2 16.271-12.313 5.473-21.024 8.137-27.217 9.217-4.176 0.72-6.983 2.447-13.176 1.151-4.392-0.937-6.84-1.224-9.864-3.888-3.023-2.592-5.903-5.04-6.407-9.359-1.368-10.441 2.88-18.289 2.52-28.729-0.36-9.432-4.176-16.92-5.616-26.496-1.512-9.864-4.176-18.217-2.088-19.512 3.889-2.377 4.752-2.592 9.36-2.592 4.607 0 6.768 0.359 8.208 1.799 2.448 2.449-1.08 7.416-2.736 8.929-4.392 4.248-5.04 12.096-0.72 17.567 4.392 5.617 9.072 8.713 15.912 8.785 10.584 0.071 16.992-4.32 21.023-10.152 3.097-4.465 3.601-7.272 5.544-11.521 1.368-2.952 5.112-11.231 5.904-11.231 0.72 0.001 5.473-1.655 8.137 2.233z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fc0" d="m236.263 275.762c-0.709-0.258-3.932-15.209-2.191-16.239 3.351-1.997 4.253-2.319 8.377-2.319s6.057 0.322 7.346 1.61c2.126 2.127-1.159 6.702-2.448 7.991-3.738 3.673-10.375 9.215-11.084 8.957z"/>
- <path fill="#ffcc02" d="m236.492 275.286c-0.77-0.326-4.102-14.719-2.368-15.742 3.344-1.992 4.278-2.211 8.322-2.211 4.124 0 5.976 0.269 7.282 1.602 2.105 2.136-1.119 6.572-2.398 7.852-3.727 3.663-10.081 8.811-10.838 8.499z"/>
- <path fill="#ffcc05" d="m236.721 274.809c-0.832-0.393-4.273-14.229-2.547-15.247 3.339-1.983 4.306-2.101 8.269-2.101 4.124 0 5.896 0.213 7.217 1.592 2.087 2.146-1.076 6.443-2.346 7.714-3.718 3.653-9.788 8.409-10.593 8.042z"/>
- <path fill="#ffcc07" d="m236.949 274.333c-0.892-0.461-4.443-13.74-2.722-14.75 3.331-1.979 4.33-1.992 8.213-1.992 4.124 0 5.814 0.158 7.151 1.582 2.068 2.156-1.033 6.316-2.294 7.574-3.707 3.644-9.494 8.007-10.348 7.586z"/>
- <path fill="#ffcd0a" d="m237.178 273.855c-0.954-0.528-4.614-13.249-2.9-14.254 3.326-1.972 4.355-1.882 8.158-1.882 4.124 0 5.734 0.104 7.089 1.572 2.048 2.166-0.993 6.187-2.243 7.437-3.699 3.634-9.202 7.605-10.104 7.127z"/>
- <path fill="#ffcd0c" d="m237.407 273.377c-1.015-0.596-4.785-12.758-3.077-13.758 3.319-1.965 4.382-1.771 8.104-1.771 4.124 0 5.653 0.049 7.023 1.563 2.029 2.176-0.951 6.057-2.19 7.299-3.69 3.623-8.91 7.201-9.86 6.667z"/>
- <path fill="#ffcd0f" d="m237.636 272.901c-1.077-0.662-4.956-12.27-3.256-13.261 3.313-1.959 4.408-1.663 8.05-1.663 4.124 0 5.573-0.006 6.959 1.553 2.01 2.186-0.908 5.93-2.14 7.159-3.679 3.614-8.615 6.8-9.613 6.212z"/>
- <path fill="#ffcd11" d="m237.864 272.424c-1.137-0.731-5.126-11.779-3.431-12.766 3.306-1.951 4.433-1.553 7.994-1.553 4.123 0 5.492-0.061 6.895 1.543 1.991 2.193-0.867 5.801-2.089 7.021-3.669 3.606-8.321 6.397-9.369 5.755z"/>
- <path fill="#ffce14" d="m238.093 271.948c-1.197-0.799-5.297-11.289-3.607-12.27 3.299-1.946 4.459-1.443 7.938-1.443 4.124 0 5.412-0.115 6.83 1.533 1.973 2.204-0.824 5.671-2.037 6.883-3.659 3.596-8.028 5.993-9.124 5.297z"/>
- <path fill="#ffce16" d="m238.322 271.471c-1.26-0.867-5.468-10.801-3.786-11.773 3.293-1.939 4.485-1.334 7.884-1.334 4.124 0 5.332-0.171 6.767 1.524 1.953 2.213-0.783 5.542-1.985 6.743-3.651 3.586-7.736 5.591-8.88 4.84z"/>
- <path fill="#ffce19" d="m238.551 270.995c-1.32-0.935-5.639-10.312-3.963-11.277 3.286-1.934 4.511-1.225 7.829-1.225 4.124 0 5.252-0.226 6.702 1.514 1.934 2.224-0.741 5.414-1.934 6.605-3.64 3.576-7.442 5.187-8.634 4.383z"/>
- <path fill="#ffce1c" d="m238.779 270.517c-1.382-1.002-5.809-9.821-4.14-10.781 3.279-1.926 4.535-1.114 7.774-1.114 4.124 0 5.171-0.279 6.637 1.504 1.914 2.233-0.698 5.285-1.882 6.467-3.63 3.566-7.148 4.784-8.389 3.924z"/>
- <path fill="#ffcf1e" d="m239.008 270.04c-1.442-1.068-5.979-9.33-4.316-10.283 3.272-1.922 4.562-1.006 7.72-1.006 4.124 0 5.09-0.334 6.572 1.494 1.895 2.244-0.657 5.156-1.83 6.328-3.622 3.556-6.857 4.383-8.146 3.467z"/>
- <path fill="#ffcf21" d="m239.237 269.563c-1.505-1.137-6.151-8.841-4.495-9.788 3.267-1.914 4.588-0.896 7.666-0.896 4.124 0 5.009-0.389 6.508 1.486 1.875 2.252-0.616 5.025-1.778 6.188-3.613 3.548-6.564 3.981-7.901 3.01z"/>
- <path fill="#ffcf23" d="m239.466 269.086c-1.565-1.205-6.321-8.352-4.672-9.293 3.262-1.906 4.613-0.785 7.61-0.785 4.124 0 4.93-0.444 6.444 1.476 1.855 2.261-0.573 4.897-1.728 6.052-3.601 3.537-6.269 3.575-7.654 2.55z"/>
- <path fill="#ffcf26" d="m239.694 268.61c-1.627-1.273-6.492-7.861-4.849-8.796 3.255-1.901 4.64-0.677 7.556-0.677 4.124 0 4.849-0.499 6.379 1.466 1.837 2.271-0.531 4.769-1.675 5.912-3.593 3.528-5.977 3.174-7.411 2.095z"/>
- <path fill="#ffd028" d="m239.923 268.133c-1.688-1.34-6.663-7.373-5.025-8.301 3.248-1.895 4.665-0.566 7.501-0.566 4.124 0 4.768-0.555 6.314 1.456 1.817 2.28-0.489 4.64-1.624 5.774-3.583 3.519-5.684 2.771-7.166 1.637z"/>
- <path fill="#ffd02b" d="m240.152 267.657c-1.749-1.408-6.834-6.883-5.203-7.805 3.241-1.889 4.69-0.457 7.446-0.457 4.124 0 4.687-0.609 6.25 1.447 1.798 2.289-0.448 4.51-1.573 5.635-3.572 3.509-5.39 2.367-6.92 1.18z"/>
- <path fill="#ffd02d" d="m240.381 267.178c-1.811-1.475-7.005-6.391-5.381-7.307 3.235-1.881 4.717-0.348 7.393-0.348 4.124 0 4.606-0.664 6.185 1.438 1.779 2.299-0.405 4.381-1.521 5.496-3.564 3.501-5.098 1.965-6.676 0.721z"/>
- <path fill="#ffd030" d="m240.609 266.702c-1.871-1.543-7.175-5.902-5.557-6.811 3.228-1.875 4.741-0.238 7.336-0.238 4.124 0 4.526-0.719 6.122 1.428 1.759 2.31-0.364 4.252-1.471 5.357-3.552 3.49-4.803 1.562-6.43 0.264z"/>
- <path fill="#ffd133" d="m240.838 266.225c-1.933-1.611-7.346-5.413-5.734-6.314 3.222-1.869 4.768-0.129 7.281-0.129 4.124 0 4.446-0.773 6.058 1.418 1.74 2.318-0.322 4.123-1.418 5.219-3.545 3.48-4.512 1.16-6.187-0.194z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fc0" d="m302.769 263.374c3.742 5.461-0.062 12.76 2.638 17.117-6.809-6.258-9.938-8.834-19.324 0.367 2.577-3.742 3.129-6.257 4.725-9.814 1.104-2.455 4.354-9.57 5.029-9.57 0.613-0.001 4.724-1.35 6.932 1.9z"/>
- <path fill="#ffcc02" d="m302.73 263.413c3.655 5.334 0.035 12.601 2.578 16.723-6.668-6.098-9.729-8.666-18.908 0.322 2.421-3.527 3.025-6.094 4.605-9.592 1.122-2.462 4.243-9.302 4.951-9.311 0.628-0.008 4.617-1.318 6.774 1.858z"/>
- <path fill="#ffcc05" d="m302.691 263.45c3.568 5.209 0.132 12.441 2.517 16.332-6.526-5.938-9.519-8.5-18.492 0.277 2.268-3.314 2.924-5.934 4.488-9.372 1.141-2.468 4.132-9.032 4.873-9.052 0.641-0.013 4.508-1.284 6.614 1.815z"/>
- <path fill="#ffcc07" d="m302.652 263.487c3.48 5.086 0.229 12.282 2.457 15.939-6.386-5.777-9.311-8.332-18.076 0.232 2.111-3.1 2.819-5.771 4.369-9.15 1.158-2.475 4.021-8.762 4.795-8.791 0.655-0.019 4.399-1.254 6.455 1.77z"/>
- <path fill="#ffcd0a" d="m302.614 263.524c3.393 4.96 0.323 12.123 2.396 15.549-6.245-5.617-9.102-8.164-17.66 0.188 1.955-2.887 2.716-5.611 4.251-8.93 1.176-2.481 3.91-8.494 4.716-8.533 0.67-0.027 4.291-1.219 6.297 1.726z"/>
- <path fill="#ffcd0c" d="m302.575 263.562c3.306 4.835 0.419 11.964 2.335 15.155-6.104-5.457-8.891-7.996-17.244 0.143 1.8-2.673 2.613-5.449 4.133-8.707 1.194-2.488 3.8-8.225 4.638-8.273 0.684-0.036 4.182-1.189 6.138 1.682z"/>
- <path fill="#ffcd0f" d="m302.536 263.599c3.219 4.71 0.517 11.805 2.275 14.765-5.963-5.299-8.683-7.83-16.828 0.098 1.644-2.461 2.51-5.289 4.015-8.486 1.212-2.496 3.688-7.956 4.559-8.016 0.698-0.04 4.075-1.155 5.979 1.639z"/>
- <path fill="#ffcd11" d="m302.497 263.637c3.131 4.585 0.612 11.645 2.216 14.371-5.822-5.137-8.474-7.661-16.413 0.053 1.489-2.245 2.406-5.125 3.896-8.264 1.229-2.504 3.576-7.688 4.479-7.756 0.714-0.046 3.968-1.123 5.822 1.596z"/>
- <path fill="#ffce14" d="m302.458 263.674c3.044 4.459 0.708 11.486 2.154 13.979-5.681-4.978-8.263-7.493-15.996 0.009 1.334-2.033 2.303-4.965 3.779-8.043 1.247-2.511 3.464-7.418 4.4-7.498 0.728-0.052 3.859-1.089 5.663 1.553z"/>
- <path fill="#ffce16" d="m302.42 263.711c2.956 4.336 0.804 11.328 2.094 13.588-5.54-4.817-8.055-7.326-15.58-0.036 1.178-1.819 2.199-4.804 3.659-7.822 1.267-2.517 3.354-7.149 4.323-7.237 0.741-0.061 3.75-1.058 5.504 1.507z"/>
- <path fill="#ffce19" d="m302.381 263.749c2.868 4.211 0.9 11.168 2.033 13.196-5.398-4.657-7.845-7.159-15.164-0.081 1.022-1.605 2.097-4.642 3.542-7.601 1.283-2.524 3.241-6.88 4.244-6.979 0.755-0.067 3.642-1.026 5.345 1.465z"/>
- <path fill="#ffce1c" d="m302.342 263.788c2.78 4.084 0.997 11.008 1.973 12.803-5.258-4.498-7.635-6.991-14.748-0.127 0.867-1.391 1.994-4.479 3.424-7.379 1.302-2.531 3.13-6.61 4.166-6.719 0.768-0.074 3.532-0.992 5.185 1.422z"/>
- <path fill="#ffcf1e" d="m302.302 263.825c2.693 3.959 1.093 10.85 1.913 12.411-5.117-4.338-7.427-6.825-14.333-0.172 0.713-1.177 1.891-4.317 3.307-7.157 1.318-2.537 3.018-6.342 4.086-6.461 0.784-0.08 3.426-0.959 5.027 1.379z"/>
- <path fill="#ffcf21" d="m302.263 263.862c2.606 3.834 1.188 10.689 1.853 12.02-4.976-4.178-7.217-6.657-13.916-0.217 0.556-0.963 1.786-4.156 3.188-6.936 1.337-2.545 2.906-6.072 4.008-6.202 0.797-0.086 3.318-0.927 4.867 1.335z"/>
- <path fill="#ffcf23" d="m302.225 263.899c2.519 3.71 1.285 10.531 1.791 11.628-4.835-4.019-7.008-6.489-13.5-0.262 0.4-0.75 1.684-3.994 3.068-6.714 1.356-2.553 2.797-5.805 3.931-5.943 0.813-0.093 3.209-0.895 4.71 1.291z"/>
- <path fill="#ffcf26" d="m302.186 263.937c2.431 3.584 1.381 10.371 1.73 11.235-4.693-3.857-6.798-6.322-13.084-0.307 0.245-0.535 1.58-3.832 2.951-6.492 1.373-2.56 2.686-5.535 3.852-5.685 0.828-0.1 3.101-0.861 4.551 1.249z"/>
- <path fill="#ffd028" d="m302.147 263.974c2.344 3.46 1.477 10.213 1.671 10.845-4.553-3.699-6.589-6.156-12.668-0.354 0.089-0.321 1.477-3.67 2.832-6.271 1.392-2.565 2.574-5.267 3.772-5.425 0.842-0.104 2.994-0.828 4.393 1.205z"/>
- <path fill="#ffd02b" d="m302.108 264.012c2.257 3.334 1.573 10.053 1.61 10.451-4.412-3.537-6.38-5.987-12.253-0.396-0.064-0.109 1.374-3.51 2.716-6.05 1.408-2.573 2.462-4.997 3.693-5.166 0.856-0.112 2.886-0.796 4.234 1.161z"/>
- <path fill="#ffd02d" d="m302.069 264.049c2.17 3.209 1.67 9.894 1.55 10.061-4.271-3.379-6.17-5.82-11.836-0.441-0.221 0.104 1.271-3.35 2.596-5.83 1.428-2.58 2.352-4.728 3.615-4.906 0.87-0.12 2.777-0.765 4.075 1.116z"/>
- <path fill="#ffd030" d="m302.03 264.086c2.082 3.084 1.767 9.736 1.49 9.668-4.131-3.219-5.961-5.652-11.42-0.486-0.377 0.318 1.167-3.188 2.478-5.607 1.445-2.586 2.239-4.459 3.536-4.647 0.884-0.127 2.669-0.732 3.916 1.072z"/>
- <path fill="#ffd133" d="m301.991 264.124c1.995 2.959 1.862 9.576 1.43 9.277-3.989-3.059-5.752-5.486-11.005-0.531-0.532 0.531 1.064-3.027 2.36-5.387 1.463-2.594 2.128-4.189 3.458-4.389 0.899-0.133 2.561-0.699 3.757 1.03z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fc0" d="m305.862 283.481c5.977 7.848 17.064 16.271 21.024 18.576 2.88 1.656 7.056 3.6 6.983 8.783-0.144 5.904-3.168 7.561-4.823 9.217-3.313 3.313-22.177 10.943-34.2 16.271-12.24 5.4-21.097 8.209-27.217 9.217-4.104 0.647-7.056 2.375-13.176 1.151-4.32-0.864-6.912-1.296-9.864-3.888-2.951-2.52-5.976-5.184-6.407-9.359-1.225-10.369 3.672-16.921 8.424-25.921 3.888-7.2 11.735-8.64 16.632-7.991 17.568 2.375 16.416-8.641 21.24-13.465 4.464-4.463 17.208-8.064 21.384-2.591z"/>
- <path fill="#ffcc02" d="m305.81 283.553c5.962 7.83 17.024 16.234 20.975 18.533 2.873 1.652 7.039 3.592 6.969 8.764-0.145 5.891-3.161 7.542-4.813 9.195-3.304 3.304-22.34 10.992-34.24 16.088-12.259 5.176-20.647 7.873-26.802 8.959-4.077 0.684-7.156 2.394-13.258 1.177-4.304-0.854-6.767-1.231-9.707-3.812-2.939-2.51-5.756-4.961-6.185-9.117-1.211-10.34 3.365-16.657 8.044-25.65 3.89-7.375 11.791-8.434 16.665-7.777 17.514 2.414 16.206-8.959 21.02-13.772 4.452-4.454 17.166-8.047 21.332-2.588z"/>
- <path fill="#ffcc05" d="m305.76 283.627c5.946 7.812 16.982 16.195 20.925 18.488 2.866 1.648 7.022 3.584 6.951 8.743-0.144 5.876-3.153 7.524-4.801 9.173-3.298 3.297-22.506 11.043-34.28 15.907-12.279 4.949-20.201 7.538-26.389 8.699-4.051 0.721-7.256 2.413-13.341 1.202-4.286-0.846-6.619-1.168-9.55-3.733-2.924-2.501-5.536-4.741-5.959-8.877-1.198-10.312 3.058-16.394 7.664-25.379 3.89-7.552 11.845-8.229 16.698-7.563 17.458 2.453 15.995-9.279 20.797-14.08 4.443-4.443 17.127-8.026 21.285-2.58z"/>
- <path fill="#ffcc07" d="m305.707 283.702c5.935 7.791 16.943 16.156 20.876 18.444 2.859 1.644 7.007 3.574 6.935 8.722-0.144 5.862-3.146 7.508-4.79 9.151-3.288 3.289-22.668 11.093-34.319 15.726-12.298 4.723-19.753 7.202-25.974 8.44-4.024 0.756-7.357 2.431-13.423 1.226-4.27-0.836-6.473-1.101-9.394-3.654-2.911-2.492-5.317-4.52-5.735-8.635-1.185-10.285 2.75-16.133 7.284-25.109 3.892-7.727 11.9-8.023 16.731-7.35 17.402 2.494 15.785-9.599 20.575-14.389 4.433-4.432 17.087-8.007 21.234-2.572z"/>
- <path fill="#ffcd0a" d="m305.655 283.774c5.92 7.773 16.904 16.119 20.826 18.4 2.854 1.642 6.99 3.566 6.919 8.703-0.143 5.848-3.138 7.488-4.779 9.129-3.28 3.281-22.832 11.143-34.358 15.543-12.317 4.498-19.307 6.867-25.561 8.182-3.997 0.793-7.457 2.45-13.506 1.251-4.252-0.828-6.325-1.036-9.236-3.577-2.896-2.482-5.096-4.298-5.51-8.393-1.172-10.258 2.443-15.869 6.904-24.84 3.892-7.901 11.955-7.818 16.763-7.135 17.349 2.532 15.576-9.918 20.355-14.697 4.422-4.422 17.046-7.987 21.183-2.566z"/>
- <path fill="#ffcd0c" d="m305.603 283.847c5.906 7.756 16.864 16.081 20.777 18.358 2.846 1.635 6.973 3.557 6.901 8.68-0.142 5.835-3.131 7.472-4.767 9.107-3.273 3.273-22.997 11.193-34.399 15.361-12.337 4.273-18.858 6.533-25.146 7.924-3.971 0.829-7.557 2.469-13.588 1.276-4.234-0.82-6.179-0.972-9.078-3.5-2.884-2.474-4.878-4.076-5.287-8.152-1.158-10.229 2.137-15.606 6.523-24.569 3.895-8.076 12.01-7.611 16.797-6.92 17.293 2.571 15.366-10.236 20.134-15.004 4.412-4.411 17.006-7.969 21.133-2.561z"/>
- <path fill="#ffcd0f" d="m305.552 283.92c5.892 7.736 16.824 16.043 20.728 18.313 2.839 1.634 6.957 3.55 6.886 8.66-0.142 5.821-3.124 7.454-4.756 9.086-3.266 3.267-23.161 11.243-34.438 15.179-12.356 4.047-18.411 6.198-24.733 7.666-3.943 0.865-7.656 2.486-13.67 1.301-4.218-0.812-6.032-0.908-8.922-3.422-2.869-2.465-4.656-3.855-5.063-7.91-1.145-10.203 1.83-15.344 6.145-24.299 3.895-8.252 12.064-7.408 16.83-6.707 17.237 2.61 15.154-10.557 19.912-15.313 4.399-4.399 16.963-7.949 21.081-2.554z"/>
- <path fill="#ffcd11" d="m305.501 283.993c5.877 7.719 16.782 16.004 20.678 18.271 2.833 1.628 6.939 3.54 6.869 8.639-0.143 5.807-3.116 7.436-4.745 9.064-3.257 3.258-23.324 11.293-34.479 14.996-12.375 3.822-17.963 5.863-24.319 7.408-3.917 0.9-7.757 2.504-13.752 1.324-4.2-0.802-5.886-0.842-8.765-3.344-2.856-2.454-4.438-3.633-4.838-7.669-1.132-10.173 1.521-15.081 5.764-24.029 3.896-8.426 12.119-7.2 16.863-6.491 17.183 2.649 14.945-10.875 19.689-15.621 4.391-4.389 16.926-7.93 21.035-2.548z"/>
- <path fill="#ffce14" d="m305.448 284.066c5.863 7.701 16.743 15.966 20.629 18.228 2.826 1.625 6.924 3.531 6.853 8.619-0.142 5.793-3.108 7.418-4.733 9.043-3.25 3.25-23.489 11.342-34.518 14.813-12.396 3.598-17.517 5.529-23.905 7.148-3.891 0.938-7.857 2.524-13.834 1.351-4.185-0.793-5.74-0.776-8.609-3.267-2.841-2.444-4.217-3.412-4.613-7.426-1.118-10.146 1.216-14.818 5.385-23.76 3.896-8.602 12.174-6.996 16.896-6.277 17.128 2.688 14.735-11.195 19.468-15.929 4.378-4.38 16.883-7.911 20.981-2.543z"/>
- <path fill="#ffce16" d="m305.396 284.139c5.85 7.682 16.703 15.928 20.579 18.184 2.82 1.62 6.907 3.523 6.837 8.598-0.141 5.779-3.101 7.4-4.722 9.021-3.242 3.242-23.653 11.393-34.559 14.631-12.414 3.372-17.068 5.194-23.491 6.891-3.862 0.975-7.957 2.543-13.917 1.375-4.167-0.783-5.592-0.713-8.451-3.188-2.827-2.437-3.997-3.19-4.389-7.187-1.105-10.117 0.908-14.555 5.004-23.487 3.898-8.776 12.229-6.79 16.928-6.063 17.074 2.728 14.525-11.515 19.248-16.236 4.37-4.371 16.845-7.894 20.933-2.539z"/>
- <path fill="#ffce19" d="m305.344 284.211c5.836 7.664 16.663 15.891 20.529 18.141 2.813 1.617 6.892 3.516 6.82 8.578-0.14 5.765-3.093 7.382-4.71 8.999-3.235 3.233-23.817 11.442-34.598 14.448-12.434 3.146-16.621 4.859-23.077 6.633-3.837 1.01-8.058 2.561-13.999 1.4-4.15-0.775-5.446-0.648-8.295-3.111-2.814-2.426-3.777-2.969-4.164-6.944-1.094-10.09 0.601-14.293 4.624-23.22 3.898-8.951 12.282-6.584 16.961-5.848 17.019 2.767 14.314-11.834 19.025-16.545 4.361-4.359 16.806-7.872 20.884-2.531z"/>
- <path fill="#ffce1c" d="m305.292 284.286c5.822 7.646 16.623 15.852 20.481 18.096 2.806 1.613 6.874 3.507 6.804 8.558-0.141 5.751-3.086 7.364-4.699 8.978-3.227 3.227-23.981 11.492-34.638 14.267-12.453 2.921-16.173 4.524-22.663 6.374-3.81 1.046-8.158 2.578-14.082 1.424-4.133-0.766-5.299-0.583-8.137-3.033-2.801-2.416-3.558-2.748-3.94-6.703-1.08-10.062 0.293-14.029 4.244-22.947 3.9-9.127 12.338-6.379 16.994-5.635 16.964 2.805 14.105-12.152 18.805-16.853 4.348-4.351 16.763-7.856 20.831-2.526z"/>
- <path fill="#ffcf1e" d="m305.241 284.358c5.808 7.627 16.582 15.814 20.432 18.053 2.799 1.609 6.856 3.498 6.787 8.536-0.141 5.738-3.079 7.347-4.688 8.957-3.219 3.218-24.145 11.541-34.677 14.084-12.473 2.695-15.727 4.188-22.25 6.115-3.783 1.083-8.258 2.599-14.163 1.448-4.116-0.756-5.153-0.518-7.981-2.954-2.786-2.408-3.337-2.526-3.716-6.462-1.066-10.034-0.013-13.766 3.864-22.678 3.901-9.303 12.393-6.172 17.027-5.42 16.908 2.844 13.896-12.473 18.583-17.16 4.338-4.337 16.723-7.835 20.782-2.519z"/>
- <path fill="#ffcf21" d="m305.189 284.431c5.793 7.608 16.542 15.776 20.382 18.009 2.792 1.605 6.84 3.49 6.771 8.516-0.14 5.725-3.071 7.33-4.677 8.936-3.211 3.211-24.309 11.591-34.717 13.902-12.491 2.47-15.278 3.854-21.836 5.856-3.756 1.119-8.357 2.616-14.246 1.474-4.099-0.748-5.006-0.453-7.823-2.877-2.772-2.398-3.118-2.306-3.492-6.22-1.053-10.007-0.319-13.505 3.484-22.407 3.903-9.479 12.448-5.969 17.062-5.207 16.853 2.883 13.684-12.791 18.36-17.469 4.328-4.328 16.683-7.819 20.732-2.513z"/>
- <path fill="#ffcf23" d="m305.137 284.504c5.778 7.59 16.503 15.736 20.332 17.965 2.786 1.602 6.825 3.482 6.755 8.496-0.139 5.709-3.064 7.311-4.665 8.912-3.204 3.203-24.474 11.642-34.759 13.721-12.51 2.244-14.829 3.52-21.421 5.598-3.729 1.155-8.457 2.635-14.327 1.499-4.082-0.739-4.86-0.389-7.667-2.8-2.76-2.389-2.897-2.083-3.268-5.979-1.04-9.979-0.627-13.24 3.104-22.138 3.903-9.653 12.503-5.762 17.093-4.991 16.799 2.922 13.475-13.111 18.141-17.777 4.318-4.316 16.643-7.799 20.682-2.506z"/>
- <path fill="#ffcf26" d="m305.086 284.579c5.765 7.57 16.463 15.697 20.282 17.92 2.779 1.599 6.809 3.474 6.738 8.476-0.139 5.696-3.056 7.293-4.654 8.892-3.194 3.194-24.637 11.69-34.797 13.536-12.529 2.021-14.382 3.185-21.007 5.341-3.703 1.191-8.559 2.652-14.411 1.523-4.065-0.73-4.713-0.324-7.509-2.723-2.745-2.379-2.679-1.861-3.043-5.735-1.027-9.952-0.936-12.979 2.724-21.868 3.905-9.828 12.557-5.557 17.126-4.777 16.744 2.961 13.265-13.431 17.919-18.084 4.307-4.309 16.602-7.783 20.632-2.501z"/>
- <path fill="#ffd028" d="m305.033 284.651c5.752 7.553 16.423 15.66 20.234 17.878 2.771 1.593 6.791 3.464 6.722 8.454-0.139 5.682-3.049 7.275-4.643 8.869-3.188 3.188-24.801 11.74-34.838 13.355-12.548 1.793-13.935 2.85-20.593 5.082-3.676 1.228-8.658 2.67-14.493 1.547-4.048-0.721-4.565-0.258-7.353-2.644-2.731-2.37-2.457-1.64-2.818-5.495-1.014-9.923-1.242-12.716 2.345-21.597 3.905-10.004 12.611-5.351 17.158-4.563 16.689 3 13.055-13.75 17.698-18.393 4.297-4.295 16.562-7.761 20.581-2.493z"/>
- <path fill="#ffd02b" d="m304.982 284.724c5.737 7.534 16.382 15.622 20.184 17.834 2.766 1.59 6.774 3.456 6.705 8.433-0.138 5.67-3.041 7.26-4.631 8.85-3.18 3.179-24.966 11.789-34.877 13.172-12.568 1.568-13.487 2.515-20.179 4.824-3.65 1.263-8.759 2.688-14.575 1.572-4.031-0.713-4.42-0.195-7.196-2.566-2.718-2.361-2.238-1.42-2.594-5.254-1.001-9.896-1.549-12.453 1.964-21.328 3.907-10.178 12.666-5.145 17.192-4.348 16.634 3.039 12.844-14.068 17.476-18.701 4.285-4.286 16.521-7.743 20.531-2.488z"/>
- <path fill="#ffd02d" d="m304.93 284.797c5.723 7.516 16.342 15.584 20.135 17.789 2.758 1.588 6.758 3.449 6.688 8.414-0.138 5.654-3.034 7.24-4.619 8.826-3.173 3.172-25.13 11.84-34.918 12.99-12.587 1.344-13.039 2.18-19.766 4.564-3.622 1.301-8.856 2.709-14.657 1.599-4.014-0.704-4.272-0.13-7.039-2.489-2.702-2.352-2.018-1.197-2.369-5.012-0.987-9.868-1.855-12.189 1.584-21.057 3.908-10.354 12.722-4.94 17.226-4.135 16.578 3.078 12.634-14.389 17.254-19.009 4.275-4.273 16.481-7.721 20.481-2.48z"/>
- <path fill="#ffd030" d="m304.879 284.87c5.709 7.498 16.302 15.547 20.085 17.748 2.752 1.582 6.741 3.438 6.673 8.391-0.139 5.642-3.027 7.224-4.609 8.806-3.164 3.164-25.293 11.89-34.956 12.808-12.606 1.119-12.592 1.844-19.352 4.308-3.596 1.336-8.958 2.726-14.739 1.622-3.997-0.695-4.127-0.065-6.882-2.411-2.69-2.343-1.799-0.976-2.146-4.771-0.974-9.84-2.163-11.928 1.204-20.787 3.91-10.529 12.777-4.734 17.258-3.92 16.524 3.117 12.424-14.707 17.034-19.316 4.263-4.267 16.439-7.706 20.43-2.478z"/>
- <path fill="#ffd133" d="m304.826 284.943c5.695 7.479 16.263 15.509 20.036 17.703 2.745 1.579 6.726 3.431 6.656 8.372-0.137 5.627-3.02 7.205-4.597 8.783-3.157 3.156-25.458 11.939-34.997 12.625-12.626 0.893-12.145 1.51-18.938 4.049-3.569 1.373-9.058 2.745-14.822 1.646-3.979-0.686-3.979 0-6.725-2.332-2.676-2.334-1.578-0.756-1.921-4.529-0.961-9.813-2.471-11.665 0.824-20.516 3.91-10.705 12.83-4.529 17.29-3.707 16.47 3.156 12.215-15.027 16.813-19.625 4.255-4.253 16.401-7.684 20.381-2.469z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#995900" d="m52.494 273.618c-6.479 4.68-22.896 4.248-27.072 9.719-4.104 5.473 0.145 13.393 0.072 28.08 0 6.265-1.08 11.017-1.8 14.832-1.008 4.824-1.656 8.209 0.36 11.664 3.672 6.121 9.575 7.633 43.344 14.688 18.072 3.744 35.136 13.464 46.584 14.399 11.448 0.865 13.896-2.951 20.88-9.144 6.912-6.192 9.144-4.248 8.928-17.856-0.216-13.535-8.928-17.567-18.792-33.191s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.208 13.248-14.688 17.929z"/>
- <path fill="#9e5e00" d="m52.598 273.905c-6.397 4.702-22.475 3.788-27.062 9.512-4.154 5.414 0.228 13.276 0.098 27.955-0.025 6.23-1.152 10.881-1.937 14.877-1.037 4.871-1.678 8.201 0.349 11.619 3.787 6.162 9.695 7.123 43.456 14.168 18.061 3.737 34.541 13.307 46.343 14.112 11.186 0.792 13.564-2.829 20.463-8.96 6.896-6.195 9.024-4.277 8.858-17.406-0.075-13.521-8.305-17.349-18.169-32.973s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.153 13.479-14.583 18.216z"/>
- <path fill="#a36400" d="m52.703 274.193c-6.314 4.724-22.054 3.327-27.051 9.304-4.204 5.356 0.31 13.16 0.123 27.828-0.051 6.198-1.225 10.748-2.074 14.924-1.065 4.918-1.699 8.194 0.339 11.571 3.902 6.206 9.813 6.617 43.567 13.651 18.05 3.73 33.948 13.146 46.101 13.824 10.923 0.72 13.234-2.707 20.045-8.777 6.885-6.199 8.907-4.305 8.792-16.956 0.064-13.507-7.683-17.129-17.547-32.753s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.1 13.709-14.479 18.504z"/>
- <path fill="#a86a00" d="m52.807 274.481c-6.231 4.745-21.633 2.866-27.04 9.094-4.255 5.299 0.393 13.047 0.148 27.702-0.076 6.167-1.297 10.616-2.211 14.972-1.095 4.965-1.721 8.188 0.328 11.524 4.018 6.25 9.932 6.108 43.679 13.134 18.039 3.721 33.354 12.988 45.86 13.535 10.659 0.648 12.902-2.585 19.627-8.593 6.869-6.203 8.788-4.335 8.723-16.507 0.205-13.492-7.06-16.909-16.924-32.533s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.045 13.94-14.374 18.792z"/>
- <path fill="#ad7000" d="m52.912 274.769c-6.149 4.767-21.211 2.405-27.029 8.885-4.306 5.242 0.476 12.931 0.173 27.576-0.101 6.136-1.368 10.483-2.347 15.019-1.123 5.012-1.742 8.181 0.316 11.478 4.133 6.293 10.052 5.603 43.791 12.614 18.028 3.716 32.76 12.83 45.619 13.248 10.396 0.576 12.57-2.463 19.21-8.409 6.854-6.206 8.668-4.363 8.653-16.056 0.347-13.479-6.437-16.69-16.301-32.314s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.991 14.169-14.269 19.079z"/>
- <path fill="#b27500" d="m53.016 275.057c-6.066 4.787-20.79 1.943-27.019 8.676-4.355 5.184 0.559 12.816 0.198 27.45-0.126 6.103-1.44 10.351-2.484 15.065-1.151 5.059-1.764 8.172 0.307 11.431 4.248 6.336 10.17 5.094 43.901 12.096 18.019 3.708 32.166 12.672 45.378 12.96 10.135 0.504 12.24-2.34 18.792-8.227 6.841-6.209 8.551-4.391 8.586-15.605 0.486-13.464-5.813-16.47-15.678-32.094s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.937 14.399-14.165 19.368z"/>
- <path fill="#b77b00" d="m53.121 275.344c-5.983 4.811-20.369 1.484-27.008 8.469-4.406 5.126 0.641 12.7 0.224 27.324-0.151 6.068-1.512 10.216-2.621 15.111-1.181 5.105-1.785 8.166 0.295 11.385 4.363 6.379 10.289 4.586 44.014 11.576 18.008 3.701 31.572 12.515 45.137 12.672 9.872 0.433 11.909-2.217 18.375-8.041 6.825-6.215 8.431-4.422 8.518-15.156 0.627-13.45-5.191-16.251-15.056-31.875s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.884 14.631-14.062 19.655z"/>
- <path fill="#bc8100" d="m53.225 275.633c-5.9 4.832-19.948 1.023-26.997 8.259-4.457 5.069 0.724 12.585 0.249 27.198-0.177 6.037-1.584 10.082-2.758 15.158-1.21 5.152-1.808 8.158 0.284 11.338 4.479 6.422 10.407 4.078 44.125 11.059 17.997 3.693 30.979 12.355 44.896 12.384 9.608 0.36 11.578-2.095 17.957-7.858 6.812-6.217 8.313-4.449 8.45-14.707 0.766-13.435-4.569-16.03-14.434-31.654s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.829 14.859-13.956 19.943z"/>
- <path fill="#c18700" d="m53.329 275.92c-5.817 4.854-19.526 0.563-26.985 8.051-4.507 5.011 0.807 12.47 0.273 27.072-0.201 6.004-1.655 9.949-2.894 15.205-1.239 5.199-1.829 8.151 0.273 11.291 4.594 6.465 10.526 3.57 44.236 10.541 17.985 3.686 30.384 12.196 44.655 12.096 9.345 0.287 11.245-1.973 17.539-7.676 6.797-6.221 8.193-4.479 8.381-14.256 0.906-13.42-3.946-15.812-13.811-31.436s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.774 15.094-13.851 20.232z"/>
- <path fill="#c68c00" d="m53.433 276.209c-5.734 4.875-19.104 0.101-26.975 7.84-4.558 4.955 0.89 12.355 0.299 26.947-0.227 5.973-1.728 9.816-3.031 15.252-1.267 5.246-1.851 8.145 0.263 11.244 4.709 6.508 10.646 3.063 44.349 10.022 17.975 3.679 29.79 12.038 44.413 11.808 9.083 0.217 10.915-1.851 17.122-7.492 6.782-6.224 8.074-4.506 8.313-13.806 1.048-13.405-3.323-15.592-13.188-31.216s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.722 15.322-13.749 20.521z"/>
- <path fill="#cc9200" d="m53.538 276.497c-5.651 4.896-18.684-0.359-26.964 7.633-4.607 4.896 0.972 12.24 0.324 26.82-0.252 5.939-1.8 9.684-3.168 15.299-1.296 5.293-1.872 8.137 0.252 11.196 4.824 6.552 10.764 2.556 44.46 9.505 17.964 3.672 29.196 11.879 44.172 11.52 8.82 0.144 10.584-1.729 16.704-7.309 6.768-6.228 7.956-4.535 8.244-13.355 1.188-13.393-2.7-15.372-12.564-30.996s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.668 15.551-13.644 20.807z"/>
- <path fill="#d19800" d="m53.642 276.786c-5.569 4.918-18.263-0.82-26.953 7.424-4.658 4.838 1.055 12.123 0.35 26.693-0.277 5.907-1.872 9.551-3.305 15.346-1.325 5.34-1.894 8.129 0.241 11.15 4.938 6.596 10.883 2.048 44.571 8.984 17.953 3.666 28.602 11.723 43.931 11.232 8.558 0.072 10.253-1.605 16.287-7.123 6.753-6.232 7.837-4.566 8.175-12.906 1.329-13.379-2.077-15.153-11.941-30.777s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.614 15.783-13.54 21.097z"/>
- <path fill="#d69e00" d="m53.747 277.073c-5.486 4.94-17.842-1.281-26.942 7.215-4.709 4.781 1.138 12.01 0.374 26.568-0.302 5.875-1.943 9.417-3.441 15.393-1.354 5.387-1.915 8.123 0.23 11.104 5.055 6.639 11.002 1.541 44.684 8.467 17.942 3.658 28.008 11.563 43.688 10.944 8.296 0 9.923-1.483 15.869-6.941 6.74-6.235 7.72-4.593 8.108-12.456 1.468-13.363-1.455-14.933-11.319-30.557s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.56 16.012-13.435 21.383z"/>
- <path fill="#dba300" d="m53.851 277.361c-5.403 4.962-17.421-1.741-26.932 7.007-4.759 4.723 1.221 11.893 0.399 26.441-0.327 5.843-2.016 9.283-3.578 15.439-1.383 5.434-1.937 8.115 0.22 11.057 5.169 6.682 11.12 1.033 44.795 7.949 17.932 3.649 27.414 11.404 43.448 10.656 8.031-0.072 9.59-1.361 15.451-6.758 6.725-6.238 7.6-4.623 8.039-12.006 1.609-13.35-0.832-14.714-10.696-30.338s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.504 16.245-13.33 21.673z"/>
- <path fill="#e0a900" d="m53.956 277.649c-5.321 4.982-16.999-2.203-26.921 6.797-4.81 4.666 1.303 11.779 0.425 26.316-0.353 5.811-2.088 9.15-3.715 15.486-1.411 5.48-1.959 8.108 0.208 11.01 5.285 6.725 11.239 0.525 44.907 7.431 17.92 3.644 26.819 11.246 43.207 10.368 7.769-0.145 9.259-1.239 15.034-6.574 6.71-6.242 7.479-4.65 7.97-11.557 1.75-13.334-0.209-14.493-10.073-30.117s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.452 16.474-13.226 21.96z"/>
- <path fill="#e5af00" d="m54.06 277.937c-5.238 5.004-16.578-2.664-26.91 6.588-4.86 4.608 1.386 11.664 0.45 26.19-0.378 5.777-2.16 9.018-3.853 15.533-1.439 5.526-1.979 8.101 0.198 10.963 5.4 6.768 11.358 0.018 45.018 6.912 17.91 3.635 26.227 11.088 42.967 10.08 7.506-0.217 8.928-1.117 14.615-6.391 6.696-6.246 7.362-4.68 7.902-11.105 1.89-13.32 0.414-14.274-9.45-29.898s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.397 16.704-13.121 22.248z"/>
- <path fill="#eab500" d="m54.165 278.225c-5.155 5.025-16.157-3.124-26.899 6.38-4.91 4.55 1.469 11.548 0.476 26.063-0.403 5.746-2.232 8.885-3.989 15.58-1.469 5.573-2.002 8.094 0.188 10.916 5.515 6.812 11.477-0.49 45.129 6.394 17.899 3.629 25.633 10.93 42.725 9.792 7.243-0.288 8.598-0.993 14.199-6.206 6.681-6.25 7.243-4.709 7.833-10.656 2.031-13.306 1.037-14.055-8.827-29.679s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.346 16.935-13.019 22.536z"/>
- <path fill="#efba00" d="m54.269 278.513c-5.073 5.048-15.736-3.585-26.889 6.171-4.961 4.492 1.552 11.434 0.5 25.938-0.428 5.713-2.304 8.752-4.125 15.627-1.498 5.621-2.023 8.086 0.176 10.869 5.631 6.854 11.596-0.996 45.241 5.875 17.889 3.623 25.038 10.771 42.483 9.504 6.981-0.359 8.266-0.871 13.781-6.022 6.668-6.253 7.125-4.737 7.766-10.206 2.17-13.291 1.659-13.835-8.205-29.459s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.289 17.164-12.912 22.823z"/>
- <path fill="#f4c000" d="m54.374 278.801c-4.99 5.068-15.314-4.047-26.878 5.962-5.012 4.435 1.634 11.317 0.525 25.812-0.453 5.682-2.376 8.618-4.263 15.674-1.526 5.668-2.045 8.08 0.166 10.822 5.745 6.898 11.714-1.505 45.353 5.357 17.878 3.613 24.444 10.613 42.243 9.216 6.717-0.433 7.934-0.749 13.362-5.839 6.653-6.258 7.007-4.768 7.697-9.756 2.312-13.277 2.282-13.616-7.582-29.24s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.235 17.395-12.807 23.112z"/>
- <path fill="#f9c600" d="m54.477 279.088c-4.906 5.092-14.893-4.506-26.866 5.754-5.062 4.377 1.717 11.203 0.551 25.686-0.479 5.648-2.448 8.485-4.399 15.721-1.555 5.715-2.066 8.072 0.155 10.775 5.86 6.941 11.833-2.012 45.464 4.839 17.867 3.607 23.851 10.454 42.001 8.929 6.455-0.504 7.604-0.627 12.946-5.656 6.638-6.26 6.886-4.795 7.628-9.307 2.452-13.262 2.905-13.396-6.959-29.02s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.182 17.626-12.705 23.399z"/>
- <path fill="#fc0" d="m54.582 279.377c-4.823 5.111-14.472-4.969-26.855 5.543-5.112 4.32 1.8 11.088 0.576 25.561-0.504 5.616-2.521 8.352-4.536 15.768-1.584 5.76-2.088 8.064 0.144 10.729 5.977 6.984 11.952-2.52 45.576 4.32 17.856 3.6 23.256 10.295 41.76 8.64 6.192-0.576 7.272-0.504 12.528-5.472 6.624-6.264 6.768-4.824 7.56-8.856 2.592-13.248 3.528-13.176-6.336-28.8s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.129 17.855-12.601 23.687z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fc0" d="m57.701 285.002c-4.278 4.539-18.28-1.36-24.892 3.631-4.732 3.5 2.398 7.908 1.426 20.873-0.389 4.926-3.824 5.834-2.398 12.64 1.103 5.121 2.27 4.991 4.214 7.325 5.315 6.223 4.084 1.686 34.355 7.777 16.011 3.242 20.938 9.271 37.596 7.779 5.575-0.518 6.612-0.453 11.279-4.926 5.964-5.575 2.917-4.408 3.565-7.973 2.269-11.863 0.453-13.938-8.428-28.004-8.88-14.066-8.102-14.844-13.936-24.113-5.834-9.141-13.872-25.799-20.549-25.93-5.25-0.129-8.297 2.723-11.603 6.094-3.305 3.372-5.768 19.643-10.629 24.827z"/>
- <path fill="#ffcc02" d="m57.995 285.094c-4.461 4.701-18.604-1.196-25.06 3.705-4.701 3.514 2.578 8.05 1.608 20.68-0.4 4.896-3.733 5.877-2.458 12.634 0.986 5.093 2.357 4.938 4.334 7.201 5.686 6.131 4.673 1.826 34.119 7.743 15.918 3.211 20.815 9.215 37.372 7.732 5.541-0.513 6.479-0.463 11.155-4.849 5.865-5.407 2.858-4.287 3.412-8.058 2.066-11.787 0.442-13.981-8.188-27.649-8.83-13.983-8.143-14.698-13.941-23.913-5.8-9.085-13.701-25.805-20.338-25.934-5.219-0.129-8.248 2.705-11.533 6.057-3.287 3.352-5.644 19.505-10.482 24.651z"/>
- <path fill="#ffcc05" d="m58.289 285.185c-4.644 4.866-18.93-1.031-25.229 3.78-4.669 3.527 2.759 8.191 1.792 20.488-0.413 4.866-3.642 5.918-2.519 12.625 0.872 5.066 2.447 4.887 4.455 7.078 6.057 6.04 5.263 1.969 33.883 7.709 15.825 3.18 20.693 9.159 37.148 7.686 5.508-0.506 6.345-0.471 11.03-4.77 5.768-5.24 2.803-4.168 3.26-8.142 1.865-11.716 0.432-14.027-7.949-27.298-8.78-13.899-8.183-14.553-13.948-23.713-5.764-9.03-13.529-25.811-20.126-25.938-5.188-0.129-8.198 2.688-11.465 6.021-3.266 3.331-5.517 19.368-10.332 24.474z"/>
- <path fill="#ffcc07" d="m58.584 285.276c-4.827 5.03-19.255-0.865-25.397 3.855-4.639 3.541 2.938 8.332 1.975 20.295-0.425 4.838-3.551 5.961-2.578 12.619 0.757 5.039 2.536 4.834 4.575 6.955 6.428 5.949 5.852 2.108 33.646 7.674 15.733 3.147 20.571 9.103 36.925 7.639 5.475-0.501 6.211-0.48 10.905-4.693 5.67-5.072 2.745-4.045 3.107-8.224 1.663-11.642 0.42-14.073-7.711-26.946-8.73-13.814-8.223-14.406-13.952-23.511-5.729-8.976-13.358-25.817-19.916-25.944-5.156-0.127-8.148 2.674-11.396 5.984s-5.391 19.229-10.183 24.297z"/>
- <path fill="#ffcd0a" d="m58.878 285.368c-5.01 5.193-19.579-0.701-25.565 3.93-4.607 3.555 3.117 8.475 2.157 20.102-0.437 4.809-3.459 6.004-2.639 12.613 0.643 5.011 2.626 4.781 4.695 6.83 6.799 5.857 6.442 2.25 33.411 7.64 15.641 3.118 20.45 9.048 36.701 7.593 5.44-0.494 6.076-0.488 10.781-4.615 5.57-4.904 2.688-3.926 2.954-8.308 1.462-11.569 0.409-14.118-7.472-26.593-8.68-13.732-8.263-14.262-13.958-23.311-5.695-8.922-13.188-25.824-19.705-25.951-5.125-0.127-8.1 2.658-11.326 5.949-3.227 3.289-5.266 19.091-10.034 24.121z"/>
- <path fill="#ffcd0c" d="m59.173 285.458c-5.193 5.358-19.905-0.535-25.734 4.008-4.577 3.566 3.297 8.613 2.34 19.908-0.449 4.778-3.368 6.045-2.698 12.605 0.526 4.982 2.715 4.729 4.815 6.707 7.17 5.766 7.031 2.391 33.175 7.604 15.549 3.088 20.328 8.994 36.477 7.547 5.408-0.488 5.943-0.498 10.657-4.537 5.472-4.737 2.63-3.805 2.802-8.393 1.261-11.494 0.398-14.162-7.232-26.24-8.63-13.647-8.304-14.117-13.964-23.109-5.66-8.867-13.017-25.829-19.494-25.956-5.094-0.126-8.05 2.642-11.257 5.912-3.21 3.27-5.142 18.955-9.887 23.944z"/>
- <path fill="#ffcd0f" d="m59.467 285.547c-5.376 5.523-20.229-0.369-25.903 4.084-4.545 3.58 3.478 8.756 2.523 19.715-0.461 4.75-3.277 6.088-2.758 12.599 0.411 4.955 2.804 4.677 4.936 6.584 7.541 5.675 7.621 2.532 32.938 7.569 15.456 3.056 20.206 8.938 36.253 7.5 5.375-0.482 5.811-0.506 10.533-4.459 5.374-4.57 2.572-3.686 2.649-8.477 1.058-11.42 0.387-14.209-6.995-25.888-8.58-13.563-8.344-13.972-13.969-22.909-5.626-8.813-12.846-25.834-19.283-25.961-5.063-0.125-8 2.625-11.188 5.877-3.188 3.251-5.015 18.818-9.736 23.766z"/>
- <path fill="#ffcd11" d="m59.76 285.639c-5.559 5.688-20.555-0.205-26.071 4.158-4.515 3.594 3.657 8.896 2.706 19.521-0.473 4.721-3.186 6.131-2.818 12.594 0.297 4.926 2.894 4.623 5.057 6.459 7.911 5.584 8.21 2.674 32.703 7.535 15.362 3.025 20.084 8.883 36.027 7.453 5.342-0.477 5.677-0.515 10.409-4.381 5.275-4.402 2.516-3.564 2.497-8.561 0.855-11.348 0.375-14.254-6.756-25.535-8.53-13.479-8.385-13.825-13.976-22.709-5.59-8.758-12.673-25.842-19.071-25.965-5.031-0.125-7.951 2.608-11.119 5.838-3.168 3.232-4.888 18.684-9.588 23.593z"/>
- <path fill="#ffce14" d="m60.055 285.73c-5.742 5.851-20.88-0.04-26.24 4.233-4.483 3.607 3.837 9.039 2.889 19.33-0.485 4.69-3.095 6.172-2.878 12.584 0.182 4.9 2.982 4.572 5.177 6.338 8.282 5.492 8.8 2.814 32.467 7.498 15.271 2.996 19.962 8.828 35.804 7.408 5.309-0.472 5.543-0.523 10.285-4.304 5.177-4.235 2.458-3.444 2.344-8.644 0.654-11.273 0.364-14.299-6.518-25.184-8.479-13.395-8.425-13.679-13.98-22.507-5.556-8.704-12.502-25.849-18.86-25.972-5-0.123-7.901 2.593-11.05 5.803s-4.765 18.547-9.44 23.417z"/>
- <path fill="#ffce16" d="m60.349 285.821c-5.925 6.016-21.205 0.125-26.408 4.309-4.453 3.621 4.017 9.18 3.07 19.137-0.496 4.662-3.002 6.215-2.938 12.579 0.066 4.872 3.072 4.518 5.298 6.213 8.653 5.401 9.389 2.956 32.23 7.464 15.178 2.964 19.84 8.771 35.58 7.361 5.275-0.465 5.409-0.532 10.159-4.225 5.079-4.068 2.401-3.324 2.192-8.729 0.452-11.2 0.354-14.346-6.279-24.831-8.429-13.312-8.464-13.534-13.985-22.306-5.521-8.65-12.331-25.854-18.649-25.978-4.969-0.123-7.853 2.577-10.98 5.767-3.129 3.19-4.637 18.409-9.29 23.239z"/>
- <path fill="#ffce19" d="m60.643 285.911c-6.107 6.18-21.529 0.291-26.577 4.385-4.421 3.635 4.197 9.322 3.254 18.945-0.508 4.631-2.911 6.256-2.997 12.571-0.049 4.845 3.161 4.465 5.418 6.089 9.023 5.309 9.979 3.098 31.994 7.43 15.085 2.934 19.718 8.717 35.355 7.314 5.242-0.459 5.276-0.541 10.036-4.148 4.98-3.899 2.344-3.203 2.039-8.811 0.25-11.127 0.342-14.391-6.04-24.479-8.38-13.228-8.505-13.389-13.991-22.105-5.486-8.596-12.16-25.859-18.438-25.982-4.938-0.123-7.803 2.561-10.911 5.73-3.109 3.17-4.513 18.272-9.142 23.061z"/>
- <path fill="#ffce1c" d="m60.938 286.002c-6.291 6.344-21.855 0.455-26.746 4.459-4.391 3.648 4.377 9.463 3.437 18.752-0.521 4.603-2.82 6.299-3.058 12.564-0.163 4.817 3.251 4.413 5.539 5.965 9.395 5.219 10.567 3.24 31.758 7.396 14.993 2.903 19.597 8.661 35.132 7.269 5.209-0.453 5.143-0.55 9.912-4.07 4.882-3.732 2.286-3.082 1.887-8.895 0.048-11.053 0.329-14.436-5.802-24.126-8.33-13.144-8.545-13.243-13.997-21.905-5.451-8.541-11.988-25.865-18.228-25.988-4.906-0.121-7.753 2.545-10.843 5.695-3.088 3.149-4.385 18.132-8.991 22.884z"/>
- <path fill="#ffcf1e" d="m61.232 286.092c-6.473 6.51-22.18 0.621-26.914 4.535-4.359 3.662 4.557 9.604 3.619 18.559-0.532 4.574-2.729 6.342-3.117 12.559-0.278 4.789 3.34 4.36 5.659 5.842 9.766 5.127 11.157 3.381 31.521 7.359 14.9 2.872 19.475 8.607 34.908 7.223 5.176-0.447 5.008-0.559 9.787-3.992 4.784-3.565 2.229-2.963 1.735-8.979-0.155-10.98 0.317-14.482-5.564-23.773-8.279-13.061-8.585-13.098-14.002-21.705-5.416-8.485-11.817-25.871-18.017-25.992-4.875-0.121-7.704 2.527-10.773 5.658-3.068 3.128-4.26 17.995-8.842 22.706z"/>
- <path fill="#ffcf21" d="m61.526 286.184c-6.655 6.673-22.505 0.785-27.082 4.611-4.328 3.674 4.736 9.744 3.802 18.365-0.544 4.543-2.638 6.383-3.178 12.551-0.394 4.761 3.43 4.308 5.78 5.718 10.136 5.036 11.746 3.522 31.285 7.325 14.808 2.841 19.353 8.551 34.685 7.176 5.142-0.441 4.875-0.567 9.663-3.914 4.685-3.398 2.171-2.842 1.582-9.063-0.357-10.906 0.307-14.527-5.325-23.422-8.23-12.976-8.625-12.951-14.008-21.503-5.382-8.432-11.646-25.878-17.806-25.999-4.844-0.119-7.654 2.512-10.704 5.622-3.049 3.109-4.134 17.859-8.694 22.533z"/>
- <path fill="#ffcf23" d="m61.821 286.275c-6.839 6.837-22.83 0.95-27.251 4.687-4.298 3.688 4.916 9.886 3.984 18.172-0.557 4.515-2.546 6.426-3.237 12.545-0.509 4.732 3.519 4.255 5.9 5.594 10.507 4.945 12.336 3.663 31.05 7.29 14.715 2.812 19.23 8.496 34.46 7.129 5.108-0.435 4.74-0.575 9.538-3.835 4.587-3.23 2.113-2.723 1.43-9.146-0.559-10.834 0.296-14.572-5.086-23.069-8.18-12.892-8.666-12.806-14.014-21.302-5.347-8.377-11.476-25.885-17.595-26.004-4.813-0.119-7.605 2.496-10.635 5.584-3.029 3.088-4.008 17.722-8.544 22.355z"/>
- <path fill="#ffcf26" d="m62.115 286.366c-7.021 7.002-23.154 1.115-27.42 4.762-4.266 3.701 5.096 10.027 4.168 17.979-0.568 4.486-2.455 6.469-3.297 12.538-0.624 4.706 3.607 4.203 6.021 5.472 10.878 4.852 12.925 3.803 30.813 7.254 14.622 2.78 19.108 8.441 34.236 7.084 5.075-0.43 4.606-0.584 9.413-3.759 4.489-3.063 2.058-2.601 1.277-9.229-0.761-10.76 0.284-14.618-4.848-22.717-8.129-12.809-8.706-12.66-14.019-21.102-5.313-8.322-11.304-25.891-17.384-26.01-4.781-0.118-7.556 2.48-10.566 5.55-3.008 3.068-3.881 17.584-8.394 22.178z"/>
- <path fill="#ffd028" d="m62.409 286.456c-7.204 7.166-23.479 1.281-27.588 4.838-4.235 3.715 5.275 10.168 4.351 17.787-0.58 4.455-2.364 6.51-3.357 12.53-0.738 4.679 3.697 4.149 6.142 5.347 11.249 4.763 13.515 3.946 30.577 7.221 14.529 2.748 18.986 8.386 34.012 7.037 5.043-0.424 4.474-0.594 9.289-3.68 4.392-2.897 2-2.481 1.125-9.314-0.963-10.686 0.273-14.664-4.608-22.364-8.079-12.726-8.746-12.517-14.024-20.901-5.277-8.269-11.133-25.896-17.173-26.015-4.75-0.116-7.506 2.464-10.497 5.513-2.992 3.047-3.759 17.447-8.249 22.001z"/>
- <path fill="#ffd02b" d="m62.704 286.547c-7.388 7.33-23.805 1.445-27.757 4.912-4.204 3.729 5.455 10.311 4.533 17.594-0.593 4.427-2.272 6.553-3.417 12.523-0.854 4.651 3.786 4.098 6.262 5.225 11.619 4.671 14.104 4.087 30.341 7.185 14.438 2.72 18.864 8.33 33.787 6.991 5.01-0.418 4.341-0.604 9.166-3.604 4.292-2.729 1.942-2.359 0.972-9.396-1.163-10.613 0.263-14.709-4.369-22.012-8.03-12.641-8.787-12.371-14.03-20.7-5.243-8.214-10.962-25.903-16.962-26.021-4.719-0.117-7.457 2.447-10.428 5.477-2.972 3.029-3.632 17.313-8.098 21.826z"/>
- <path fill="#ffd02d" d="m62.998 286.638c-7.57 7.493-24.13 1.61-27.925 4.987-4.174 3.742 5.635 10.451 4.716 17.4-0.604 4.398-2.182 6.596-3.478 12.518-0.969 4.623 3.875 4.045 6.382 5.101 11.991 4.579 14.694 4.228 30.105 7.149 14.345 2.688 18.743 8.275 33.563 6.944 4.977-0.411 4.207-0.61 9.042-3.524 4.193-2.562 1.884-2.239 0.819-9.481-1.366-10.538 0.251-14.754-4.133-21.659-7.979-12.557-8.825-12.224-14.034-20.498-5.208-8.16-10.791-25.91-16.751-26.027-4.688-0.114-7.407 2.433-10.358 5.441-2.951 3.01-3.505 17.174-7.948 21.649z"/>
- <path fill="#ffd030" d="m63.292 286.729c-7.753 7.658-24.454 1.775-28.094 5.063-4.142 3.756 5.815 10.594 4.899 17.209-0.616 4.367-2.09 6.638-3.537 12.51-1.084 4.596 3.964 3.992 6.502 4.977 12.362 4.488 15.283 4.369 29.869 7.115 14.252 2.656 18.621 8.22 33.34 6.898 4.943-0.406 4.073-0.621 8.917-3.447 4.095-2.395 1.828-2.119 0.667-9.565-1.568-10.465 0.239-14.8-3.894-21.307-7.929-12.474-8.866-12.078-14.04-20.298-5.173-8.105-10.619-25.916-16.54-26.031-4.656-0.115-7.357 2.415-10.289 5.404-2.932 2.988-3.38 17.036-7.8 21.472z"/>
- <path fill="#ffd133" d="m63.587 286.82c-7.937 7.822-24.78 1.94-28.263 5.138-4.111 3.77 5.995 10.734 5.081 17.016-0.627 4.339-1.998 6.68-3.597 12.504-1.199 4.568 4.054 3.939 6.623 4.854 12.732 4.396 15.873 4.51 29.633 7.08 14.16 2.625 18.499 8.164 33.116 6.852 4.909-0.4 3.939-0.629 8.793-3.369 3.997-2.227 1.77-1.999 0.514-9.648-1.771-10.393 0.228-14.846-3.654-20.955-7.88-12.39-8.907-11.934-14.046-20.098-5.139-8.051-10.448-25.922-16.329-26.037-4.625-0.113-7.309 2.398-10.221 5.368s-3.254 16.897-7.65 21.295z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m88.782 218.681c-0.936 2.088-1.728 20.017 2.952 27 4.68 6.911 3.312 10.872-1.872 5.616-5.4-5.112-8.928-12.816-9-18.145 0-3.096 2.376-15.84 3.313-17.208 1.007-1.44 5.327 1.153 4.607 2.737z"/>
- <path fill="#030303" d="m88.692 219.032c-0.903 2.34-1.656 19.698 3.01 26.668 4.665 6.901 3.186 10.49-1.84 5.356-5.23-4.997-8.607-12.47-8.741-17.787-0.043-3.114 2.236-15.419 3.133-16.791 0.961-1.394 5.126 0.989 4.438 2.554z"/>
- <path fill="#070707" d="m88.602 219.379c-0.871 2.593-1.584 19.383 3.067 26.338 4.65 6.891 3.06 10.109-1.808 5.098-5.062-4.882-8.287-12.125-8.481-17.432-0.087-3.131 2.095-14.998 2.952-16.373 0.915-1.345 4.926 0.828 4.27 2.369z"/>
- <path fill="#0b0b0b" d="m88.512 219.729c-0.839 2.844-1.513 19.066 3.124 26.006 4.638 6.881 2.935 9.729-1.774 4.84-4.893-4.768-7.967-11.779-8.223-17.076-0.129-3.149 1.955-14.576 2.772-15.955 0.868-1.299 4.724 0.665 4.101 2.185z"/>
- <path fill="#0f0f0f" d="m88.422 220.079c-0.806 3.096-1.439 18.748 3.183 25.674 4.623 6.869 2.809 9.347-1.742 4.58-4.724-4.651-7.646-11.434-7.963-16.719-0.173-3.168 1.814-14.154 2.592-15.537 0.819-1.252 4.52 0.504 3.93 2.002z"/>
- <path fill="#131313" d="m88.332 220.426c-0.773 3.349-1.368 18.433 3.24 25.345 4.608 6.858 2.682 8.964-1.71 4.319-4.554-4.535-7.326-11.088-7.704-16.361-0.216-3.186 1.674-13.734 2.412-15.12 0.774-1.206 4.32 0.343 3.762 1.817z"/>
- <path fill="#161616" d="m88.242 220.777c-0.741 3.601-1.296 18.115 3.298 25.013 4.594 6.848 2.556 8.582-1.678 4.061-4.385-4.421-7.006-10.742-7.444-16.006-0.26-3.203 1.533-13.313 2.231-14.702 0.728-1.16 4.118 0.18 3.593 1.634z"/>
- <path fill="#1a1a1a" d="m88.152 221.125c-0.709 3.853-1.224 17.799 3.355 24.682 4.579 6.837 2.43 8.201-1.646 3.802-4.216-4.306-6.686-10.397-7.186-15.649-0.303-3.221 1.394-12.892 2.052-14.285 0.682-1.112 3.918 0.018 3.425 1.45z"/>
- <path fill="#1e1e1e" d="m88.062 221.475c-0.677 4.104-1.152 17.482 3.413 24.35 4.564 6.826 2.304 7.82-1.613 3.543-4.046-4.191-6.365-10.051-6.927-15.293-0.345-3.24 1.253-12.47 1.872-13.867 0.634-1.066 3.716-0.144 3.255 1.267z"/>
- <path fill="#222" d="m87.972 221.825c-0.645 4.355-1.08 17.164 3.47 24.018 4.551 6.816 2.179 7.439-1.58 3.285-3.877-4.076-6.044-9.707-6.667-14.938-0.389-3.258 1.112-12.049 1.691-13.449 0.587-1.019 3.514-0.306 3.086 1.084z"/>
- <path fill="#262626" d="m87.883 222.172c-0.612 4.609-1.009 16.849 3.527 23.688 4.536 6.804 2.052 7.056-1.548 3.024-3.708-3.961-5.724-9.36-6.408-14.58-0.432-3.276 0.973-11.629 1.513-13.032 0.54-0.971 3.311-0.467 2.916 0.9z"/>
- <path fill="#2a2a2a" d="m87.792 222.523c-0.579 4.86-0.936 16.531 3.586 23.356 4.521 6.793 1.926 6.675-1.516 2.765-3.539-3.845-5.403-9.015-6.148-14.224-0.476-3.293 0.831-11.207 1.332-12.614 0.493-0.925 3.11-0.63 2.746 0.717z"/>
- <path fill="#2d2d2d" d="m87.702 222.872c-0.547 5.112-0.864 16.215 3.644 23.025 4.507 6.783 1.8 6.293-1.483 2.506-3.369-3.73-5.083-8.669-5.89-13.867-0.519-3.312 0.691-10.785 1.152-12.197 0.446-0.878 2.908-0.792 2.577 0.533z"/>
- <path fill="#313131" d="m87.612 223.221c-0.515 5.363-0.792 15.898 3.701 22.693 4.492 6.772 1.674 5.912-1.451 2.248-3.2-3.615-4.763-8.324-5.63-13.512-0.563-3.33 0.551-10.363 0.972-11.779 0.399-0.831 2.707-0.953 2.408 0.35z"/>
- <path fill="#353535" d="m87.522 223.57c-0.482 5.616-0.72 15.581 3.758 22.363 4.479 6.761 1.549 5.53-1.418 1.987-3.031-3.5-4.442-7.978-5.371-13.154-0.604-3.348 0.41-9.943 0.792-11.361 0.352-0.785 2.506-1.115 2.239 0.165z"/>
- <path fill="#393939" d="m87.432 223.918c-0.45 5.869-0.648 15.265 3.815 22.033 4.464 6.75 1.422 5.147-1.386 1.728-2.862-3.384-4.122-7.632-5.112-12.798-0.647-3.366 0.271-9.522 0.612-10.944 0.307-0.737 2.305-1.278 2.071-0.019z"/>
- <path fill="#3d3d3d" d="m87.343 224.269c-0.418 6.12-0.576 14.946 3.873 21.7 4.45 6.74 1.296 4.767-1.354 1.469-2.692-3.27-3.802-7.286-4.853-12.441-0.691-3.383 0.129-9.101 0.432-10.527 0.26-0.691 2.103-1.44 1.902-0.201z"/>
- <path fill="#414141" d="m87.252 224.618c-0.385 6.373-0.504 14.631 3.932 21.369 4.436 6.729 1.17 4.385-1.321 1.211-2.523-3.154-3.481-6.941-4.594-12.086-0.734-3.402-0.011-8.68 0.252-10.109 0.212-0.644 1.901-1.602 1.731-0.385z"/>
- <path fill="#444" d="m87.162 224.967c-0.353 6.623-0.432 14.314 3.989 21.037 4.421 6.719 1.044 4.004-1.289 0.951-2.354-3.039-3.161-6.595-4.334-11.729-0.778-3.42-0.151-8.258 0.071-9.691 0.166-0.597 1.7-1.763 1.563-0.568z"/>
- <path fill="#484848" d="m87.072 225.316c-0.32 6.876-0.36 13.997 4.047 20.707 4.406 6.707 0.918 3.622-1.257 0.692-2.186-2.924-2.841-6.25-4.075-11.373-0.82-3.438-0.292-7.838-0.108-9.273 0.119-0.551 1.498-1.926 1.393-0.753z"/>
- <path fill="#4c4c4c" d="m86.982 225.665c-0.288 7.129-0.288 13.68 4.104 20.377 4.393 6.695 0.792 3.24-1.224 0.432s-2.52-5.904-3.816-11.016c-0.863-3.457-0.432-7.416-0.287-8.856 0.071-0.505 1.295-2.089 1.223-0.937z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m88.782 218.681c4.32-9.433 6.696-19.584 12.888-29.448 6.12-9.792 3.672-13.608-0.863-8.64-4.536 4.968-9.504 15.48-9.504 15.48s-5.832 9.216-7.128 19.872c-0.217 1.8 3.887 4.248 4.607 2.736z"/>
- <path fill="#020202" d="m88.968 218.071c4.279-9.5 6.615-19.246 12.586-28.802 5.901-9.488 3.608-13.279-0.764-8.472-4.403 4.847-9.302 15.236-9.368 15.381 0 0-5.637 8.993-6.877 19.239-0.209 1.771 3.72 4.145 4.423 2.654z"/>
- <path fill="#050505" d="m89.152 217.459c4.239-9.566 6.535-18.908 12.284-28.155 5.683-9.183 3.547-12.95-0.663-8.303-4.27 4.725-9.099 14.991-9.231 15.282 0 0-5.442 8.766-6.627 18.605-0.201 1.741 3.554 4.042 4.237 2.571z"/>
- <path fill="#070707" d="m89.338 216.849c4.199-9.634 6.454-18.572 11.981-27.51 5.465-8.878 3.484-12.621-0.563-8.135-4.137 4.605-8.896 14.748-9.096 15.184 0 0-5.247 8.542-6.376 17.972-0.192 1.713 3.387 3.937 4.054 2.489z"/>
- <path fill="#0a0a0a" d="m89.522 216.239c4.159-9.701 6.375-18.234 11.68-26.865 5.247-8.573 3.422-12.292-0.461-7.966-4.005 4.483-8.693 14.503-8.96 15.085 0 0-5.053 8.317-6.126 17.337-0.186 1.684 3.219 3.837 3.867 2.409z"/>
- <path fill="#0c0c0c" d="m89.708 215.627c4.118-9.769 6.294-17.897 11.376-26.218 5.029-8.268 3.36-11.962-0.359-7.797-3.871 4.361-8.49 14.259-8.823 14.985 0 0-4.858 8.093-5.876 16.706-0.179 1.653 3.051 3.731 3.682 2.324z"/>
- <path fill="#0f0f0f" d="m89.893 215.017c4.077-9.836 6.213-17.56 11.073-25.573 4.812-7.963 3.298-11.633-0.259-7.629-3.738 4.241-8.288 14.015-8.688 14.887 0 0-4.663 7.868-5.625 16.072-0.169 1.624 2.886 3.628 3.499 2.243z"/>
- <path fill="#111" d="m90.078 214.407c4.037-9.904 6.133-17.224 10.772-24.928 4.593-7.658 3.234-11.304-0.159-7.46-3.605 4.119-8.085 13.771-8.551 14.788 0 0-4.47 7.645-5.375 15.439-0.162 1.594 2.718 3.524 3.313 2.161z"/>
- <path fill="#141414" d="m90.263 213.795c3.997-9.971 6.052-16.885 10.47-24.281 4.374-7.353 3.172-10.975-0.059-7.291-3.472 3.998-7.882 13.526-8.415 14.689 0 0-4.273 7.418-5.124 14.805-0.154 1.565 2.551 3.421 3.128 2.078z"/>
- <path fill="#161616" d="m90.449 213.184c3.956-10.037 5.972-16.548 10.167-23.635 4.156-7.048 3.11-10.645 0.043-7.123-3.34 3.877-7.68 13.283-8.279 14.591 0 0-4.08 7.194-4.874 14.172-0.147 1.535 2.383 3.317 2.943 1.995z"/>
- <path fill="#191919" d="m90.634 212.573c3.916-10.105 5.892-16.209 9.865-22.989 3.938-6.743 3.047-10.316 0.144-6.954-3.207 3.755-7.477 13.038-8.143 14.491 0 0-3.886 6.969-4.624 13.54-0.139 1.506 2.217 3.213 2.758 1.912z"/>
- <path fill="#1c1c1c" d="m90.819 211.963c3.875-10.174 5.811-15.874 9.563-22.344 3.721-6.438 2.984-9.987 0.244-6.785-3.073 3.634-7.274 12.793-8.007 14.392 0 0-3.69 6.745-4.373 12.905-0.131 1.477 2.049 3.112 2.573 1.832z"/>
- <path fill="#1e1e1e" d="m91.004 211.352c3.836-10.24 5.73-15.536 9.262-21.698 3.501-6.133 2.922-9.658 0.344-6.617-2.94 3.513-7.071 12.55-7.87 14.293 0 0-3.496 6.521-4.123 12.272-0.124 1.447 1.881 3.009 2.387 1.75z"/>
- <path fill="#212121" d="m91.189 210.741c3.795-10.307 5.649-15.198 8.958-21.052 3.284-5.828 2.859-9.328 0.445-6.448-2.808 3.392-6.868 12.305-7.734 14.195 0 0-3.301 6.295-3.872 11.639-0.115 1.418 1.715 2.904 2.203 1.666z"/>
- <path fill="#232323" d="m91.375 210.129c3.754-10.373 5.569-14.86 8.655-20.405 3.066-5.523 2.797-8.999 0.547-6.279-2.675 3.27-6.666 12.061-7.599 14.097 0 0-3.106 6.07-3.622 11.004-0.107 1.388 1.548 2.801 2.019 1.583z"/>
- <path fill="#262626" d="m91.559 209.519c3.714-10.44 5.489-14.523 8.354-19.76 2.847-5.218 2.735-8.67 0.647-6.111-2.542 3.149-6.463 11.817-7.462 13.997 0 0-2.912 5.848-3.372 10.373-0.099 1.357 1.381 2.697 1.833 1.501z"/>
- <path fill="#282828" d="m91.745 208.909c3.674-10.509 5.408-14.187 8.051-19.115 2.629-4.913 2.672-8.341 0.748-5.942-2.409 3.028-6.261 11.573-7.326 13.898 0 0-2.717 5.621-3.121 9.738-0.092 1.33 1.213 2.595 1.648 1.421z"/>
- <path fill="#2b2b2b" d="m91.929 208.297c3.634-10.575 5.328-13.848 7.75-18.468 2.41-4.608 2.609-8.011 0.848-5.773-2.275 2.906-6.058 11.328-7.189 13.799 0 0-2.522 5.397-2.871 9.106-0.084 1.299 1.046 2.491 1.462 1.336z"/>
- <path fill="#2d2d2d" d="m92.115 207.687c3.593-10.643 5.247-13.512 7.447-17.823 2.191-4.303 2.547-7.682 0.949-5.605-2.144 2.786-5.855 11.085-7.055 13.701 0 0-2.327 5.172-2.62 8.473-0.076 1.269 0.881 2.386 1.279 1.254z"/>
- <path fill="#303030" d="m92.301 207.077c3.552-10.71 5.167-13.175 7.145-17.178 1.974-3.998 2.484-7.353 1.05-5.436-2.011 2.664-5.652 10.84-6.918 13.602 0 0-2.133 4.947-2.37 7.839-0.07 1.24 0.712 2.283 1.093 1.173z"/>
- <path fill="#333" d="m92.485 206.465c3.513-10.778 5.087-12.837 6.843-16.531s2.422-7.024 1.15-5.268c-1.877 2.543-5.449 10.596-6.781 13.502 0 0-1.938 4.724-2.12 7.207-0.061 1.211 0.545 2.18 0.908 1.09z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m273.03 225.592c2.088-5.903 1.872-20.951-3.456-30.671-1.872-3.528-3.672-7.632-4.752-7.848-1.152-0.216-3.24 2.088-3.024 2.448 0.288 0.576 10.009 14.256 7.992 32.832-0.144 1.513 2.736 4.608 3.24 3.239z"/>
- <path fill="#030303" d="m272.936 224.831c2.025-5.719 1.753-20.379-3.344-29.663-1.815-3.407-3.535-7.374-4.595-7.59-1.122-0.214-3.125 2.022-2.925 2.367 0.258 0.562 9.605 13.778 7.729 31.753-0.129 1.487 2.647 4.456 3.135 3.133z"/>
- <path fill="#070707" d="m272.841 224.068c1.967-5.532 1.637-19.808-3.228-28.654-1.762-3.286-3.401-7.115-4.44-7.332-1.091-0.211-3.009 1.956-2.824 2.287 0.227 0.548 9.201 13.299 7.466 30.672-0.118 1.463 2.555 4.305 3.026 3.027z"/>
- <path fill="#0b0b0b" d="m272.747 223.305c1.904-5.348 1.518-19.235-3.115-27.645-1.706-3.165-3.265-6.856-4.282-7.073-1.062-0.21-2.896 1.889-2.727 2.206 0.197 0.534 8.799 12.821 7.203 29.592-0.103 1.44 2.466 4.153 2.921 2.92z"/>
- <path fill="#0f0f0f" d="m272.652 222.542c1.843-5.162 1.398-18.662-3.001-26.635-1.65-3.044-3.13-6.598-4.127-6.815-1.03-0.207-2.779 1.823-2.626 2.126 0.167 0.52 8.396 12.341 6.94 28.511-0.09 1.416 2.376 4.001 2.814 2.813z"/>
- <path fill="#131313" d="m272.558 221.779c1.78-4.976 1.279-18.09-2.889-25.626-1.595-2.923-2.994-6.34-3.97-6.557-1-0.205-2.664 1.756-2.527 2.045 0.137 0.506 7.993 11.861 6.679 27.432-0.078 1.392 2.285 3.849 2.707 2.706z"/>
- <path fill="#161616" d="m272.463 221.016c1.721-4.79 1.163-17.518-2.773-24.617-1.539-2.802-2.858-6.081-3.814-6.299-0.969-0.203-2.548 1.691-2.427 1.965 0.106 0.492 7.59 11.383 6.415 26.352-0.065 1.369 2.194 3.697 2.599 2.599z"/>
- <path fill="#1a1a1a" d="m272.369 220.254c1.659-4.605 1.044-16.946-2.66-23.609-1.483-2.681-2.723-5.822-3.658-6.04-0.938-0.201-2.434 1.624-2.326 1.884 0.074 0.478 7.185 10.904 6.15 25.271-0.051 1.344 2.106 3.546 2.494 2.494z"/>
- <path fill="#1e1e1e" d="m272.274 219.491c1.598-4.42 0.926-16.373-2.546-22.6-1.43-2.56-2.587-5.564-3.501-5.782-0.908-0.198-2.319 1.558-2.229 1.804 0.044 0.464 6.782 10.425 5.889 24.19-0.037 1.321 2.016 3.396 2.387 2.388z"/>
- <path fill="#222" d="m272.18 218.728c1.535-4.233 0.807-15.802-2.434-21.59-1.373-2.439-2.452-5.306-3.345-5.524-0.877-0.197-2.203 1.491-2.128 1.723 0.014 0.45 6.379 9.947 5.625 23.111-0.023 1.297 1.927 3.242 2.282 2.28z"/>
- <path fill="#262626" d="m272.085 217.965c1.476-4.049 0.69-15.229-2.318-20.582-1.317-2.317-2.316-5.046-3.188-5.265-0.847-0.194-2.088 1.425-2.029 1.642-0.016 0.436 5.977 9.468 5.362 22.032-0.011 1.272 1.835 3.089 2.173 2.173z"/>
- <path fill="#2a2a2a" d="m271.991 217.202c1.413-3.861 0.571-14.656-2.206-19.572-1.262-2.196-2.18-4.788-3.032-5.007-0.815-0.191-1.973 1.36-1.929 1.562-0.047 0.422 5.573 8.988 5.099 20.951 0.003 1.247 1.746 2.939 2.068 2.066z"/>
- <path fill="#2d2d2d" d="m271.896 216.439c1.353-3.677 0.453-14.084-2.091-18.563-1.207-2.076-2.045-4.529-2.876-4.749-0.786-0.19-1.858 1.293-1.83 1.481-0.077 0.408 5.17 8.51 4.836 19.87 0.017 1.226 1.656 2.789 1.961 1.961z"/>
- <path fill="#313131" d="m271.802 215.676c1.29-3.491 0.334-13.512-1.979-17.553-1.151-1.956-1.909-4.272-2.72-4.493-0.755-0.187-1.742 1.227-1.73 1.401-0.106 0.394 4.768 8.031 4.573 18.791 0.031 1.202 1.567 2.637 1.856 1.854z"/>
- <path fill="#353535" d="m271.707 214.915c1.23-3.307 0.217-12.94-1.864-16.545-1.096-1.834-1.773-4.014-2.563-4.234-0.725-0.185-1.627 1.16-1.631 1.32-0.138 0.38 4.364 7.552 4.311 17.71 0.042 1.176 1.475 2.485 1.747 1.749z"/>
- <path fill="#393939" d="m271.613 214.151c1.168-3.119 0.098-12.367-1.751-15.535-1.04-1.714-1.638-3.755-2.407-3.976-0.693-0.183-1.512 1.094-1.531 1.24-0.168 0.366 3.962 7.074 4.049 16.63 0.055 1.153 1.384 2.332 1.64 1.641z"/>
- <path fill="#3d3d3d" d="m271.518 213.388c1.106-2.935-0.021-11.796-1.638-14.527-0.983-1.592-1.502-3.496-2.25-3.716-0.664-0.181-1.396 1.028-1.432 1.159-0.198 0.352 3.558 6.594 3.785 15.549 0.07 1.13 1.296 2.183 1.535 1.535z"/>
- <path fill="#414141" d="m271.424 212.625c1.047-2.75-0.139-11.223-1.522-13.518-0.93-1.471-1.367-3.238-2.094-3.459-0.635-0.178-1.282 0.962-1.333 1.079-0.229 0.338 3.153 6.114 3.521 14.47 0.083 1.106 1.205 2.03 1.428 1.428z"/>
- <path fill="#444" d="m271.329 211.862c0.985-2.563-0.256-10.65-1.409-12.508-0.874-1.35-1.23-2.979-1.938-3.2-0.604-0.177-1.166 0.895-1.233 0.998-0.259 0.324 2.751 5.636 3.259 13.39 0.096 1.082 1.115 1.876 1.321 1.32z"/>
- <path fill="#484848" d="m271.235 211.099c0.923-2.377-0.375-10.077-1.296-11.499-0.818-1.229-1.097-2.72-1.781-2.942-0.573-0.174-1.052 0.829-1.134 0.918-0.289 0.309 2.348 5.156 2.996 12.309 0.11 1.058 1.025 1.726 1.215 1.214z"/>
- <path fill="#4c4c4c" d="m271.14 210.336c0.861-2.192-0.493-9.506-1.183-10.49-0.763-1.107-0.96-2.463-1.625-2.684-0.542-0.172-0.936 0.762-1.034 0.836-0.319 0.297 1.945 4.68 2.733 11.229 0.124 1.035 0.936 1.576 1.109 1.109z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m264.822 187.073c-10.224-13.968-23.472-18.504-22.104-14.112 0 0 10.152 5.76 19.08 16.56 1.728 2.088 4.608-0.288 3.024-2.448z"/>
- <path fill="#030303" d="m264.372 186.687c-9.924-13.495-22.894-17.912-21.539-13.7 0.018 0.012 9.901 5.614 18.609 16.071 1.678 2.016 4.467-0.285 2.93-2.371z"/>
- <path fill="#070707" d="m263.922 186.3c-9.624-13.022-22.316-17.319-20.975-13.287 0.036 0.023 9.652 5.467 18.139 15.582 1.628 1.943 4.325-0.283 2.836-2.295z"/>
- <path fill="#0b0b0b" d="m263.472 185.913c-9.324-12.549-21.739-16.726-20.41-12.874 0.053 0.034 9.4 5.32 17.668 15.093 1.578 1.871 4.183-0.28 2.742-2.219z"/>
- <path fill="#0f0f0f" d="m263.022 185.527c-9.024-12.077-21.162-16.134-19.847-12.462 0.071 0.045 9.151 5.174 17.198 14.604 1.529 1.798 4.043-0.278 2.649-2.142z"/>
- <path fill="#131313" d="m262.571 185.14c-8.723-11.603-20.583-15.541-19.28-12.049 0.088 0.056 8.901 5.027 16.728 14.114 1.477 1.726 3.899-0.275 2.552-2.065z"/>
- <path fill="#161616" d="m262.121 184.753c-8.423-11.13-20.006-14.948-18.716-11.636 0.106 0.067 8.651 4.88 16.257 13.625 1.428 1.654 3.759-0.272 2.459-1.989z"/>
- <path fill="#1a1a1a" d="m261.671 184.367c-8.124-10.658-19.428-14.356-18.15-11.224 0.124 0.078 8.399 4.734 15.785 13.136 1.378 1.581 3.617-0.27 2.365-1.912z"/>
- <path fill="#1e1e1e" d="m261.221 183.98c-7.824-10.185-18.851-13.763-17.588-10.811 0.143 0.089 8.151 4.587 15.315 12.647 1.33 1.508 3.477-0.267 2.273-1.836z"/>
- <path fill="#222" d="m260.771 183.593c-7.524-9.711-18.273-13.17-17.022-10.398 0.159 0.1 7.9 4.44 14.844 12.158 1.279 1.436 3.335-0.265 2.178-1.76z"/>
- <path fill="#262626" d="m260.321 183.206c-7.224-9.238-17.695-12.578-16.458-9.985 0.177 0.111 7.65 4.293 14.374 11.668 1.229 1.364 3.193-0.262 2.084-1.683z"/>
- <path fill="#2a2a2a" d="m259.871 182.82c-6.924-8.766-17.118-11.986-15.893-9.573 0.193 0.122 7.398 4.147 13.902 11.179 1.18 1.291 3.053-0.259 1.991-1.606z"/>
- <path fill="#2d2d2d" d="m259.42 182.433c-6.623-8.293-16.539-11.393-15.328-9.16 0.214 0.133 7.15 4 13.434 10.69 1.128 1.219 2.909-0.257 1.894-1.53z"/>
- <path fill="#313131" d="m258.97 182.046c-6.323-7.819-15.963-10.8-14.764-8.747 0.23 0.144 6.899 3.853 12.962 10.201 1.08 1.146 2.769-0.254 1.802-1.454z"/>
- <path fill="#353535" d="m258.52 181.66c-6.023-7.347-15.384-10.208-14.199-8.335 0.248 0.155 6.649 3.707 12.492 9.712 1.028 1.073 2.627-0.252 1.707-1.377z"/>
- <path fill="#393939" d="m258.07 181.273c-5.723-6.874-14.807-9.615-13.634-7.922 0.265 0.166 6.398 3.56 12.021 9.222 0.978 1.002 2.485-0.249 1.613-1.3z"/>
- <path fill="#3d3d3d" d="m257.62 180.886c-5.423-6.401-14.229-9.021-13.07-7.509 0.283 0.177 6.149 3.413 11.552 8.733 0.927 0.929 2.343-0.246 1.518-1.224z"/>
- <path fill="#414141" d="m257.17 180.5c-5.124-5.928-13.65-8.43-12.505-7.097 0.301 0.188 5.898 3.267 11.079 8.244 0.879 0.856 2.203-0.244 1.426-1.147z"/>
- <path fill="#444" d="m256.719 180.113c-4.823-5.455-13.073-7.837-11.94-6.684 0.319 0.199 5.649 3.12 10.609 7.755 0.829 0.784 2.061-0.241 1.331-1.071z"/>
- <path fill="#484848" d="m256.269 179.726c-4.523-4.982-12.495-7.244-11.375-6.271 0.336 0.21 5.397 2.973 10.138 7.266 0.779 0.711 1.92-0.239 1.237-0.995z"/>
- <path fill="#4c4c4c" d="m255.819 179.339c-4.223-4.509-11.918-6.652-10.812-5.859 0.354 0.222 5.148 2.827 9.668 6.777 0.73 0.639 1.779-0.236 1.144-0.918z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m273.03 225.592c0.144 6.265-5.76 22.248-7.992 21.673-2.52-0.576 0.504-5.257 2.809-13.177 0.936-3.312 1.655-11.447 1.943-11.735 0.936-0.936 3.24 1.728 3.24 3.239z"/>
- <path fill="#050505" d="m272.846 226.116c0.103 6.082-5.638 21.594-7.797 21.018-2.422-0.567 0.548-5.146 2.814-12.928 0.899-3.178 1.595-10.947 1.887-11.25 0.914-0.927 3.147 1.527 3.096 3.16z"/>
- <path fill="#0a0a0a" d="m272.662 226.637c0.063 5.902-5.514 20.939-7.601 20.363-2.323-0.558 0.592-5.035 2.82-12.681 0.861-3.041 1.534-10.446 1.83-10.761 0.89-0.917 3.054 1.327 2.951 3.079z"/>
- <path fill="#0f0f0f" d="m272.478 227.159c0.021 5.721-5.392 20.284-7.405 19.711-2.224-0.55 0.635-4.927 2.827-12.434 0.824-2.907 1.473-9.945 1.773-10.273 0.866-0.911 2.959 1.125 2.805 2.996z"/>
- <path fill="#141414" d="m272.294 227.68c-0.02 5.539-5.268 19.63-7.21 19.057-2.125-0.541 0.68-4.816 2.835-12.186 0.786-2.771 1.412-9.445 1.717-9.786 0.84-0.901 2.863 0.924 2.658 2.915z"/>
- <path fill="#191919" d="m272.11 228.202c-0.063 5.359-5.146 18.977-7.014 18.403-2.027-0.532 0.722-4.706 2.841-11.938 0.748-2.637 1.351-8.944 1.659-9.299 0.818-0.893 2.77 0.722 2.514 2.834z"/>
- <path fill="#1e1e1e" d="m271.926 228.723c-0.103 5.179-5.021 18.322-6.818 17.75-1.928-0.523 0.766-4.596 2.848-11.691 0.711-2.5 1.29-8.443 1.603-8.811 0.792-0.885 2.674 0.522 2.367 2.752z"/>
- <path fill="#232323" d="m271.742 229.245c-0.144 4.998-4.9 17.668-6.623 17.096-1.83-0.514 0.811-4.485 2.854-11.442 0.673-2.366 1.229-7.944 1.545-8.325 0.771-0.876 2.583 0.32 2.224 2.671z"/>
- <path fill="#282828" d="m271.558 229.766c-0.186 4.816-4.777 17.013-6.428 16.443-1.731-0.506 0.854-4.377 2.86-11.196 0.636-2.231 1.168-7.443 1.488-7.837 0.749-0.866 2.49 0.119 2.08 2.59z"/>
- <path fill="#2d2d2d" d="m271.374 230.288c-0.226 4.637-4.653 16.359-6.231 15.789-1.632-0.496 0.896-4.266 2.866-10.947 0.6-2.098 1.107-6.943 1.433-7.351 0.722-0.859 2.393-0.081 1.932 2.509z"/>
- <path fill="#333" d="m271.19 230.809c-0.268 4.456-4.531 15.705-6.036 15.136-1.534-0.489 0.94-4.155 2.873-10.7 0.561-1.961 1.046-6.443 1.375-6.863 0.7-0.848 2.3-0.282 1.788 2.427z"/>
- <path fill="#383838" d="m271.006 231.331c-0.308 4.275-4.407 15.051-5.841 14.482-1.435-0.48 0.984-4.046 2.88-10.453 0.524-1.826 0.985-5.941 1.318-6.375 0.676-0.84 2.206-0.483 1.643 2.346z"/>
- <path fill="#3d3d3d" d="m270.822 231.853c-0.35 4.093-4.285 14.396-5.645 13.828-1.338-0.472 1.027-3.937 2.886-10.206 0.485-1.691 0.924-5.441 1.261-5.887 0.653-0.832 2.113-0.684 1.498 2.265z"/>
- <path fill="#424242" d="m270.638 232.374c-0.392 3.914-4.162 13.742-5.45 13.176-1.238-0.463 1.072-3.826 2.893-9.959 0.449-1.555 0.863-4.94 1.204-5.399 0.629-0.824 2.019-0.886 1.353 2.182z"/>
- <path fill="#474747" d="m270.454 232.896c-0.432 3.731-4.039 13.087-5.254 12.521-1.14-0.453 1.115-3.715 2.9-9.711 0.411-1.42 0.802-4.439 1.146-4.912 0.606-0.815 1.925-1.086 1.208 2.102z"/>
- <path fill="#4c4c4c" d="m270.27 233.417c-0.474 3.553-3.916 12.434-5.06 11.869-1.041-0.445 1.159-3.606 2.907-9.463 0.373-1.287 0.741-3.941 1.089-4.427 0.583-0.806 1.832-1.287 1.064 2.021z"/>
- <path fill="#515151" d="m270.086 233.939c-0.514 3.37-3.793 11.778-4.862 11.214-0.942-0.436 1.201-3.496 2.913-9.216 0.336-1.151 0.68-3.438 1.032-3.938 0.558-0.797 1.736-1.489 0.917 1.94z"/>
- <path fill="#565656" d="m269.902 234.461c-0.555 3.188-3.671 11.123-4.667 10.56-0.844-0.429 1.246-3.386 2.919-8.968 0.298-1.016 0.619-2.939 0.976-3.451 0.535-0.788 1.643-1.689 0.772 1.859z"/>
- <path fill="#5b5b5b" d="m269.718 234.982c-0.597 3.009-3.548 10.47-4.472 9.907-0.745-0.42 1.29-3.275 2.926-8.721 0.262-0.881 0.559-2.438 0.919-2.963 0.511-0.781 1.549-1.89 0.627 1.777z"/>
- <path fill="#606060" d="m269.534 235.504c-0.638 2.828-3.425 9.814-4.276 9.252-0.646-0.409 1.333-3.166 2.933-8.473 0.224-0.746 0.497-1.938 0.862-2.476 0.487-0.769 1.454-2.09 0.481 1.697z"/>
- <path fill="#666" d="m269.35 236.025c-0.68 2.647-3.303 9.161-4.081 8.599-0.548-0.4 1.377-3.056 2.938-8.225 0.187-0.611 0.437-1.438 0.806-1.988 0.464-0.763 1.361-2.293 0.337 1.614z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m251.07 187.865c-1.537 1.622-2.903 9.991 0.938 12.893 3.844 2.818 10.59-2.391 10.59-5.379-0.086-6.746-9.991-9.222-11.528-7.514z"/>
- <path fill="#010101" d="m251.207 188.006c-1.559 1.611-2.876 9.823 0.857 12.667 3.731 2.764 10.349-2.273 10.384-5.279-0.047-6.576-9.681-9.083-11.241-7.388z"/>
- <path fill="#030303" d="m251.344 188.146c-1.582 1.601-2.85 9.653 0.774 12.438 3.62 2.709 10.109-2.154 10.178-5.177-0.007-6.404-9.37-8.943-10.952-7.261z"/>
- <path fill="#050505" d="m251.481 188.287c-1.604 1.589-2.823 9.484 0.691 12.211 3.511 2.653 9.869-2.037 9.975-5.078 0.031-6.232-9.061-8.802-10.666-7.133z"/>
- <path fill="#070707" d="m251.617 188.427c-1.626 1.579-2.795 9.316 0.611 11.984 3.397 2.6 9.629-1.918 9.768-4.976 0.071-6.062-8.751-8.664-10.379-7.008z"/>
- <path fill="#090909" d="m251.754 188.567c-1.648 1.568-2.768 9.146 0.529 11.758 3.287 2.543 9.389-1.802 9.563-4.875 0.109-5.892-8.441-8.525-10.092-6.883z"/>
- <path fill="#0b0b0b" d="m251.891 188.708c-1.671 1.557-2.741 8.978 0.445 11.529 3.177 2.489 9.15-1.683 9.358-4.774 0.15-5.72-8.13-8.385-9.803-6.755z"/>
- <path fill="#0d0d0d" d="m252.028 188.848c-1.694 1.546-2.715 8.809 0.364 11.302 3.064 2.435 8.908-1.565 9.152-4.673 0.189-5.549-7.82-8.245-9.516-6.629z"/>
- <path fill="#0f0f0f" d="m252.165 188.989c-1.716 1.535-2.688 8.64 0.282 11.074 2.953 2.38 8.669-1.447 8.948-4.572 0.226-5.378-7.512-8.106-9.23-6.502z"/>
- <path fill="#111" d="m252.301 189.129c-1.737 1.524-2.659 8.471 0.2 10.847 2.844 2.325 8.431-1.33 8.743-4.471 0.266-5.207-7.201-7.966-8.943-6.376z"/>
- <path fill="#131313" d="m252.438 189.269c-1.76 1.514-2.633 8.304 0.118 10.619 2.73 2.271 8.189-1.212 8.538-4.369 0.305-5.036-6.892-7.827-8.656-6.25z"/>
- <path fill="#151515" d="m252.575 189.41c-1.783 1.503-2.606 8.133 0.036 10.391 2.62 2.216 7.949-1.094 8.332-4.268 0.344-4.865-6.581-7.687-8.368-6.123z"/>
- <path fill="#161616" d="m252.712 189.55c-1.805 1.492-2.58 7.965-0.046 10.164 2.508 2.162 7.709-0.975 8.127-4.167 0.383-4.694-6.272-7.548-8.081-5.997z"/>
- <path fill="#181818" d="m252.849 189.691c-1.828 1.481-2.554 7.796-0.129 9.937 2.397 2.105 7.47-0.857 7.922-4.066 0.423-4.524-5.961-7.409-7.793-5.871z"/>
- <path fill="#1a1a1a" d="m252.985 189.831c-1.85 1.47-2.525 7.626-0.21 9.708 2.286 2.053 7.229-0.74 7.717-3.964 0.461-4.352-5.652-7.269-7.507-5.744z"/>
- <path fill="#1c1c1c" d="m253.122 189.971c-1.872 1.46-2.499 7.459-0.292 9.482 2.175 1.996 6.989-0.623 7.511-3.865 0.501-4.18-5.341-7.128-7.219-5.617z"/>
- <path fill="#1e1e1e" d="m253.259 190.112c-1.895 1.448-2.472 7.289-0.375 9.254 2.064 1.942 6.75-0.504 7.308-3.763 0.539-4.01-5.033-6.99-6.933-5.491z"/>
- <path fill="#202020" d="m253.396 190.252c-1.917 1.438-2.445 7.122-0.457 9.027 1.953 1.888 6.51-0.386 7.102-3.662 0.578-3.839-4.722-6.85-6.645-5.365z"/>
- <path fill="#222" d="m253.533 190.393c-1.939 1.426-2.418 6.951-0.539 8.799 1.841 1.832 6.271-0.268 6.896-3.561 0.618-3.668-4.412-6.711-6.357-5.238z"/>
- <path fill="#242424" d="m253.669 190.533c-1.961 1.416-2.391 6.783-0.621 8.572 1.731 1.776 6.03-0.149 6.692-3.46 0.657-3.497-4.102-6.571-6.071-5.112z"/>
- <path fill="#262626" d="m253.806 190.673c-1.984 1.405-2.364 6.615-0.703 8.344 1.619 1.724 5.79-0.032 6.485-3.358 0.697-3.326-3.791-6.432-5.782-4.986z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m250.71 256.698c1.513 1.512 2.809-2.232 4.32-3.457 1.512-1.224 3.96-3.888 8.856-3.888s4.535-0.144 4.319-2.017c-0.144-1.799-1.584-1.655-5.903-1.008-4.32 0.576-7.2 2.809-8.929 4.824-1.654 1.945-3.527 4.681-2.663 5.546z"/>
- <path fill="#050505" d="m251.043 256.331c1.459 1.449 2.703-2.121 4.205-3.308 1.501-1.187 3.931-3.731 8.64-3.731 4.71-0.002 4.415-0.129 4.209-1.94-0.139-1.743-1.543-1.593-5.749-0.979-4.207 0.543-7.029 2.703-8.712 4.648-1.616 1.877-3.438 4.474-2.593 5.31z"/>
- <path fill="#0a0a0a" d="m251.376 255.961c1.406 1.389 2.6-2.008 4.089-3.156 1.491-1.148 3.901-3.576 8.425-3.577 4.521-0.001 4.293-0.11 4.096-1.862-0.132-1.688-1.501-1.531-5.594-0.951-4.093 0.51-6.857 2.596-8.495 4.471-1.575 1.812-3.348 4.271-2.521 5.075z"/>
- <path fill="#0f0f0f" d="m251.709 255.594c1.354 1.326 2.494-1.895 3.975-3.008 1.479-1.111 3.871-3.42 8.207-3.422s4.171-0.094 3.984-1.785c-0.126-1.631-1.46-1.467-5.438-0.924-3.979 0.479-6.687 2.492-8.28 4.297-1.533 1.747-3.257 4.066-2.448 4.842z"/>
- <path fill="#141414" d="m252.042 255.226c1.302 1.265 2.39-1.783 3.858-2.856 1.47-1.076 3.842-3.266 7.991-3.268s4.05-0.077 3.873-1.709c-0.119-1.575-1.419-1.404-5.284-0.895-3.865 0.444-6.515 2.385-8.063 4.121-1.49 1.678-3.165 3.861-2.375 4.607z"/>
- <path fill="#191919" d="m252.374 254.859c1.249 1.202 2.285-1.671 3.744-2.708 1.458-1.037 3.813-3.109 7.774-3.111 3.963-0.004 3.929-0.061 3.761-1.633-0.113-1.519-1.377-1.341-5.128-0.867-3.751 0.414-6.344 2.279-7.847 3.945-1.449 1.613-3.075 3.656-2.304 4.374z"/>
- <path fill="#1e1e1e" d="m252.707 254.491c1.196 1.141 2.182-1.559 3.628-2.558 1.448-1 3.783-2.954 7.56-2.957 3.775-0.003 3.806-0.043 3.648-1.556-0.106-1.461-1.336-1.277-4.974-0.838-3.637 0.379-6.172 2.174-7.63 3.77-1.408 1.546-2.984 3.451-2.232 4.139z"/>
- <path fill="#232323" d="m253.04 254.124c1.144 1.078 2.076-1.447 3.514-2.41 1.437-0.961 3.753-2.797 7.342-2.799 3.589-0.004 3.685-0.027 3.537-1.48-0.101-1.405-1.294-1.215-4.818-0.811-3.524 0.349-6.001 2.068-7.415 3.594-1.367 1.48-2.894 3.245-2.16 3.906z"/>
- <path fill="#282828" d="m253.373 253.754c1.09 1.018 1.972-1.334 3.398-2.258 1.426-0.926 3.723-2.642 7.125-2.646 3.402-0.005 3.563-0.011 3.426-1.403-0.095-1.349-1.253-1.15-4.664-0.781-3.409 0.314-5.829 1.961-7.198 3.418-1.325 1.415-2.803 3.041-2.087 3.67z"/>
- <path fill="#2d2d2d" d="m253.706 253.388c1.038 0.954 1.866-1.222 3.282-2.11 1.416-0.887 3.694-2.486 6.909-2.49 3.217-0.004 3.441 0.008 3.313-1.326-0.088-1.293-1.212-1.088-4.508-0.754-3.296 0.283-5.658 1.857-6.981 3.244-1.284 1.345-2.712 2.836-2.015 3.436z"/>
- <path fill="#333" d="m254.039 253.02c0.985 0.893 1.762-1.109 3.167-1.96s3.664-2.33 6.693-2.335c3.029-0.006 3.32 0.023 3.202-1.249-0.082-1.237-1.171-1.024-4.354-0.726-3.182 0.25-5.485 1.75-6.765 3.066-1.243 1.282-2.622 2.634-1.943 3.204z"/>
- <path fill="#383838" d="m254.372 252.652c0.933 0.831 1.657-0.998 3.051-1.81 1.396-0.813 3.636-2.174 6.478-2.18 2.843-0.006 3.199 0.039 3.09-1.172-0.076-1.181-1.129-0.963-4.198-0.697-3.068 0.217-5.314 1.644-6.55 2.891-1.202 1.214-2.531 2.427-1.871 2.968z"/>
- <path fill="#3d3d3d" d="m254.704 252.284c0.88 0.771 1.553-0.885 2.938-1.66 1.383-0.775 3.604-2.019 6.26-2.024 2.656-0.007 3.078 0.058 2.979-1.095-0.069-1.125-1.088-0.899-4.044-0.67-2.954 0.185-5.144 1.539-6.333 2.715-1.16 1.148-2.441 2.222-1.8 2.734z"/>
- <path fill="#424242" d="m255.037 251.917c0.827 0.707 1.448-0.773 2.821-1.51 1.373-0.738 3.576-1.863 6.044-1.871 2.47-0.007 2.956 0.074 2.867-1.018-0.063-1.068-1.046-0.836-3.889-0.641-2.841 0.151-4.973 1.433-6.116 2.539-1.119 1.083-2.35 2.018-1.727 2.501z"/>
- <path fill="#474747" d="m255.37 251.549c0.774 0.645 1.344-0.661 2.706-1.362 1.362-0.7 3.545-1.706 5.828-1.713 2.283-0.009 2.834 0.09 2.754-0.942-0.057-1.012-1.005-0.773-3.733-0.613-2.727 0.119-4.801 1.328-5.899 2.365-1.078 1.013-2.26 1.81-1.656 2.265z"/>
- <path fill="#4c4c4c" d="m255.703 251.181c0.721 0.584 1.239-0.55 2.59-1.212 1.353-0.663 3.517-1.551 5.612-1.559 2.096-0.009 2.713 0.107 2.643-0.865-0.051-0.955-0.964-0.709-3.577-0.584-2.613 0.086-4.631 1.222-5.686 2.188-1.035 0.949-2.168 1.607-1.582 2.032z"/>
- <path fill="#515151" d="m256.036 250.813c0.669 0.521 1.134-0.436 2.476-1.063 1.341-0.625 3.485-1.395 5.395-1.402 1.91-0.01 2.591 0.124 2.531-0.789-0.044-0.898-0.922-0.646-3.423-0.557-2.499 0.055-4.458 1.117-5.469 2.014-0.994 0.882-2.077 1.402-1.51 1.797z"/>
- <path fill="#565656" d="m256.369 250.446c0.616 0.459 1.029-0.324 2.36-0.912 1.33-0.589 3.456-1.24 5.178-1.248 1.723-0.01 2.47 0.141 2.42-0.713-0.039-0.842-0.881-0.582-3.268-0.527-2.387 0.021-4.287 1.01-5.252 1.836-0.953 0.816-1.987 1.199-1.438 1.564z"/>
- <path fill="#5b5b5b" d="m256.701 250.079c0.564 0.397 0.926-0.213 2.245-0.764s3.427-1.084 4.963-1.093c1.536-0.011 2.348 0.157 2.307-0.636-0.031-0.785-0.839-0.52-3.112-0.5-2.271-0.01-4.116 0.906-5.035 1.662-0.913 0.751-1.898 0.993-1.368 1.331z"/>
- <path fill="#606060" d="m257.034 249.709c0.511 0.336 0.821-0.1 2.13-0.612 1.309-0.515 3.397-0.929 4.746-0.938 1.351-0.01 2.227 0.176 2.196-0.558-0.026-0.729-0.799-0.457-2.958-0.472-2.158-0.043-3.945 0.799-4.82 1.486-0.87 0.682-1.805 0.788-1.294 1.094z"/>
- <path fill="#666" d="m257.367 249.342c0.458 0.273 0.716 0.012 2.014-0.465 1.299-0.476 3.368-0.771 4.53-0.781 1.163-0.012 2.105 0.191 2.084-0.482-0.02-0.673-0.757-0.393-2.803-0.443-2.044-0.076-3.773 0.693-4.604 1.311-0.828 0.616-1.714 0.582-1.221 0.86z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m270.222 247.265c0 2.304 4.68 3.096 9.144 3.743 4.392 0.648 7.92 1.513 8.136 6.121 0.216 4.535-0.936 7.775 1.08 7.416 4.32-0.793 5.904-5.473 5.832-7.633 0-2.16-3.168-6.047-8.855-8.207-4.177-1.584-7.2-2.305-10.872-2.449-4.897-0.214-4.465 1.009-4.465 1.009z"/>
- <path fill="#030303" d="m270.348 247.304c0.012 2.239 4.643 2.97 9.049 3.639 4.352 0.675 7.75 1.511 8.11 6.002 0.345 4.415-0.854 7.515 1.136 7.188 4.145-0.739 5.688-5.2 5.607-7.332-0.015-2.151-3.118-5.91-8.733-8.038-4.129-1.563-7.11-2.298-10.74-2.452-4.754-0.217-4.438 0.952-4.429 0.993z"/>
- <path fill="#070707" d="m270.474 247.342c0.023 2.174 4.605 2.845 8.953 3.533 4.312 0.701 7.58 1.508 8.087 5.885 0.471 4.295-0.771 7.252 1.189 6.963 3.97-0.689 5.472-4.93 5.384-7.033-0.028-2.145-3.068-5.773-8.61-7.87-4.082-1.543-7.022-2.291-10.609-2.456-4.612-0.218-4.412 0.896-4.394 0.978z"/>
- <path fill="#0b0b0b" d="m270.6 247.379c0.035 2.109 4.568 2.721 8.857 3.431 4.271 0.728 7.411 1.506 8.063 5.767 0.599 4.174-0.689 6.988 1.245 6.735 3.795-0.638 5.257-4.66 5.159-6.733-0.044-2.137-3.019-5.636-8.488-7.701-4.035-1.522-6.933-2.285-10.478-2.459-4.469-0.219-4.384 0.837-4.358 0.96z"/>
- <path fill="#0f0f0f" d="m270.726 247.418c0.047 2.043 4.531 2.595 8.762 3.324 4.232 0.754 7.242 1.504 8.039 5.649 0.725 4.052-0.608 6.728 1.299 6.509 3.621-0.586 5.041-4.389 4.937-6.436-0.06-2.127-2.971-5.496-8.367-7.53-3.988-1.502-6.842-2.278-10.346-2.464-4.328-0.22-4.359 0.784-4.324 0.948z"/>
- <path fill="#131313" d="m270.852 247.458c0.059 1.978 4.495 2.469 8.667 3.219 4.19 0.781 7.071 1.502 8.014 5.531 0.854 3.932-0.526 6.465 1.354 6.283 3.445-0.535 4.824-4.119 4.712-6.137-0.074-2.119-2.92-5.359-8.245-7.361-3.941-1.482-6.753-2.271-10.213-2.469-4.186-0.221-4.333 0.726-4.289 0.934z"/>
- <path fill="#161616" d="m270.978 247.495c0.07 1.914 4.458 2.344 8.57 3.115 4.151 0.807 6.903 1.5 7.99 5.413 0.98 3.812-0.443 6.202 1.409 6.056 3.271-0.482 4.609-3.848 4.488-5.836-0.088-2.111-2.871-5.222-8.123-7.193-3.894-1.461-6.663-2.264-10.081-2.471-4.043-0.223-4.306 0.67-4.253 0.916z"/>
- <path fill="#1a1a1a" d="m271.104 247.534c0.082 1.848 4.422 2.219 8.476 3.01 4.111 0.832 6.734 1.498 7.965 5.295 1.108 3.69-0.36 5.94 1.464 5.83 3.097-0.433 4.394-3.578 4.265-5.537-0.104-2.104-2.821-5.084-8-7.023-3.848-1.441-6.575-2.26-9.949-2.477-3.905-0.223-4.283 0.613-4.221 0.902z"/>
- <path fill="#1e1e1e" d="m271.23 247.573c0.094 1.781 4.385 2.092 8.381 2.904 4.07 0.859 6.563 1.495 7.939 5.178 1.236 3.568-0.278 5.678 1.52 5.602 2.921-0.381 4.177-3.305 4.04-5.237-0.118-2.097-2.771-4.946-7.878-6.854-3.8-1.42-6.485-2.252-9.817-2.479-3.762-0.226-4.256 0.556-4.185 0.886z"/>
- <path fill="#222" d="m271.356 247.61c0.105 1.717 4.348 1.969 8.285 2.801 4.029 0.885 6.395 1.493 7.916 5.059 1.362 3.449-0.197 5.416 1.573 5.377 2.746-0.329 3.962-3.036 3.816-4.939-0.133-2.087-2.722-4.808-7.756-6.684-3.753-1.4-6.396-2.247-9.686-2.484-3.618-0.227-4.227 0.499-4.148 0.87z"/>
- <path fill="#262626" d="m271.482 247.648c0.118 1.651 4.311 1.843 8.189 2.694 3.99 0.914 6.226 1.492 7.892 4.943 1.491 3.328-0.115 5.152 1.629 5.149 2.571-0.278 3.746-2.765 3.592-4.64-0.146-2.08-2.672-4.672-7.634-6.516-3.705-1.38-6.306-2.24-9.553-2.488-3.478-0.225-4.203 0.446-4.115 0.858z"/>
- <path fill="#2a2a2a" d="m271.608 247.687c0.129 1.587 4.273 1.716 8.094 2.59 3.95 0.938 6.056 1.489 7.867 4.825 1.618 3.206-0.033 4.891 1.684 4.922 2.396-0.227 3.53-2.494 3.368-4.34-0.162-2.072-2.623-4.534-7.512-6.348-3.658-1.358-6.216-2.232-9.421-2.492-3.336-0.226-4.177 0.39-4.08 0.843z"/>
- <path fill="#2d2d2d" d="m271.734 247.725c0.141 1.521 4.237 1.591 7.999 2.484 3.909 0.967 5.886 1.488 7.842 4.707 1.746 3.086 0.05 4.629 1.739 4.697 2.221-0.176 3.313-2.225 3.144-4.041-0.177-2.064-2.572-4.396-7.389-6.178-3.612-1.339-6.128-2.227-9.29-2.497-3.194-0.227-4.151 0.334-4.045 0.828z"/>
- <path fill="#313131" d="m271.86 247.763c0.153 1.456 4.2 1.466 7.903 2.381 3.869 0.991 5.717 1.485 7.817 4.589 1.873 2.965 0.132 4.365 1.794 4.469 2.046-0.123 3.099-1.953 2.92-3.742-0.191-2.055-2.523-4.258-7.267-6.008-3.565-1.318-6.038-2.22-9.158-2.5-3.051-0.229-4.124 0.276-4.009 0.811z"/>
- <path fill="#353535" d="m271.986 247.801c0.165 1.392 4.163 1.341 7.808 2.275 3.829 1.018 5.547 1.483 7.794 4.473 2 2.843 0.213 4.103 1.848 4.242 1.873-0.074 2.883-1.683 2.696-3.443-0.206-2.047-2.474-4.12-7.145-5.838-3.517-1.299-5.948-2.215-9.026-2.506-2.91-0.229-4.099 0.221-3.975 0.797z"/>
- <path fill="#393939" d="m272.112 247.84c0.176 1.326 4.126 1.215 7.712 2.17 3.789 1.045 5.378 1.482 7.771 4.354 2.127 2.723 0.295 3.842 1.901 4.016 1.698-0.021 2.667-1.412 2.474-3.144-0.222-2.038-2.426-3.981-7.023-5.669-3.47-1.277-5.859-2.208-8.894-2.509-2.769-0.231-4.074 0.164-3.941 0.782z"/>
- <path fill="#3d3d3d" d="m272.238 247.877c0.188 1.262 4.089 1.09 7.617 2.066 3.749 1.071 5.208 1.479 7.745 4.236 2.255 2.602 0.377 3.578 1.957 3.789 1.522 0.029 2.451-1.141 2.249-2.844-0.236-2.033-2.375-3.846-6.901-5.5-3.423-1.258-5.769-2.203-8.762-2.514-2.626-0.231-4.046 0.109-3.905 0.767z"/>
- <path fill="#414141" d="m272.364 247.917c0.2 1.195 4.052 0.965 7.522 1.961 3.708 1.098 5.037 1.477 7.72 4.119 2.383 2.479 0.46 3.315 2.012 3.562 1.348 0.081 2.236-0.87 2.025-2.545-0.251-2.022-2.325-3.707-6.778-5.331-3.377-1.237-5.681-2.195-8.631-2.518-2.485-0.233-4.02 0.05-3.87 0.752z"/>
- <path fill="#444" d="m272.49 247.956c0.212 1.129 4.015 0.838 7.426 1.855 3.668 1.124 4.869 1.475 7.696 4 2.51 2.359 0.542 3.055 2.067 3.336 1.173 0.133 2.02-0.6 1.801-2.246-0.266-2.016-2.276-3.568-6.656-5.16-3.329-1.218-5.591-2.189-8.499-2.521-2.343-0.235-3.994-0.007-3.835 0.736z"/>
- <path fill="#484848" d="m272.616 247.993c0.223 1.065 3.979 0.715 7.331 1.752 3.628 1.15 4.699 1.473 7.671 3.883 2.638 2.238 0.624 2.791 2.122 3.108 0.998 0.185 1.804-0.329 1.577-1.946-0.28-2.008-2.227-3.432-6.534-4.992-3.282-1.196-5.501-2.182-8.367-2.525-2.201-0.235-3.968-0.064-3.8 0.72z"/>
- <path fill="#4c4c4c" d="m272.742 248.032c0.235 1 3.941 0.588 7.235 1.645 3.588 1.178 4.529 1.472 7.646 3.766 2.766 2.118 0.706 2.529 2.177 2.883 0.823 0.235 1.589-0.059 1.354-1.648-0.295-1.998-2.177-3.293-6.412-4.822-3.235-1.176-5.412-2.176-8.235-2.529-2.059-0.239-3.942-0.119-3.765 0.705z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#4c4c4c" d="m287.565 252.854c1.646 1 1.353 2.059 2.412 2.766 0.528 0.352 1.412 0.352 0.882-1-0.706-1.588-1.294-2.472-4.941-3.943-2.353-0.941-1.882 0.059 1.647 2.177z"/>
- <path fill="#505050" d="m287.609 252.868c1.605 0.975 1.32 2.008 2.353 2.696 0.517 0.343 1.377 0.343 0.86-0.976-0.689-1.549-1.262-2.41-4.82-3.846-2.295-0.917-1.836 0.059 1.607 2.126z"/>
- <path fill="#545454" d="m287.652 252.879c1.567 0.951 1.287 1.957 2.294 2.629 0.503 0.334 1.343 0.334 0.839-0.951-0.671-1.51-1.23-2.35-4.699-3.749-2.238-0.893-1.79 0.058 1.566 2.071z"/>
- <path fill="#575757" d="m287.696 252.891c1.526 0.926 1.254 1.908 2.235 2.563 0.489 0.325 1.308 0.325 0.816-0.928-0.653-1.471-1.199-2.289-4.578-3.652-2.179-0.872-1.743 0.055 1.527 2.017z"/>
- <path fill="#5b5b5b" d="m287.74 252.903c1.485 0.902 1.22 1.857 2.175 2.494 0.479 0.318 1.274 0.318 0.796-0.902-0.637-1.432-1.167-2.229-4.457-3.556-2.122-0.849-1.697 0.054 1.486 1.964z"/>
- <path fill="#5f5f5f" d="m287.783 252.915c1.446 0.879 1.188 1.808 2.117 2.426 0.464 0.31 1.239 0.31 0.773-0.877-0.619-1.394-1.136-2.168-4.336-3.459-2.064-0.826-1.65 0.052 1.446 1.91z"/>
- <path fill="#636363" d="m287.827 252.926c1.405 0.854 1.154 1.758 2.057 2.359 0.452 0.301 1.205 0.301 0.754-0.853-0.603-1.354-1.104-2.108-4.216-3.363-2.007-0.801-1.605 0.053 1.405 1.857z"/>
- <path fill="#676767" d="m287.871 252.94c1.364 0.828 1.121 1.705 1.998 2.29 0.438 0.292 1.17 0.292 0.731-0.828-0.585-1.315-1.072-2.047-4.095-3.267-1.948-0.779-1.558 0.05 1.366 1.805z"/>
- <path fill="#6b6b6b" d="m287.914 252.952c1.325 0.805 1.088 1.655 1.94 2.223 0.425 0.283 1.135 0.283 0.709-0.803-0.568-1.277-1.041-1.988-3.974-3.17-1.891-0.757-1.512 0.047 1.325 1.75z"/>
- <path fill="#6e6e6e" d="m287.958 252.963c1.284 0.779 1.056 1.605 1.88 2.156 0.413 0.274 1.102 0.274 0.688-0.779-0.551-1.238-1.009-1.926-3.853-3.073-1.833-0.733-1.466 0.046 1.285 1.696z"/>
- <path fill="#727272" d="m288.002 252.976c1.243 0.755 1.021 1.554 1.821 2.087 0.399 0.266 1.066 0.266 0.666-0.755-0.533-1.199-0.977-1.865-3.731-2.976-1.776-0.71-1.421 0.045 1.244 1.644z"/>
- <path fill="#767676" d="m288.045 252.989c1.203 0.73 0.989 1.504 1.763 2.02 0.387 0.257 1.031 0.257 0.645-0.731-0.516-1.159-0.946-1.805-3.61-2.879-1.72-0.688-1.376 0.042 1.202 1.59z"/>
- <path fill="#7a7a7a" d="m288.089 253c1.163 0.705 0.955 1.453 1.703 1.951 0.373 0.25 0.997 0.25 0.623-0.705-0.499-1.121-0.914-1.744-3.489-2.783-1.661-0.664-1.329 0.041 1.163 1.537z"/>
- <path fill="#7e7e7e" d="m288.133 253.012c1.122 0.682 0.923 1.404 1.644 1.885 0.361 0.24 0.962 0.24 0.602-0.682-0.481-1.082-0.882-1.684-3.367-2.687-1.605-0.64-1.285 0.041 1.121 1.484z"/>
- <path fill="#828282" d="m288.176 253.025c1.082 0.657 0.89 1.353 1.586 1.815 0.348 0.232 0.927 0.232 0.578-0.656-0.463-1.043-0.85-1.623-3.245-2.59-1.547-0.618-1.237 0.039 1.081 1.431z"/>
- <path fill="#858585" d="m288.22 253.038c1.042 0.631 0.855 1.301 1.524 1.748 0.335 0.223 0.894 0.223 0.559-0.633-0.446-1.005-0.818-1.563-3.125-2.492-1.488-0.596-1.19 0.037 1.042 1.377z"/>
- <path fill="#898989" d="m288.264 253.049c1.001 0.607 0.821 1.252 1.466 1.681 0.322 0.214 0.857 0.214 0.536-0.608-0.43-0.965-0.786-1.502-3.004-2.396-1.43-0.573-1.144 0.034 1.002 1.323z"/>
- <path fill="#8d8d8d" d="m288.307 253.061c0.961 0.584 0.79 1.201 1.407 1.613 0.309 0.205 0.823 0.205 0.515-0.584-0.412-0.926-0.755-1.441-2.883-2.299-1.373-0.548-1.098 0.034 0.961 1.27z"/>
- <path fill="#919191" d="m288.351 253.073c0.921 0.559 0.756 1.151 1.348 1.547 0.296 0.196 0.789 0.196 0.493-0.56-0.395-0.888-0.723-1.381-2.762-2.204-1.315-0.525-1.052 0.033 0.921 1.217z"/>
- <path fill="#959595" d="m288.395 253.084c0.88 0.535 0.723 1.102 1.289 1.479 0.282 0.189 0.754 0.189 0.471-0.534-0.377-0.849-0.691-1.321-2.641-2.106-1.257-0.505-1.006 0.031 0.881 1.161z"/>
- <path fill="#999" d="m288.438 253.097c0.84 0.51 0.689 1.05 1.229 1.409 0.271 0.181 0.721 0.181 0.45-0.51-0.36-0.81-0.66-1.26-2.52-2.01-1.199-0.48-0.959 0.031 0.841 1.111z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path d="m222.275 107.427c-0.738 0.902 0.574 8.365 5.412 13.285 4.839 4.838 7.791 4.838 9.759 2.706 3.771-4.018 0.738-7.791-1.558-10.415-2.297-2.624-5.248-1.722-7.955-4.346-2.706-2.624-4.592-2.46-5.658-1.23z"/>
- <path fill="#050505" d="m222.345 107.494c-0.732 0.895 0.569 8.3 5.369 13.182 4.803 4.801 7.731 4.801 9.685 2.685 3.742-3.987 0.731-7.73-1.546-10.334-2.278-2.604-5.208-1.709-7.894-4.312-2.684-2.604-4.556-2.441-5.614-1.221z"/>
- <path fill="#0a0a0a" d="m222.416 107.561c-0.727 0.888 0.565 8.235 5.328 13.079 4.763 4.763 7.67 4.763 9.607 2.664 3.713-3.956 0.727-7.67-1.534-10.253-2.26-2.584-5.166-1.696-7.831-4.279-2.664-2.583-4.521-2.422-5.57-1.211z"/>
- <path fill="#0f0f0f" d="m222.486 107.628c-0.721 0.881 0.561 8.17 5.286 12.976 4.726 4.725 7.608 4.725 9.532 2.642 3.684-3.924 0.72-7.609-1.522-10.172-2.243-2.563-5.126-1.682-7.77-4.244-2.643-2.563-4.485-2.403-5.526-1.202z"/>
- <path fill="#141414" d="m222.556 107.695c-0.716 0.874 0.557 8.105 5.243 12.872 4.689 4.688 7.55 4.688 9.456 2.622 3.655-3.893 0.716-7.549-1.51-10.091-2.224-2.543-5.085-1.669-7.707-4.211-2.621-2.543-4.449-2.384-5.482-1.192z"/>
- <path fill="#191919" d="m222.627 107.762c-0.71 0.867 0.552 8.04 5.202 12.769 4.65 4.65 7.488 4.65 9.379 2.601 3.626-3.862 0.71-7.489-1.497-10.011s-5.044-1.655-7.646-4.177-4.414-2.364-5.438-1.182z"/>
- <path fill="#1e1e1e" d="m222.697 107.829c-0.704 0.86 0.547 7.975 5.16 12.666 4.613 4.612 7.428 4.612 9.304 2.579 3.596-3.83 0.703-7.427-1.486-9.929-2.188-2.502-5.003-1.642-7.584-4.143-2.579-2.502-4.378-2.346-5.394-1.173z"/>
- <path fill="#232323" d="m222.767 107.896c-0.697 0.853 0.543 7.91 5.117 12.562 4.576 4.575 7.367 4.575 9.229 2.559 3.567-3.8 0.698-7.367-1.473-9.848-2.171-2.482-4.963-1.629-7.522-4.11s-4.343-2.326-5.351-1.163z"/>
- <path fill="#282828" d="m222.838 107.963c-0.691 0.846 0.538 7.845 5.076 12.459 4.537 4.537 7.307 4.537 9.152 2.538 3.537-3.769 0.691-7.307-1.461-9.768-2.154-2.461-4.922-1.615-7.461-4.076-2.538-2.461-4.307-2.307-5.306-1.153z"/>
- <path fill="#2d2d2d" d="m222.908 108.03c-0.686 0.839 0.534 7.78 5.034 12.355 4.5 4.499 7.246 4.499 9.076 2.516 3.509-3.737 0.686-7.246-1.449-9.686-2.135-2.441-4.881-1.602-7.399-4.042-2.516-2.44-4.271-2.287-5.262-1.143z"/>
- <path fill="#333" d="m222.978 108.096c-0.681 0.832 0.529 7.715 4.992 12.253 4.463 4.462 7.186 4.462 9.001 2.496 3.479-3.706 0.68-7.186-1.438-9.605-2.118-2.42-4.841-1.588-7.337-4.008s-4.235-2.27-5.218-1.136z"/>
- <path fill="#383838" d="m223.048 108.163c-0.674 0.825 0.526 7.65 4.95 12.15 4.425 4.425 7.125 4.425 8.925 2.475 3.45-3.675 0.676-7.125-1.425-9.525-2.099-2.4-4.8-1.575-7.274-3.975-2.475-2.399-4.201-2.25-5.176-1.125z"/>
- <path fill="#3d3d3d" d="m223.119 108.23c-0.669 0.818 0.521 7.585 4.908 12.047 4.387 4.387 7.063 4.387 8.849 2.453 3.42-3.643 0.669-7.064-1.413-9.443-2.082-2.38-4.759-1.562-7.214-3.941-2.453-2.38-4.164-2.231-5.13-1.116z"/>
- <path fill="#424242" d="m223.189 108.297c-0.663 0.811 0.516 7.52 4.866 11.944 4.35 4.349 7.004 4.349 8.772 2.432 3.392-3.612 0.663-7.004-1.4-9.363-2.064-2.359-4.719-1.548-7.151-3.907-2.433-2.359-4.129-2.212-5.087-1.106z"/>
- <path fill="#474747" d="m223.259 108.364c-0.656 0.804 0.513 7.455 4.824 11.84 4.313 4.312 6.944 4.312 8.697 2.412 3.362-3.582 0.658-6.944-1.388-9.282-2.046-2.339-4.679-1.535-7.09-3.874-2.411-2.338-4.093-2.192-5.043-1.096z"/>
- <path fill="#4c4c4c" d="m223.33 108.431c-0.651 0.797 0.507 7.39 4.782 11.737 4.274 4.274 6.882 4.274 8.621 2.39 3.332-3.55 0.651-6.883-1.377-9.201s-4.636-1.521-7.028-3.839c-2.39-2.318-4.057-2.174-4.998-1.087z"/>
- <path fill="#515151" d="m223.4 108.498c-0.646 0.79 0.503 7.325 4.74 11.634 4.236 4.236 6.821 4.236 8.545 2.369 3.304-3.519 0.646-6.822-1.364-9.12s-4.596-1.508-6.966-3.806c-2.369-2.298-4.022-2.154-4.955-1.077z"/>
- <path fill="#565656" d="m223.47 108.565c-0.641 0.783 0.499 7.26 4.697 11.53 4.199 4.199 6.763 4.199 8.471 2.349 3.273-3.488 0.64-6.762-1.353-9.039-1.993-2.278-4.556-1.495-6.905-3.773-2.347-2.277-3.985-2.135-4.91-1.067z"/>
- <path fill="#5b5b5b" d="m223.541 108.632c-0.635 0.776 0.493 7.195 4.656 11.427 4.161 4.161 6.701 4.161 8.393 2.327 3.245-3.456 0.636-6.701-1.34-8.958-1.975-2.257-4.514-1.48-6.843-3.738-2.327-2.257-3.95-2.116-4.866-1.058z"/>
- <path fill="#606060" d="m223.611 108.699c-0.629 0.769 0.489 7.13 4.614 11.324 4.124 4.123 6.64 4.123 8.317 2.306 3.215-3.425 0.628-6.641-1.328-8.877-1.957-2.237-4.474-1.468-6.78-3.705-2.306-2.236-3.915-2.097-4.823-1.048z"/>
- <path fill="#666" d="m223.681 108.765c-0.623 0.762 0.484 7.065 4.571 11.221 4.086 4.086 6.58 4.086 8.242 2.285 3.187-3.394 0.623-6.58-1.315-8.796-1.939-2.217-4.434-1.455-6.72-3.671-2.284-2.216-3.878-2.078-4.778-1.039z"/>
- </g>
- <g transform="translate(-12.4048,10.0005)">
- <path fill="#fc0" d="m137.79 109.277c1.978 1.366 2.031 1.607 4.948 3.514 4.64 3.768 12.885 4.616 16.922 4.75 9.233 1.467 25.738-7.161 32.273-11.111 3.291-2.463 9.38-7.551 11.659-7.637 1.405 1.485-0.66 1.792-3.587 3.775-3.906 2.779-7.25 5.156-13.172 8.515-6.338 3.316-16.078 8.794-28.548 8.054-6.542-0.959-6.566-1.024-10.606-3.086-2.4-1.732-7.901-4.608-9.889-6.774z"/>
- <linearGradient id="al" x1="129.342" gradientUnits="userSpaceOnUse" x2="195.598" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.305" y2="259.305">
- <stop stop-color="#FAC700" offset="0"/>
- <stop stop-color="#F7C400" offset=".415"/>
- <stop stop-color="#F7C400" offset="1"/>
- </linearGradient>
- <path fill="url(#al)" d="m137.742 109.259c1.926 1.274 2.165 1.643 5.083 3.554 4.616 3.734 12.716 4.616 16.796 4.763 9.365 1.452 26.05-7.294 32.356-11.159 3.357-2.506 9.344-7.498 11.595-7.604 1.365 1.472-0.728 1.768-3.688 3.814-3.889 2.753-7.119 5.065-12.972 8.383-6.29 3.291-16.078 8.795-28.536 8.104-6.561-0.945-6.851-1.07-10.758-3.079-2.468-1.755-7.876-4.587-9.876-6.776z"/>
- <linearGradient id="am" x1="129.293" gradientUnits="userSpaceOnUse" x2="195.554" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.311" y2="259.311">
- <stop stop-color="#F6C200" offset="0"/>
- <stop stop-color="#EFBC00" offset=".415"/>
- <stop stop-color="#EFBC00" offset="1"/>
- </linearGradient>
- <path fill="url(#am)" d="m137.693 109.24c1.876 1.183 2.3 1.68 5.218 3.595 4.593 3.7 12.548 4.616 16.67 4.776 9.498 1.437 26.364-7.428 32.44-11.207 3.425-2.55 9.308-7.444 11.528-7.57 1.326 1.457-0.795 1.743-3.788 3.854-3.87 2.725-6.99 4.973-12.771 8.25-6.243 3.266-16.078 8.796-28.525 8.154-6.579-0.931-7.134-1.117-10.908-3.073-2.536-1.779-7.852-4.567-9.864-6.779z"/>
- <linearGradient id="an" x1="129.245" gradientUnits="userSpaceOnUse" x2="195.51" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.317" y2="259.317">
- <stop stop-color="#F1BD00" offset="0"/>
- <stop stop-color="#E8B500" offset=".415"/>
- <stop stop-color="#E8B500" offset="1"/>
- </linearGradient>
- <path fill="url(#an)" d="m137.645 109.222c1.825 1.091 2.434 1.715 5.352 3.635 4.569 3.665 12.38 4.615 16.544 4.789 9.631 1.422 26.677-7.562 32.524-11.255 3.491-2.594 9.271-7.392 11.463-7.538 1.287 1.442-0.861 1.718-3.889 3.893-3.853 2.699-6.86 4.882-12.57 8.119-6.195 3.241-16.078 8.797-28.513 8.203-6.6-0.916-7.418-1.163-11.061-3.066-2.603-1.801-7.826-4.546-9.85-6.78z"/>
- <linearGradient id="ao" x1="129.196" gradientUnits="userSpaceOnUse" x2="195.465" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.322" y2="259.322">
- <stop stop-color="#EDB800" offset="0"/>
- <stop stop-color="#E0AD00" offset=".415"/>
- <stop stop-color="#E0AD00" offset="1"/>
- </linearGradient>
- <path fill="url(#ao)" d="m137.596 109.203c1.774 1 2.568 1.752 5.487 3.676 4.545 3.631 12.211 4.615 16.418 4.801 9.764 1.408 26.989-7.695 32.608-11.302 3.557-2.637 9.236-7.338 11.396-7.505 1.247 1.427-0.928 1.693-3.99 3.932-3.833 2.672-6.729 4.791-12.369 7.986-6.148 3.217-16.078 8.799-28.501 8.254-6.619-0.902-7.702-1.21-11.21-3.059-2.672-1.825-7.803-4.525-9.839-6.783z"/>
- <linearGradient id="ap" x1="129.148" gradientUnits="userSpaceOnUse" x2="195.422" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.327" y2="259.327">
- <stop stop-color="#E9B300" offset="0"/>
- <stop stop-color="#D8A500" offset=".415"/>
- <stop stop-color="#D8A500" offset="1"/>
- </linearGradient>
- <path fill="url(#ap)" d="m137.548 109.184c1.724 0.909 2.703 1.788 5.622 3.717 4.522 3.597 12.043 4.615 16.292 4.814 9.896 1.393 27.303-7.829 32.692-11.35 3.624-2.681 9.2-7.286 11.331-7.472 1.208 1.412-0.995 1.668-4.092 3.972-3.814 2.644-6.6 4.698-12.168 7.853-6.101 3.192-16.077 8.8-28.489 8.303-6.638-0.887-7.986-1.256-11.361-3.052-2.741-1.848-7.779-4.504-9.827-6.785z"/>
- <linearGradient id="aq" x1="129.099" gradientUnits="userSpaceOnUse" x2="195.379" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.332" y2="259.332">
- <stop stop-color="#E4AE00" offset="0"/>
- <stop stop-color="#D19E00" offset=".415"/>
- <stop stop-color="#D19E00" offset="1"/>
- </linearGradient>
- <path fill="url(#aq)" d="m137.499 109.166c1.673 0.817 2.838 1.824 5.757 3.757 4.499 3.562 11.875 4.614 16.166 4.827 10.029 1.378 27.615-7.963 32.776-11.398 3.691-2.725 9.164-7.232 11.265-7.439 1.169 1.397-1.061 1.644-4.191 4.01-3.796 2.618-6.469 4.608-11.968 7.722-6.053 3.167-16.077 8.801-28.478 8.353-6.657-0.873-8.27-1.303-11.512-3.046-2.809-1.87-7.755-4.483-9.815-6.786z"/>
- <linearGradient id="ar" x1="129.051" gradientUnits="userSpaceOnUse" x2="195.338" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.336" y2="259.336">
- <stop stop-color="#E0A900" offset="0"/>
- <stop stop-color="#C99600" offset=".415"/>
- <stop stop-color="#C99600" offset="1"/>
- </linearGradient>
- <path fill="url(#ar)" d="m137.451 109.147c1.622 0.726 2.972 1.86 5.892 3.798 4.475 3.528 11.705 4.614 16.04 4.84 10.161 1.362 27.929-8.097 32.859-11.447 3.757-2.767 9.128-7.178 11.2-7.405 1.13 1.382-1.128 1.619-4.294 4.049-3.777 2.592-6.339 4.517-11.767 7.589-6.005 3.143-16.077 8.803-28.466 8.404-6.676-0.859-8.553-1.35-11.663-3.039-2.876-1.894-7.729-4.462-9.801-6.789z"/>
- <linearGradient id="w" x1="129.003" gradientUnits="userSpaceOnUse" x2="195.296" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.34" y2="259.34">
- <stop stop-color="#DCA400" offset="0"/>
- <stop stop-color="#C18E00" offset=".415"/>
- <stop stop-color="#C18E00" offset="1"/>
- </linearGradient>
- <path fill="url(#w)" d="m137.403 109.129c1.571 0.634 3.105 1.896 6.026 3.838 4.45 3.494 11.536 4.614 15.913 4.852 10.295 1.348 28.241-8.23 32.943-11.494 3.824-2.811 9.092-7.125 11.134-7.373 1.092 1.367-1.194 1.594-4.394 4.088-3.759 2.565-6.209 4.425-11.566 7.457-5.957 3.118-16.077 8.804-28.454 8.453-6.694-0.844-8.837-1.396-11.813-3.032-2.945-1.916-7.706-4.44-9.789-6.789z"/>
- <linearGradient id="x" x1="128.954" gradientUnits="userSpaceOnUse" x2="195.255" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.343" y2="259.343">
- <stop stop-color="#D79F00" offset="0"/>
- <stop stop-color="#BA8700" offset=".415"/>
- <stop stop-color="#BA8700" offset="1"/>
- </linearGradient>
- <path fill="url(#x)" d="m137.354 109.11c1.521 0.543 3.241 1.932 6.161 3.879 4.428 3.459 11.368 4.613 15.788 4.865 10.427 1.333 28.554-8.364 33.026-11.542 3.892-2.855 9.057-7.073 11.068-7.339 1.052 1.353-1.261 1.569-4.495 4.127-3.74 2.538-6.078 4.334-11.365 7.325-5.91 3.093-16.077 8.805-28.441 8.503-6.716-0.83-9.121-1.443-11.966-3.026-3.012-1.939-7.68-4.42-9.776-6.792z"/>
- <linearGradient id="y" x1="128.906" gradientUnits="userSpaceOnUse" x2="195.216" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.348" y2="259.348">
- <stop stop-color="#D39B00" offset="0"/>
- <stop stop-color="#B27F00" offset=".415"/>
- <stop stop-color="#B27F00" offset="1"/>
- </linearGradient>
- <path fill="url(#y)" d="m137.306 109.091c1.47 0.451 3.375 1.969 6.296 3.919 4.403 3.426 11.2 4.614 15.662 4.879 10.559 1.318 28.865-8.498 33.109-11.59 3.958-2.899 9.021-7.02 11.003-7.306 1.013 1.337-1.328 1.544-4.596 4.167-3.722 2.511-5.949 4.242-11.165 7.192-5.862 3.068-16.077 8.807-28.43 8.553-6.734-0.816-9.405-1.489-12.116-3.019-3.08-1.963-7.656-4.4-9.763-6.795z"/>
- <linearGradient id="z" x1="128.857" gradientUnits="userSpaceOnUse" x2="195.176" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.35" y2="259.35">
- <stop stop-color="#CF9600" offset="0"/>
- <stop stop-color="#a70" offset=".415"/>
- <stop stop-color="#a70" offset="1"/>
- </linearGradient>
- <path fill="url(#z)" d="m137.257 109.073c1.421 0.359 3.511 2.005 6.432 3.959 4.38 3.392 11.032 4.614 15.536 4.892 10.691 1.303 29.179-8.631 33.193-11.638 4.024-2.942 8.984-6.967 10.938-7.274 0.973 1.323-1.396 1.521-4.697 4.206-3.703 2.484-5.818 4.151-10.964 7.06-5.814 3.043-16.077 8.808-28.418 8.603-6.753-0.802-9.689-1.535-12.268-3.012-3.149-1.986-7.632-4.378-9.752-6.796z"/>
- <linearGradient id="aa" x1="128.809" gradientUnits="userSpaceOnUse" x2="195.137" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.354" y2="259.354">
- <stop stop-color="#CA9100" offset="0"/>
- <stop stop-color="#A37000" offset=".415"/>
- <stop stop-color="#A37000" offset="1"/>
- </linearGradient>
- <path fill="url(#aa)" d="m137.209 109.054c1.368 0.268 3.645 2.041 6.565 4 4.356 3.357 10.864 4.613 15.41 4.904 10.824 1.289 29.493-8.764 33.277-11.685 4.092-2.986 8.948-6.914 10.871-7.241 0.935 1.308-1.461 1.496-4.797 4.245-3.685 2.457-5.688 4.06-10.763 6.928-5.768 3.018-16.077 8.809-28.407 8.653-6.771-0.788-9.972-1.582-12.418-3.006-3.216-2.008-7.607-4.357-9.738-6.798z"/>
- <linearGradient id="ab" x1="128.76" gradientUnits="userSpaceOnUse" x2="195.099" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.356" y2="259.356">
- <stop stop-color="#C68C00" offset="0"/>
- <stop stop-color="#9B6800" offset=".415"/>
- <stop stop-color="#9B6800" offset="1"/>
- </linearGradient>
- <path fill="url(#ab)" d="m137.16 109.036c1.318 0.176 3.779 2.077 6.701 4.04 4.333 3.323 10.695 4.613 15.284 4.917 10.957 1.274 29.805-8.898 33.36-11.733 4.158-3.03 8.912-6.86 10.807-7.208 0.894 1.292-1.528 1.471-4.899 4.284-3.666 2.43-5.558 3.968-10.562 6.796-5.72 2.993-16.077 8.81-28.396 8.702-6.791-0.773-10.256-1.628-12.568-2.999-3.285-2.031-7.583-4.336-9.727-6.799z"/>
- <linearGradient id="ac" x1="128.712" gradientUnits="userSpaceOnUse" x2="195.062" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.358" y2="259.358">
- <stop stop-color="#C28700" offset="0"/>
- <stop stop-color="#936000" offset=".415"/>
- <stop stop-color="#936000" offset="1"/>
- </linearGradient>
- <path fill="url(#ac)" d="m137.112 109.017c1.267 0.085 3.912 2.113 6.835 4.081 4.31 3.289 10.527 4.613 15.158 4.93 11.09 1.258 30.118-9.032 33.445-11.782 4.225-3.072 8.877-6.807 10.739-7.174 0.855 1.278-1.595 1.446-5 4.323-3.647 2.404-5.427 3.877-10.36 6.663-5.673 2.969-16.077 8.812-28.384 8.753-6.811-0.759-10.54-1.675-12.719-2.992-3.353-2.055-7.559-4.315-9.714-6.802z"/>
- <linearGradient id="ad" x1="128.663" gradientUnits="userSpaceOnUse" x2="195.025" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.36" y2="259.36">
- <stop stop-color="#BD8200" offset="0"/>
- <stop stop-color="#8C5900" offset=".415"/>
- <stop stop-color="#8C5900" offset="1"/>
- </linearGradient>
- <path fill="url(#ad)" d="m137.063 108.998c1.217-0.006 4.047 2.15 6.97 4.122 4.286 3.254 10.359 4.612 15.032 4.943 11.223 1.243 30.431-9.166 33.53-11.83 4.289-3.116 8.84-6.753 10.673-7.141 0.815 1.263-1.661 1.421-5.101 4.362-3.63 2.377-5.298 3.785-10.161 6.531-5.624 2.944-16.075 8.813-28.37 8.802-6.83-0.744-10.824-1.721-12.87-2.985-3.422-2.077-7.535-4.294-9.703-6.804z"/>
- <linearGradient id="ae" x1="128.615" gradientUnits="userSpaceOnUse" x2="194.989" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.362" y2="259.362">
- <stop stop-color="#B97D00" offset="0"/>
- <stop stop-color="#845100" offset=".415"/>
- <stop stop-color="#845100" offset="1"/>
- </linearGradient>
- <path fill="url(#ae)" d="m137.015 108.98c1.166-0.098 4.181 2.185 7.104 4.162 4.262 3.22 10.19 4.612 14.906 4.955 11.354 1.229 30.743-9.299 33.613-11.877 4.356-3.16 8.804-6.7 10.607-7.108 0.776 1.248-1.728 1.397-5.202 4.401-3.61 2.35-5.167 3.694-9.96 6.399-5.576 2.919-16.076 8.814-28.358 8.852-6.85-0.73-11.108-1.768-13.021-2.979-3.489-2.1-7.51-4.273-9.689-6.805z"/>
- <linearGradient id="af" x1="128.567" gradientUnits="userSpaceOnUse" x2="194.954" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.364" y2="259.364">
- <stop stop-color="#B57800" offset="0"/>
- <stop stop-color="#7C4900" offset=".415"/>
- <stop stop-color="#7C4900" offset="1"/>
- </linearGradient>
- <path fill="url(#af)" d="m136.967 108.961c1.115-0.189 4.315 2.222 7.239 4.203 4.239 3.186 10.021 4.612 14.78 4.968 11.488 1.214 31.057-9.433 33.697-11.925 4.424-3.203 8.768-6.647 10.542-7.075 0.736 1.233-1.795 1.372-5.303 4.44-3.593 2.323-5.038 3.603-9.759 6.266-5.529 2.895-16.077 8.816-28.348 8.903-6.868-0.716-11.392-1.815-13.172-2.972-3.557-2.124-7.485-4.252-9.676-6.808z"/>
- <linearGradient id="ah" x1="128.518" gradientUnits="userSpaceOnUse" x2="194.918" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.366" y2="259.366">
- <stop stop-color="#B07300" offset="0"/>
- <stop stop-color="#754200" offset=".415"/>
- <stop stop-color="#754200" offset="1"/>
- </linearGradient>
- <path fill="url(#ah)" d="m136.918 108.943c1.064-0.281 4.45 2.257 7.374 4.243 4.216 3.151 9.854 4.611 14.654 4.981 11.621 1.199 31.37-9.567 33.781-11.973 4.49-3.247 8.731-6.594 10.476-7.042 0.698 1.218-1.861 1.347-5.403 4.479-3.573 2.296-4.906 3.511-9.558 6.134-5.48 2.87-16.076 8.817-28.336 8.952-6.887-0.701-11.675-1.861-13.323-2.965-3.626-2.146-7.462-4.231-9.665-6.809z"/>
- <linearGradient id="ai" x1="128.47" gradientUnits="userSpaceOnUse" x2="194.886" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.367" y2="259.367">
- <stop stop-color="#AC6E00" offset="0"/>
- <stop stop-color="#6D3A00" offset=".415"/>
- <stop stop-color="#6D3A00" offset="1"/>
- </linearGradient>
- <path fill="url(#ai)" d="m136.87 108.924c1.013-0.372 4.584 2.294 7.509 4.284 4.191 3.117 9.685 4.611 14.528 4.994 11.753 1.184 31.682-9.701 33.864-12.021 4.557-3.291 8.695-6.542 10.411-7.009 0.657 1.203-1.929 1.322-5.504 4.518-3.557 2.269-4.777 3.42-9.358 6.002-5.434 2.845-16.076 8.818-28.324 9.002-6.907-0.687-11.959-1.908-13.474-2.959-3.694-2.169-7.437-4.21-9.652-6.811z"/>
- <linearGradient id="aj" x1="128.421" gradientUnits="userSpaceOnUse" x2="194.85" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.369" y2="259.369">
- <stop stop-color="#A86A00" offset="0"/>
- <stop stop-color="#663200" offset=".415"/>
- <stop stop-color="#663200" offset="1"/>
- </linearGradient>
- <path fill="url(#aj)" d="m136.821 108.905c0.963-0.464 4.719 2.33 7.644 4.324 4.168 3.083 9.517 4.611 14.402 5.007 11.886 1.169 31.995-9.834 33.948-12.069 4.624-3.334 8.66-6.487 10.345-6.976 0.619 1.188-1.995 1.298-5.604 4.558-3.537 2.242-4.647 3.328-9.157 5.869-5.386 2.82-16.076 8.82-28.313 9.052-6.926-0.673-12.243-1.954-13.625-2.952-3.762-2.192-7.413-4.189-9.64-6.813z"/>
- </g>
- </g>
-</svg>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 349.46883 405.12272">
+ <title>Tux</title>
+ <desc>For more information see: http://commons.wikimedia.org/wiki/Image:Tux.svg</desc>
+ <radialGradient id="ag" gradientUnits="userSpaceOnUse" cy="-551.04" cx="274.822" gradientTransform="matrix(.5671 0 0 -.2835 81.263 201.645)" r="165.384">
+ <stop stop-opacity=".502" offset="0"/>
+ <stop stop-opacity="0" offset="1"/>
+ </radialGradient>
+ <path fill="url(#ag)" d="m330.892 357.885c0 25.898-41.989 46.893-93.785 46.893-51.795 0-93.784-20.994-93.784-46.893s41.989-46.893 93.784-46.893c51.795 0.001 93.785 20.995 93.785 46.893z"/>
+ <radialGradient id="ak" gradientUnits="userSpaceOnUse" cy="-551.042" cx="268.794" gradientTransform="matrix(.5823 0 0 -.2835 -61.6052 201.14)" r="165.383">
+ <stop stop-opacity=".502" offset="0"/>
+ <stop stop-opacity="0" offset="1"/>
+ </radialGradient>
+ <path fill="url(#ak)" d="m191.223 357.381c0 25.897-43.117 46.892-96.306 46.892-53.188 0-96.305-20.994-96.305-46.892s43.117-46.893 96.305-46.893c53.188 0.001 96.306 20.995 96.306 46.893z"/>
+ <g transform="translate(8.99996 9.00046)">
+ <path d="m292.327 256.606c-4.752 19.584-28.872 60.48-41.688 78.48-12.815 18.072-11.231 34.344-34.92 28.008-23.616-6.336-30.24-5.184-54.647-3.744-24.265 1.439-19.009-0.721-34.2 6.12-15.12 6.84-65.88-82.944-69.984-99.647-4.031-16.705-5.976-14.689 4.536-32.761 10.513-18.071 12.024-35.928 25.92-57.816 13.896-21.96 29.952-33.12 28.8-49.896-4.535-62.28-8.136-93.384 19.513-107.784 26.352-13.68 48.384-5.544 57.096-0.864 3.744 2.016 11.376 5.904 17.064 12.744 5.688 6.696 10.8 16.848 13.68 29.664 5.904 25.704-2.448 17.208 4.248 46.656 6.624 29.375 20.088 43.775 36.504 67.031 16.414 23.257 33.55 61.633 28.078 83.809z"/>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#666" d="m148.47 94.049c4.319-1.728 3.592-1.958 6.472-8.222 2.304-4.824 4.328-6.898 4.256-14.242 0-7.2-2.232-9.648-5.616-14.328-3.24-4.464-8.424-4.68-11.664-4.104-1.872 0.288-4.319 2.664-5.976 6.192-1.08 2.376-1.944 5.4-2.017 8.568-0.216 8.496 0.505 11.736 2.448 17.496 2.305 6.769 7.921 10.297 12.097 8.64z"/>
+ <path fill="#6d6d6d" d="m148.47 94.023c4.293-1.717 3.563-1.954 6.425-8.178 2.289-4.793 4.312-6.861 4.271-14.164 0.027-7.152-2.162-9.702-5.488-14.201-3.296-4.345-8.376-4.509-11.593-3.953-1.916 0.283-4.354 2.569-6.038 5.968-1.159 2.31-2.016 5.353-2.087 8.535-0.212 8.438 0.547 11.691 2.46 17.417 2.268 6.731 7.901 10.221 12.05 8.576z"/>
+ <path fill="#757575" d="m148.471 93.996c4.264-1.706 3.533-1.95 6.377-8.133 2.273-4.762 4.296-6.823 4.288-14.085 0.053-7.105-2.093-9.756-5.363-14.075-3.35-4.225-8.327-4.338-11.52-3.801-1.961 0.278-4.389 2.474-6.099 5.744-1.242 2.245-2.089 5.305-2.16 8.501-0.207 8.38 0.591 11.647 2.473 17.34 2.231 6.691 7.881 10.144 12.004 8.509z"/>
+ <path fill="#7c7c7c" d="m148.471 93.969c4.235-1.694 3.506-1.946 6.329-8.089 2.26-4.731 4.28-6.786 4.304-14.006 0.081-7.058-2.021-9.811-5.236-13.948-3.403-4.105-8.278-4.167-11.446-3.649-2.006 0.273-4.424 2.379-6.16 5.519-1.322 2.179-2.161 5.257-2.232 8.468-0.202 8.323 0.636 11.603 2.486 17.261 2.191 6.654 7.859 10.068 11.955 8.444z"/>
+ <path fill="#848484" d="m148.471 93.943c4.209-1.684 3.477-1.942 6.282-8.045 2.245-4.7 4.266-6.749 4.319-13.928 0.107-7.01-1.95-9.864-5.109-13.821-3.458-3.985-8.23-3.996-11.375-3.498-2.049 0.268-4.458 2.284-6.222 5.295-1.403 2.114-2.233 5.21-2.303 8.435-0.198 8.265 0.679 11.559 2.498 17.183 2.156 6.615 7.842 9.992 11.91 8.379z"/>
+ <path fill="#8c8c8c" d="m148.471 93.916c4.181-1.672 3.448-1.938 6.235-8 2.23-4.668 4.249-6.711 4.335-13.85 0.134-6.962-1.88-9.918-4.982-13.695-3.513-3.865-8.183-3.825-11.303-3.347-2.094 0.263-4.492 2.189-6.283 5.07-1.484 2.049-2.306 5.163-2.375 8.401-0.193 8.207 0.723 11.515 2.511 17.105 2.118 6.58 7.821 9.919 11.862 8.316z"/>
+ <path fill="#939393" d="m148.472 93.889c4.152-1.661 3.419-1.934 6.188-7.956 2.215-4.638 4.233-6.674 4.35-13.771 0.161-6.915-1.809-9.972-4.854-13.568-3.567-3.746-8.134-3.654-11.23-3.195-2.138 0.259-4.527 2.094-6.345 4.847-1.564 1.983-2.378 5.115-2.447 8.368-0.188 8.149 0.767 11.47 2.523 17.026 2.079 6.54 7.8 9.841 11.815 8.249z"/>
+ <path fill="#9b9b9b" d="m148.472 93.863c4.125-1.65 3.391-1.93 6.141-7.912 2.2-4.607 4.217-6.637 4.366-13.693 0.188-6.868-1.739-10.026-4.729-13.441-3.621-3.626-8.085-3.484-11.157-3.044-2.183 0.253-4.562 1.999-6.406 4.622-1.646 1.918-2.45 5.068-2.52 8.335-0.185 8.091 0.811 11.426 2.535 16.948 2.044 6.502 7.782 9.766 11.77 8.185z"/>
+ <path fill="#a3a3a3" d="m148.472 93.836c4.097-1.639 3.361-1.926 6.094-7.867 2.185-4.576 4.201-6.599 4.382-13.614 0.214-6.82-1.669-10.081-4.603-13.315-3.676-3.506-8.036-3.313-11.084-2.893-2.229 0.249-4.598 1.904-6.47 4.398-1.726 1.852-2.521 5.021-2.591 8.301-0.18 8.034 0.854 11.382 2.548 16.87 2.008 6.465 7.763 9.691 11.724 8.12z"/>
+ <path fill="#aaa" d="m148.472 93.809c4.069-1.628 3.334-1.922 6.047-7.823 2.17-4.544 4.185-6.562 4.396-13.536 0.242-6.772-1.597-10.134-4.475-13.188-3.73-3.387-7.989-3.142-11.013-2.741-2.271 0.243-4.632 1.809-6.53 4.173-1.808 1.787-2.594 4.974-2.662 8.268-0.176 7.976 0.897 11.337 2.56 16.792 1.97 6.427 7.743 9.615 11.677 8.055z"/>
+ <path fill="#b2b2b2" d="m148.473 93.782c4.041-1.617 3.304-1.918 5.999-7.778 2.154-4.514 4.169-6.524 4.412-13.458 0.269-6.725-1.526-10.188-4.349-13.062-3.784-3.267-7.939-2.971-10.939-2.589-2.316 0.238-4.666 1.714-6.592 3.949-1.888 1.721-2.667 4.926-2.734 8.234-0.171 7.918 0.941 11.293 2.572 16.713 1.933 6.391 7.723 9.541 11.631 7.991z"/>
+ <path fill="#bababa" d="m148.473 93.756c4.014-1.606 3.275-1.914 5.951-7.734 2.141-4.482 4.153-6.487 4.43-13.379 0.295-6.678-1.457-10.243-4.223-12.935-3.839-3.147-7.892-2.8-10.867-2.438-2.36 0.233-4.701 1.619-6.653 3.725-1.969 1.656-2.739 4.879-2.806 8.201-0.167 7.86 0.984 11.249 2.585 16.636 1.895 6.35 7.702 9.462 11.583 7.924z"/>
+ <path fill="#c1c1c1" d="m148.473 93.729c3.985-1.595 3.247-1.91 5.904-7.69 2.125-4.451 4.138-6.45 4.445-13.3 0.321-6.63-1.387-10.297-4.096-12.808-3.894-3.028-7.844-2.629-10.795-2.287-2.405 0.229-4.735 1.524-6.716 3.5-2.049 1.59-2.811 4.831-2.878 8.167-0.161 7.802 1.029 11.205 2.599 16.557 1.859 6.314 7.683 9.389 11.537 7.861z"/>
+ <path fill="#c9c9c9" d="m148.473 93.702c3.958-1.583 3.219-1.906 5.857-7.646 2.11-4.42 4.121-6.412 4.46-13.222 0.35-6.583-1.315-10.351-3.969-12.682-3.947-2.908-7.794-2.458-10.722-2.135-2.45 0.224-4.771 1.429-6.777 3.276-2.13 1.525-2.883 4.784-2.95 8.135-0.157 7.745 1.073 11.16 2.611 16.479 1.821 6.276 7.663 9.313 11.49 7.795z"/>
+ <path fill="#d1d1d1" d="m148.474 93.676c3.93-1.573 3.188-1.902 5.809-7.601 2.097-4.389 4.107-6.375 4.477-13.144 0.375-6.535-1.245-10.404-3.842-12.555-4.002-2.788-7.747-2.287-10.65-1.984-2.493 0.219-4.805 1.334-6.837 3.052-2.213 1.459-2.957 4.736-3.022 8.101-0.153 7.687 1.116 11.116 2.623 16.401 1.782 6.237 7.642 9.237 11.442 7.73z"/>
+ <path fill="#d8d8d8" d="m148.474 93.649c3.901-1.562 3.16-1.898 5.762-7.557 2.082-4.358 4.091-6.338 4.493-13.065 0.401-6.487-1.176-10.458-3.716-12.428-4.057-2.668-7.698-2.116-10.578-1.832-2.538 0.214-4.839 1.239-6.899 2.827-2.292 1.394-3.029 4.689-3.094 8.068-0.148 7.629 1.16 11.072 2.636 16.322 1.746 6.2 7.623 9.161 11.396 7.665z"/>
+ <path fill="#e0e0e0" d="m148.474 93.622c3.875-1.55 3.132-1.894 5.715-7.512 2.066-4.327 4.075-6.3 4.508-12.987 0.429-6.44-1.104-10.513-3.588-12.302-4.111-2.549-7.65-1.945-10.506-1.681-2.582 0.209-4.874 1.144-6.961 2.604-2.373 1.328-3.102 4.642-3.165 8.034-0.145 7.571 1.204 11.027 2.647 16.244 1.709 6.162 7.604 9.086 11.35 7.6z"/>
+ <path fill="#e8e8e8" d="m148.474 93.596c3.847-1.54 3.104-1.89 5.668-7.468 2.052-4.296 4.059-6.263 4.523-12.908 0.456-6.393-1.034-10.567-3.462-12.175-4.165-2.429-7.601-1.774-10.433-1.529-2.627 0.204-4.908 1.049-7.023 2.379-2.453 1.263-3.173 4.594-3.236 8.001-0.141 7.514 1.247 10.983 2.659 16.166 1.673 6.123 7.585 9.008 11.304 7.534z"/>
+ <path fill="#efefef" d="m148.475 93.569c3.817-1.528 3.073-1.886 5.62-7.424 2.036-4.265 4.043-6.226 4.539-12.83 0.482-6.345-0.964-10.621-3.336-12.048-4.219-2.31-7.552-1.604-10.359-1.378-2.672 0.199-4.943 0.954-7.084 2.155-2.535 1.197-3.246 4.546-3.311 7.967-0.135 7.456 1.292 10.939 2.673 16.087 1.636 6.087 7.565 8.935 11.258 7.471z"/>
+ <path fill="#f7f7f7" d="m148.475 93.542c3.791-1.517 3.046-1.882 5.572-7.379 2.022-4.234 4.027-6.188 4.556-12.751 0.51-6.297-0.894-10.675-3.208-11.921-4.274-2.19-7.505-1.433-10.289-1.227-2.715 0.194-4.978 0.859-7.146 1.93-2.614 1.132-3.317 4.5-3.381 7.935-0.131 7.398 1.335 10.895 2.686 16.009 1.597 6.047 7.544 8.858 11.21 7.404z"/>
+ <path fill="#fff" d="m148.475 93.516c3.763-1.506 3.017-1.878 5.525-7.335 2.007-4.203 4.012-6.151 4.571-12.673 0.536-6.25-0.823-10.729-3.082-11.795-4.328-2.07-7.456-1.262-10.216-1.075-2.76 0.189-5.012 0.764-7.207 1.706-2.696 1.066-3.39 4.452-3.453 7.901-0.126 7.34 1.379 10.85 2.698 15.931 1.561 6.01 7.525 8.782 11.164 7.34z"/>
+ </g>
+ <path d="m132.033 74.7465c2.16 0 4.896 1.44 6.191 3.384 1.368 1.944 2.376 4.68 2.376 7.776 0 4.608-0.504 9.72-3.239 11.304-0.864 0.504-2.736 0.936-3.816 0.936-2.448 0-2.664-1.584-4.968-3.96-0.792-0.864-3.168-5.04-3.168-8.496 0-2.16-0.504-5.256 1.368-7.992 1.296-2.016 2.952-2.952 5.256-2.952z"/>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m143.862 68.608c0.844-1.305 4.222-0.69 5.45 1.996 1.229 2.687 0.998 8.522 0.153 8.829-2.226 0.691-1.535-2.534-3.454-5.451-1.919-2.762-2.994-4.067-2.149-5.374z"/>
+ <path fill="#070707" d="m143.916 68.664c0.833-1.289 4.169-0.681 5.381 1.971 1.215 2.653 0.985 8.414 0.152 8.717-2.198 0.682-1.516-2.502-3.411-5.382-1.895-2.728-2.956-4.017-2.122-5.306z"/>
+ <path fill="#0f0f0f" d="m143.97 68.719c0.822-1.272 4.114-0.673 5.312 1.945 1.198 2.619 0.973 8.306 0.15 8.605-2.169 0.673-1.497-2.47-3.367-5.313-1.871-2.692-2.918-3.964-2.095-5.237z"/>
+ <path fill="#161616" d="m144.024 68.774c0.812-1.255 4.062-0.664 5.243 1.92 1.182 2.585 0.96 8.198 0.147 8.493-2.141 0.665-1.477-2.438-3.323-5.244-1.846-2.657-2.88-3.913-2.067-5.169z"/>
+ <path fill="#1e1e1e" d="m144.078 68.829c0.801-1.239 4.008-0.655 5.174 1.895 1.167 2.551 0.947 8.09 0.146 8.381-2.113 0.656-1.458-2.405-3.28-5.174-1.821-2.623-2.842-3.863-2.04-5.102z"/>
+ <path fill="#262626" d="m144.132 68.884c0.791-1.222 3.955-0.646 5.105 1.87 1.151 2.517 0.935 7.982 0.144 8.27-2.085 0.647-1.438-2.374-3.235-5.105-1.798-2.589-2.805-3.812-2.014-5.035z"/>
+ <path fill="#2d2d2d" d="m144.186 68.939c0.779-1.206 3.9-0.638 5.036 1.844 1.135 2.483 0.922 7.874 0.142 8.158-2.057 0.639-1.419-2.341-3.192-5.037-1.773-2.552-2.766-3.758-1.986-4.965z"/>
+ <path fill="#353535" d="m144.24 68.994c0.769-1.189 3.848-0.629 4.967 1.819 1.12 2.449 0.909 7.766 0.141 8.046-2.028 0.629-1.399-2.31-3.148-4.967-1.75-2.518-2.73-3.708-1.96-4.898z"/>
+ <path fill="#3d3d3d" d="m144.294 69.049c0.76-1.172 3.794-0.621 4.898 1.793 1.104 2.415 0.896 7.658 0.138 7.934-2 0.621-1.38-2.277-3.104-4.898-1.725-2.482-2.691-3.655-1.932-4.829z"/>
+ <path fill="#444" d="m144.348 69.104c0.748-1.156 3.74-0.612 4.829 1.768 1.088 2.38 0.884 7.55 0.136 7.822-1.973 0.612-1.36-2.245-3.062-4.829-1.699-2.448-2.651-3.604-1.903-4.761z"/>
+ <path fill="#4c4c4c" d="m144.402 69.16c0.737-1.14 3.687-0.603 4.76 1.743 1.073 2.347 0.871 7.442 0.134 7.71-1.943 0.604-1.341-2.213-3.017-4.76-1.676-2.414-2.614-3.554-1.877-4.693z"/>
+ <path fill="#545454" d="m144.456 69.215c0.727-1.123 3.634-0.595 4.691 1.717 1.057 2.313 0.857 7.334 0.132 7.598-1.916 0.595-1.321-2.181-2.973-4.691-1.652-2.378-2.577-3.501-1.85-4.624z"/>
+ <path fill="#5b5b5b" d="m144.51 69.27c0.717-1.106 3.58-0.585 4.622 1.692 1.041 2.278 0.847 7.226 0.131 7.486-1.888 0.586-1.303-2.149-2.93-4.622-1.628-2.343-2.539-3.45-1.823-4.556z"/>
+ <path fill="#636363" d="m144.564 69.325c0.705-1.09 3.526-0.577 4.553 1.667 1.026 2.245 0.833 7.118 0.128 7.375-1.858 0.577-1.282-2.117-2.885-4.553-1.604-2.309-2.501-3.399-1.796-4.489z"/>
+ <path fill="#6b6b6b" d="m144.618 69.38c0.694-1.073 3.473-0.568 4.483 1.642 1.011 2.21 0.82 7.01 0.127 7.263-1.831 0.568-1.264-2.084-2.842-4.484-1.578-2.274-2.462-3.347-1.768-4.421z"/>
+ <path fill="#727272" d="m144.672 69.435c0.685-1.057 3.42-0.56 4.414 1.617 0.995 2.176 0.81 6.902 0.125 7.15-1.803 0.56-1.243-2.053-2.798-4.415-1.554-2.238-2.425-3.295-1.741-4.352z"/>
+ <path fill="#7a7a7a" d="m144.726 69.49c0.673-1.041 3.365-0.551 4.345 1.591 0.979 2.143 0.796 6.794 0.123 7.039-1.775 0.551-1.224-2.021-2.754-4.346-1.53-2.203-2.387-3.244-1.714-4.284z"/>
+ <path fill="#828282" d="m144.78 69.545c0.662-1.023 3.313-0.542 4.276 1.566 0.964 2.108 0.782 6.686 0.121 6.926-1.746 0.542-1.204-1.988-2.711-4.276-1.505-2.167-2.348-3.192-1.686-4.216z"/>
+ <path fill="#898989" d="m144.834 69.6c0.652-1.007 3.259-0.533 4.207 1.541s0.771 6.578 0.119 6.815c-1.718 0.534-1.185-1.956-2.666-4.207-1.482-2.134-2.311-3.142-1.66-4.149z"/>
+ <path fill="#919191" d="m144.888 69.655c0.641-0.99 3.206-0.524 4.138 1.516 0.933 2.04 0.758 6.47 0.117 6.703-1.69 0.525-1.165-1.924-2.623-4.138-1.457-2.098-2.273-3.09-1.632-4.081z"/>
+ <path fill="#999" d="m144.942 69.71c0.63-0.974 3.152-0.516 4.069 1.49s0.744 6.362 0.114 6.591c-1.662 0.516-1.146-1.892-2.579-4.069-1.432-2.062-2.234-3.037-1.604-4.012z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#666" d="m193.11 94.985c10.8-1.152 14.616-5.328 16.56-12.6 1.729-6.48 1.801-13.68-3.023-22.104-4.536-8.063-7.128-9.36-13.681-9.864-10.079-0.864-14.832 6.192-17.063 11.232-2.376 5.472-1.872 4.68-1.729 11.592 0.145 7.272 4.245 9.299 6.766 13.835 2.519 4.465 10.946 7.982 12.17 7.909z"/>
+ <path fill="#6d6d6d" d="m193.115 94.944c10.759-1.131 14.618-5.354 16.515-12.569 1.701-6.525 1.785-13.686-3.002-21.912-4.434-7.797-7.038-9.081-13.512-9.581-10.049-0.861-14.941 5.873-17.181 10.874-2.304 5.28-1.878 4.718-1.726 11.539 0.16 7.268 4.268 9.223 6.784 13.76 2.521 4.475 10.898 7.962 12.122 7.889z"/>
+ <path fill="#757575" d="m193.12 94.902c10.718-1.11 14.62-5.379 16.469-12.538 1.676-6.57 1.771-13.692-2.979-21.721-4.331-7.53-6.947-8.801-13.344-9.297-10.018-0.858-15.05 5.553-17.298 10.516-2.229 5.087-1.885 4.757-1.722 11.487 0.176 7.264 4.289 9.146 6.803 13.686 2.52 4.485 10.848 7.942 12.071 7.867z"/>
+ <path fill="#7c7c7c" d="m193.126 94.861c10.675-1.09 14.621-5.405 16.423-12.507 1.648-6.616 1.756-13.698-2.958-21.529-4.229-7.263-6.856-8.522-13.176-9.014-9.985-0.854-15.158 5.234-17.414 10.158-2.156 4.895-1.891 4.795-1.719 11.434 0.193 7.26 4.31 9.07 6.822 13.611 2.52 4.495 10.798 7.922 12.022 7.847z"/>
+ <path fill="#848484" d="m193.131 94.82c10.635-1.069 14.623-5.431 16.377-12.476 1.622-6.661 1.741-13.704-2.936-21.337-4.126-6.996-6.767-8.242-13.008-8.73-9.955-0.852-15.267 4.915-17.53 9.8-2.084 4.703-1.896 4.833-1.716 11.38 0.209 7.256 4.332 8.995 6.841 13.537 2.52 4.505 10.748 7.902 11.972 7.826z"/>
+ <path fill="#8c8c8c" d="m193.136 94.778c10.593-1.048 14.625-5.457 16.331-12.445 1.596-6.706 1.726-13.709-2.913-21.145-4.025-6.729-6.678-7.963-12.841-8.447-9.924-0.848-15.375 4.595-17.647 9.441-2.01 4.51-1.903 4.872-1.712 11.328 0.225 7.251 4.354 8.918 6.858 13.462 2.521 4.517 10.7 7.883 11.924 7.806z"/>
+ <path fill="#939393" d="m193.141 94.737c10.552-1.027 14.627-5.482 16.286-12.414 1.568-6.751 1.711-13.715-2.893-20.954-3.922-6.462-6.586-7.683-12.672-8.163-9.892-0.845-15.483 4.276-17.764 9.083-1.938 4.318-1.909 4.91-1.709 11.275 0.24 7.247 4.375 8.842 6.878 13.387 2.521 4.528 10.651 7.863 11.874 7.786z"/>
+ <path fill="#9b9b9b" d="m193.146 94.695c10.51-1.007 14.63-5.508 16.241-12.382 1.542-6.796 1.694-13.721-2.87-20.762-3.82-6.195-6.496-7.404-12.504-7.879-9.861-0.842-15.592 3.956-17.882 8.725-1.863 4.126-1.915 4.949-1.706 11.223 0.258 7.243 4.397 8.766 6.897 13.313 2.521 4.535 10.601 7.841 11.824 7.762z"/>
+ <path fill="#a3a3a3" d="m193.151 94.654c10.469-0.986 14.632-5.534 16.196-12.351 1.515-6.842 1.68-13.727-2.85-20.57-3.717-5.928-6.405-7.125-12.335-7.596-9.83-0.839-15.7 3.637-17.998 8.367-1.791 3.933-1.922 4.987-1.703 11.169 0.273 7.239 4.419 8.689 6.916 13.238 2.521 4.547 10.551 7.822 11.774 7.743z"/>
+ <path fill="#aaa" d="m193.157 94.612c10.427-0.965 14.633-5.56 16.149-12.32 1.488-6.887 1.666-13.733-2.826-20.379-3.615-5.661-6.316-6.845-12.168-7.313-9.799-0.835-15.809 3.317-18.114 8.009-1.718 3.741-1.928 5.025-1.7 11.117 0.29 7.235 4.44 8.613 6.936 13.163 2.519 4.558 10.499 7.804 11.723 7.723z"/>
+ <path fill="#b2b2b2" d="m193.162 94.571c10.386-0.944 14.635-5.585 16.104-12.289 1.462-6.932 1.649-13.739-2.806-20.188-3.512-5.394-6.225-6.565-11.999-7.029-9.768-0.833-15.917 2.998-18.23 7.651-1.646 3.549-1.935 5.064-1.697 11.064 0.306 7.231 4.462 8.537 6.954 13.088 2.52 4.569 10.451 7.784 11.674 7.703z"/>
+ <path fill="#bababa" d="m193.167 94.529c10.345-0.923 14.638-5.611 16.059-12.258 1.436-6.977 1.636-13.744-2.782-19.995-3.41-5.127-6.135-6.286-11.832-6.746-9.736-0.829-16.025 2.679-18.347 7.293-1.572 3.356-1.941 5.103-1.694 11.011 0.322 7.227 4.484 8.461 6.973 13.014 2.519 4.579 10.4 7.764 11.623 7.681z"/>
+ <path fill="#c1c1c1" d="m193.172 94.488c10.304-0.903 14.64-5.637 16.014-12.227 1.409-7.022 1.62-13.75-2.762-19.804-3.308-4.86-6.044-6.006-11.662-6.462-9.705-0.826-16.135 2.359-18.466 6.935-1.498 3.164-1.945 5.141-1.689 10.958 0.338 7.223 4.506 8.385 6.991 12.939 2.519 4.59 10.351 7.744 11.574 7.661z"/>
+ <path fill="#c9c9c9" d="m193.177 94.447c10.262-0.882 14.641-5.663 15.967-12.196 1.383-7.068 1.605-13.756-2.738-19.612-3.206-4.593-5.954-5.727-11.496-6.179-9.673-0.823-16.242 2.04-18.581 6.577-1.425 2.972-1.952 5.179-1.687 10.906 0.354 7.219 4.526 8.308 7.01 12.865 2.52 4.598 10.302 7.723 11.525 7.639z"/>
+ <path fill="#d1d1d1" d="m193.182 94.405c10.221-0.861 14.643-5.688 15.922-12.165 1.355-7.113 1.591-13.762-2.717-19.42-3.104-4.326-5.864-5.448-11.327-5.895-9.644-0.82-16.352 1.721-18.698 6.219-1.353 2.779-1.959 5.217-1.684 10.853 0.369 7.214 4.549 8.232 7.028 12.79 2.521 4.609 10.254 7.703 11.476 7.618z"/>
+ <path fill="#d8d8d8" d="m193.187 94.364c10.179-0.841 14.645-5.714 15.876-12.133 1.33-7.158 1.576-13.768-2.694-19.229-3.001-4.059-5.773-5.168-11.16-5.612-9.61-0.817-16.459 1.401-18.813 5.861-1.279 2.586-1.965 5.256-1.682 10.8 0.387 7.21 4.571 8.156 7.049 12.715 2.519 4.619 10.202 7.684 11.424 7.598z"/>
+ <path fill="#e0e0e0" d="m193.193 94.322c10.137-0.82 14.646-5.74 15.83-12.103 1.303-7.203 1.561-13.773-2.673-19.037-2.898-3.792-5.684-4.889-10.991-5.328-9.58-0.813-16.568 1.082-18.931 5.502-1.206 2.395-1.972 5.294-1.679 10.747 0.403 7.207 4.592 8.08 7.067 12.641 2.521 4.631 10.154 7.666 11.377 7.578z"/>
+ <path fill="#e8e8e8" d="m193.198 94.281c10.096-0.799 14.648-5.766 15.785-12.071 1.275-7.249 1.545-13.779-2.651-18.845-2.796-3.525-5.593-4.609-10.823-5.044-9.549-0.81-16.677 0.762-19.048 5.145-1.133 2.202-1.978 5.333-1.675 10.694 0.419 7.202 4.614 8.003 7.086 12.566 2.52 4.638 10.103 7.643 11.326 7.555z"/>
+ <path fill="#efefef" d="m193.203 94.239c10.055-0.778 14.65-5.792 15.739-12.04 1.25-7.293 1.531-13.785-2.629-18.653-2.694-3.258-5.502-4.33-10.655-4.761-9.517-0.807-16.785 0.443-19.165 4.786-1.059 2.01-1.983 5.372-1.671 10.642 0.435 7.198 4.636 7.928 7.104 12.492 2.52 4.649 10.055 7.624 11.277 7.534z"/>
+ <path fill="#f7f7f7" d="m193.208 94.198c10.014-0.757 14.652-5.817 15.694-12.009 1.223-7.339 1.516-13.792-2.607-18.462-2.592-2.991-5.413-4.05-10.486-4.478-9.487-0.804-16.895 0.124-19.282 4.428-0.986 1.817-1.989 5.41-1.668 10.589 0.451 7.194 4.657 7.851 7.123 12.417 2.519 4.661 10.004 7.605 11.226 7.515z"/>
+ <path fill="#fff" d="m193.213 94.156c9.973-0.737 14.654-5.843 15.648-11.978 1.197-7.384 1.501-13.797-2.585-18.27-2.489-2.724-5.322-3.771-10.319-4.194-9.455-0.801-17.002-0.196-19.397 4.07-0.913 1.625-1.996 5.448-1.665 10.536 0.467 7.19 4.679 7.775 7.142 12.342 2.519 4.671 9.954 7.586 11.176 7.494z"/>
+ </g>
+ <path d="m179.841 74.4585c5.4 0 8.568 4.824 9.648 11.016 0.432 2.808-0.216 6.048-1.944 8.28-1.944 2.592-5.4 4.176-8.208 4.176-2.664 0-5.688 0.432-7.271-1.728-1.584-2.232-1.944-7.2-1.944-10.728 0-3.96 1.152-6.768 3.168-9 1.511-1.657 4.247-2.016 6.551-2.016z"/>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m192.591 66.68c0.98-0.653 2.612 0 4.489 2.122 2.039 2.285 2.938 4.08 0.489 5.385-1.877 0.98-2.448-1.958-3.59-3.182-1.795-1.959-3.346-3.02-1.388-4.325z"/>
+ <path fill="#070707" d="m192.631 66.738c0.96-0.649 2.573 0 4.423 2.09 2.009 2.251 2.864 4.02 0.481 5.305-1.837 0.977-2.403-1.929-3.525-3.135-1.768-1.925-3.296-2.965-1.379-4.26z"/>
+ <path fill="#0f0f0f" d="m192.671 66.797c0.939-0.645 2.534 0 4.356 2.059 1.978 2.217 2.792 3.958 0.474 5.225-1.798 0.974-2.357-1.9-3.46-3.087-1.742-1.895-3.247-2.913-1.37-4.197z"/>
+ <path fill="#161616" d="m192.711 66.855c0.919-0.641 2.495 0 4.289 2.027 1.948 2.184 2.721 3.898 0.467 5.146-1.759 0.971-2.313-1.871-3.396-3.041-1.715-1.861-3.197-2.858-1.36-4.132z"/>
+ <path fill="#1e1e1e" d="m192.751 66.914c0.899-0.637 2.457 0 4.223 1.996 1.918 2.149 2.647 3.838 0.46 5.065-1.72 0.968-2.269-1.842-3.331-2.993-1.689-1.83-3.148-2.805-1.352-4.068z"/>
+ <path fill="#262626" d="m192.791 66.973c0.878-0.633 2.418 0 4.155 1.964 1.888 2.116 2.576 3.777 0.453 4.986-1.68 0.965-2.224-1.813-3.267-2.946-1.661-1.798-3.097-2.752-1.341-4.004z"/>
+ <path fill="#2d2d2d" d="m192.831 67.031c0.858-0.629 2.379 0 4.089 1.933 1.857 2.082 2.503 3.717 0.445 4.906-1.641 0.961-2.178-1.784-3.201-2.898-1.636-1.767-3.048-2.7-1.333-3.941z"/>
+ <path fill="#353535" d="m192.87 67.09c0.838-0.625 2.341 0 4.023 1.902 1.827 2.047 2.431 3.656 0.438 4.826-1.601 0.958-2.133-1.755-3.137-2.852-1.608-1.735-2.998-2.646-1.324-3.876z"/>
+ <path fill="#3d3d3d" d="m192.91 67.148c0.818-0.621 2.302 0 3.956 1.87 1.797 2.014 2.359 3.596 0.431 4.746-1.562 0.956-2.088-1.726-3.071-2.804-1.583-1.702-2.95-2.592-1.316-3.812z"/>
+ <path fill="#444" d="m192.95 67.207c0.798-0.617 2.263 0 3.889 1.839 1.768 1.98 2.287 3.535 0.425 4.666-1.523 0.952-2.043-1.697-3.008-2.757-1.556-1.671-2.899-2.539-1.306-3.748z"/>
+ <path fill="#4c4c4c" d="m192.99 67.266c0.777-0.614 2.224 0 3.823 1.807 1.735 1.946 2.214 3.474 0.416 4.586-1.483 0.949-1.998-1.667-2.942-2.709-1.529-1.639-2.85-2.486-1.297-3.684z"/>
+ <path fill="#545454" d="m193.03 67.325c0.757-0.61 2.185 0 3.756 1.775 1.706 1.912 2.143 3.414 0.409 4.506-1.444 0.946-1.953-1.639-2.878-2.663-1.502-1.606-2.799-2.431-1.287-3.618z"/>
+ <path fill="#5b5b5b" d="m193.07 67.383c0.736-0.605 2.146 0 3.688 1.744 1.677 1.878 2.07 3.353 0.402 4.426-1.405 0.943-1.908-1.609-2.813-2.615-1.475-1.575-2.749-2.378-1.277-3.555z"/>
+ <path fill="#636363" d="m193.11 67.442c0.716-0.602 2.106 0 3.622 1.712 1.646 1.844 1.998 3.293 0.395 4.347-1.364 0.94-1.862-1.581-2.748-2.568-1.449-1.543-2.701-2.326-1.269-3.491z"/>
+ <path fill="#6b6b6b" d="m193.15 67.5c0.696-0.598 2.069 0 3.556 1.681 1.615 1.811 1.925 3.232 0.387 4.267-1.325 0.937-1.818-1.552-2.683-2.521-1.423-1.511-2.651-2.272-1.26-3.427z"/>
+ <path fill="#727272" d="m193.19 67.559c0.675-0.594 2.03 0 3.489 1.649 1.585 1.777 1.853 3.172 0.38 4.187-1.287 0.935-1.774-1.522-2.619-2.473-1.396-1.48-2.601-2.219-1.25-3.363z"/>
+ <path fill="#7a7a7a" d="m193.23 67.618c0.654-0.59 1.991 0 3.422 1.618 1.555 1.743 1.781 3.111 0.373 4.107-1.247 0.931-1.729-1.494-2.554-2.426-1.369-1.448-2.551-2.166-1.241-3.299z"/>
+ <path fill="#828282" d="m193.269 67.677c0.635-0.586 1.953 0 3.355 1.586 1.525 1.708 1.709 3.05 0.366 4.026-1.208 0.928-1.684-1.464-2.489-2.378-1.342-1.416-2.501-2.112-1.232-3.234z"/>
+ <path fill="#898989" d="m193.309 67.735c0.614-0.582 1.914 0 3.29 1.555 1.493 1.675 1.636 2.99 0.357 3.947-1.169 0.925-1.639-1.435-2.424-2.332-1.316-1.384-2.452-2.058-1.223-3.17z"/>
+ <path fill="#919191" d="m193.349 67.794c0.595-0.578 1.875 0 3.223 1.523 1.464 1.641 1.564 2.93 0.351 3.867-1.129 0.922-1.594-1.406-2.359-2.284-1.29-1.352-2.403-2.005-1.215-3.106z"/>
+ <path fill="#999" d="m193.389 67.853c0.573-0.574 1.836 0 3.155 1.492 1.435 1.607 1.492 2.869 0.345 3.787-1.091 0.919-1.55-1.377-2.295-2.237-1.263-1.32-2.353-1.953-1.205-3.042z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m165.498 69.906c1.693-0.654 3.012-0.69 5.63 1.036 3.166 2.088 1.705 5.245-0.779 4.601-2.146-0.556-2.417-0.681-4.391-1.086-3.101-0.648-3.641-3.322-0.46-4.551z"/>
+ <path fill="#050505" d="m165.564 70.033c1.658-0.629 2.973-0.656 5.555 1.026 3.066 2.009 1.654 5.012-0.805 4.38-2.131-0.547-2.345-0.656-4.284-1.052-3.055-0.634-3.587-3.173-0.466-4.354z"/>
+ <path fill="#0a0a0a" d="m165.63 70.16c1.623-0.604 2.935-0.622 5.481 1.015 2.965 1.93 1.602 4.779-0.83 4.159-2.119-0.539-2.274-0.63-4.179-1.018-3.009-0.618-3.533-3.022-0.472-4.156z"/>
+ <path fill="#0f0f0f" d="m165.696 70.287c1.587-0.579 2.895-0.587 5.406 1.005 2.864 1.851 1.551 4.546-0.855 3.938-2.105-0.53-2.203-0.605-4.073-0.983-2.963-0.604-3.48-2.873-0.478-3.96z"/>
+ <path fill="#141414" d="m165.761 70.413c1.553-0.553 2.856-0.553 5.331 0.995 2.766 1.772 1.5 4.313-0.88 3.717-2.092-0.521-2.131-0.58-3.967-0.949-2.916-0.588-3.425-2.723-0.484-3.763z"/>
+ <path fill="#191919" d="m165.827 70.54c1.519-0.528 2.818-0.519 5.258 0.984 2.664 1.693 1.448 4.079-0.905 3.497-2.079-0.513-2.06-0.554-3.861-0.915-2.873-0.573-3.373-2.573-0.492-3.566z"/>
+ <path fill="#1e1e1e" d="m165.893 70.667c1.482-0.503 2.778-0.484 5.183 0.974 2.564 1.614 1.397 3.846-0.93 3.276-2.067-0.504-1.989-0.529-3.756-0.88-2.826-0.559-3.319-2.425-0.497-3.37z"/>
+ <path fill="#232323" d="m165.959 70.793c1.447-0.478 2.74-0.45 5.108 0.964 2.464 1.535 1.345 3.613-0.955 3.055-2.053-0.496-1.917-0.503-3.651-0.846-2.779-0.543-3.264-2.274-0.502-3.173z"/>
+ <path fill="#282828" d="m166.025 70.92c1.412-0.453 2.701-0.416 5.034 0.954 2.362 1.456 1.293 3.38-0.981 2.834-2.04-0.487-1.845-0.478-3.545-0.812-2.733-0.528-3.21-2.125-0.508-2.976z"/>
+ <path fill="#2d2d2d" d="m166.09 71.047c1.378-0.428 2.663-0.382 4.96 0.943 2.264 1.377 1.242 3.146-1.006 2.613-2.026-0.478-1.773-0.453-3.438-0.777-2.688-0.513-3.158-1.974-0.516-2.779z"/>
+ <path fill="#333" d="m166.156 71.173c1.343-0.402 2.624-0.347 4.885 0.933 2.163 1.298 1.191 2.914-1.029 2.392-2.015-0.47-1.703-0.428-3.334-0.743-2.642-0.498-3.104-1.824-0.522-2.582z"/>
+ <path fill="#383838" d="m166.222 71.3c1.307-0.377 2.585-0.313 4.81 0.922 2.063 1.219 1.14 2.681-1.055 2.171-2.001-0.461-1.631-0.402-3.229-0.708-2.594-0.483-3.048-1.674-0.526-2.385z"/>
+ <path fill="#3d3d3d" d="m166.288 71.427c1.272-0.352 2.546-0.279 4.736 0.913 1.962 1.14 1.088 2.447-1.081 1.95-1.988-0.452-1.56-0.377-3.122-0.674-2.55-0.469-2.995-1.526-0.533-2.189z"/>
+ <path fill="#424242" d="m166.354 71.554c1.236-0.327 2.507-0.245 4.661 0.902 1.861 1.061 1.037 2.214-1.106 1.729-1.974-0.444-1.488-0.352-3.016-0.64-2.504-0.453-2.942-1.375-0.539-1.991z"/>
+ <path fill="#474747" d="m166.419 71.68c1.203-0.302 2.469-0.21 4.587 0.892 1.762 0.982 0.986 1.98-1.13 1.508-1.962-0.435-1.417-0.326-2.911-0.606-2.458-0.437-2.888-1.224-0.546-1.794z"/>
+ <path fill="#4c4c4c" d="m166.485 71.807c1.167-0.276 2.429-0.176 4.513 0.882 1.66 0.903 0.935 1.748-1.156 1.288-1.948-0.426-1.345-0.301-2.805-0.572-2.412-0.423-2.834-1.076-0.552-1.598z"/>
+ <path fill="#515151" d="m166.551 71.934c1.133-0.251 2.391-0.142 4.438 0.871 1.56 0.824 0.883 1.515-1.181 1.067-1.936-0.417-1.274-0.275-2.699-0.537-2.366-0.408-2.781-0.926-0.558-1.401z"/>
+ <path fill="#565656" d="m166.617 72.061c1.097-0.227 2.351-0.108 4.363 0.861 1.46 0.745 0.831 1.281-1.206 0.846-1.922-0.409-1.202-0.25-2.594-0.503-2.319-0.393-2.726-0.777-0.563-1.204z"/>
+ <path fill="#5b5b5b" d="m166.683 72.187c1.062-0.201 2.312-0.073 4.289 0.851 1.358 0.666 0.778 1.048-1.231 0.625-1.91-0.4-1.131-0.225-2.489-0.469-2.274-0.377-2.672-0.626-0.569-1.007z"/>
+ <path fill="#606060" d="m166.748 72.314c1.027-0.176 2.274-0.04 4.215 0.84 1.26 0.587 0.729 0.815-1.256 0.404-1.896-0.392-1.06-0.2-2.383-0.435-2.228-0.361-2.619-0.475-0.576-0.809z"/>
+ <path fill="#666" d="m166.814 72.44c0.992-0.151 2.234-0.005 4.14 0.83 1.159 0.508 0.677 0.582-1.281 0.183-1.883-0.383-0.987-0.174-2.276-0.4-2.183-0.346-2.566-0.325-0.583-0.613z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#666" d="m159.99 128.249c-9.36 0.36-24.192-25.848-24.552-14.976-0.288 9.216 0.216 9.072 0.216 18 0 5.976-2.736 6.408-8.64 15.408-3.024 4.752-5.4 9.864-7.272 15.048-1.152 3.096-2.232 6.336-3.096 9.504-0.36 1.584-1.008 3.24-1.368 4.824-2.952 10.872-13.464 24.264-15.912 35.136-2.448 10.8-5.328 17.712-4.968 32.185 0.36 14.472 0.504 10.295 4.896 13.896 4.32 3.601 8.784 6.983 15.624 13.032 7.2 6.264 22.177 17.208 24.192 20.592 2.16 3.456 2.088 11.232 0.792 13.752-1.296 2.448-12.6 3.816-12.528 3.816-0.071 0 9.864 13.68 11.809 15.623 1.872 1.873 9.936 10.873 42.768 4.752 18.504-3.455 32.832-13.823 43.2-23.832 13.392-13.031 6.624-16.775 8.352-23.327 2.521-9.433 10.729-12.96 12.601-23.616 0.216-1.512 0.72-2.664 2.088-4.896 2.088-3.168 1.584-9.432 1.584-15.191 0-14.977-1.729-30.24-5.185-41.472-3.168-10.512-8.208-17.856-12.527-27.36-8.641-18.936-8.208-27.432-15.912-39.528-8.784-13.968-4.464-23.256-16.128-22.68-14.546 0.79-26.282 20.734-40.034 21.31z"/>
+ <path fill="#6d6d6d" d="m159.973 129.334c-9.281 0.353-23.746-25.511-24.242-15.179-0.316 8.755 0.1 8.678 0.03 17.247-0.15 5.87-2.953 6.637-8.727 15.481-3.013 4.763-5.273 9.812-6.993 14.877-0.968 3.253-1.56 6.422-2.43 9.526-0.415 1.642-1.497 3.187-2.185 5.042-3.254 10.78-13.545 24.182-15.961 34.877-2.466 10.81-5.37 17.694-4.961 32.141 0.366 14 0.395 10.177 4.773 13.816 4.283 3.616 8.839 7.069 15.662 13.103 7.183 6.248 22.237 17.216 24.243 20.588 2.149 3.444 2.131 11.317 0.844 13.823-1.284 2.439-12.579 3.875-12.508 3.875-0.071 0 9.815 13.566 11.757 15.508 1.87 1.87 9.902 10.809 42.678 4.704 18.524-3.455 33.124-13.753 43.078-23.856 12.789-12.762 6.107-16.773 7.826-23.291 2.513-9.416 11.277-12.961 13.143-23.602 0.216-1.508 0.754-2.654 2.113-4.876 2.096-3.202 1.561-9.447 1.582-15.185 0.067-15.027-1.705-30.234-5.159-41.434-3.171-10.483-8.204-17.817-12.515-27.305-8.624-18.906-8.221-27.415-15.933-39.474-8.586-13.613-4.601-22.583-16.011-21.99-14.374 0.826-26.375 21.016-40.104 21.584z"/>
+ <path fill="#757575" d="m159.955 130.419c-9.201 0.346-23.299-25.175-23.931-15.383-0.344 8.295-0.017 8.284-0.156 16.494-0.301 5.764-3.17 6.867-8.812 15.555-3.002 4.774-5.148 9.76-6.714 14.706-0.784 3.41-0.889 6.508-1.764 9.548-0.471 1.699-1.986 3.133-3.003 5.259-3.554 10.688-13.624 24.1-16.009 34.619-2.483 10.82-5.411 17.678-4.954 32.097 0.373 13.528 0.285 10.058 4.651 13.739 4.244 3.632 8.893 7.154 15.699 13.171 7.167 6.233 22.299 17.224 24.294 20.585 2.142 3.432 2.175 11.404 0.896 13.896-1.271 2.428-12.558 3.932-12.486 3.932-0.071 0 9.768 13.453 11.705 15.392 1.867 1.867 9.867 10.744 42.588 4.655 18.545-3.453 33.415-13.682 42.956-23.879 12.187-12.492 5.591-16.771 7.3-23.258 2.507-9.398 11.826-12.959 13.687-23.586 0.215-1.5 0.788-2.643 2.138-4.854 2.104-3.235 1.538-9.462 1.58-15.178 0.133-15.076-1.681-30.228-5.135-41.394-3.173-10.455-8.199-17.779-12.501-27.25-8.609-18.877-8.234-27.399-15.952-39.42-8.389-13.258-4.739-21.911-15.895-21.301-14.21 0.859-26.474 21.295-40.182 21.855z"/>
+ <path fill="#7c7c7c" d="m159.938 131.504c-9.122 0.338-22.854-24.838-23.622-15.586-0.37 7.833-0.131 7.89-0.341 15.741-0.452 5.657-3.388 7.096-8.899 15.628-2.99 4.785-5.021 9.708-6.433 14.535-0.602 3.566-0.218 6.594-1.099 9.57-0.526 1.756-2.475 3.08-3.82 5.477-3.854 10.596-13.703 24.016-16.057 34.361-2.501 10.829-5.453 17.66-4.948 32.052 0.38 13.059 0.177 9.939 4.529 13.66 4.208 3.648 8.948 7.239 15.739 13.242 7.149 6.217 22.358 17.232 24.345 20.581 2.13 3.42 2.216 11.489 0.946 13.968-1.259 2.417-12.538 3.99-12.466 3.99-0.072 0 9.718 13.34 11.653 15.275 1.865 1.864 9.833 10.681 42.498 4.607 18.565-3.453 33.706-13.609 42.834-23.902 11.583-12.223 5.074-16.771 6.774-23.223 2.499-9.382 12.375-12.959 14.229-23.57 0.215-1.496 0.821-2.633 2.162-4.834 2.111-3.271 1.516-9.478 1.578-15.173 0.199-15.125-1.657-30.221-5.109-41.354-3.177-10.427-8.196-17.741-12.488-27.195-8.594-18.848-8.247-27.383-15.972-39.366-8.192-12.903-4.877-21.239-15.779-20.612-14.041 0.894-26.569 21.576-40.254 22.128z"/>
+ <path fill="#848484" d="m159.921 132.589c-9.043 0.331-22.406-24.502-23.312-15.79-0.398 7.373-0.247 7.496-0.527 14.988-0.602 5.551-3.604 7.326-8.984 15.702-2.98 4.796-4.896 9.656-6.154 14.364-0.417 3.723 0.455 6.679-0.432 9.592-0.582 1.813-2.964 3.026-4.639 5.694-4.153 10.504-13.782 23.936-16.104 34.104-2.519 10.838-5.495 17.643-4.941 32.008 0.387 12.586 0.067 9.819 4.407 13.582 4.171 3.664 9.002 7.324 15.777 13.311 7.132 6.201 22.419 17.24 24.396 20.576 2.12 3.41 2.259 11.578 0.998 14.041-1.247 2.408-12.517 4.049-12.446 4.049-0.07 0 9.67 13.227 11.604 15.16 1.861 1.861 9.798 10.615 42.409 4.558 18.584-3.45 33.996-13.538 42.711-23.926 10.979-11.952 4.557-16.769 6.248-23.187 2.491-9.367 12.924-12.959 14.771-23.557 0.215-1.49 0.856-2.622 2.188-4.813 2.118-3.305 1.491-9.494 1.575-15.166 0.267-15.174-1.635-30.215-5.086-41.314-3.179-10.399-8.19-17.703-12.473-27.141-8.579-18.818-8.262-27.366-15.994-39.312-7.993-12.547-5.013-20.565-15.661-19.922-13.876 0.927-26.669 21.855-40.331 22.399z"/>
+ <path fill="#8c8c8c" d="m159.903 133.674c-8.963 0.323-21.961-24.165-23.001-15.994-0.426 6.912-0.363 7.102-0.713 14.236-0.753 5.445-3.821 7.554-9.071 15.775-2.969 4.807-4.768 9.604-5.875 14.192-0.232 3.881 1.128 6.766 0.234 9.615-0.638 1.87-3.452 2.972-5.455 5.911-4.455 10.413-13.862 23.853-16.153 33.845-2.537 10.849-5.537 17.625-4.935 31.963 0.393 12.115-0.042 9.701 4.285 13.505 4.133 3.68 9.057 7.409 15.814 13.38 7.116 6.188 22.48 17.248 24.447 20.574 2.109 3.398 2.301 11.662 1.049 14.113-1.235 2.396-12.496 4.104-12.425 4.104-0.071 0 9.622 13.114 11.552 15.045 1.86 1.858 9.763 10.552 42.319 4.509 18.604-3.449 34.288-13.467 42.589-23.949 10.377-11.682 4.04-16.766 5.721-23.15 2.486-9.35 13.474-12.959 15.316-23.542 0.214-1.483 0.89-2.611 2.213-4.793 2.126-3.339 1.468-9.507 1.573-15.158 0.333-15.224-1.611-30.208-5.062-41.276-3.181-10.37-8.186-17.664-12.459-27.085-8.563-18.789-8.275-27.35-16.014-39.258-7.796-12.192-5.151-19.893-15.545-19.233-13.707 0.961-26.763 22.134-40.404 22.671z"/>
+ <path fill="#939393" d="m159.886 134.759c-8.885 0.316-21.516-23.829-22.691-16.197-0.454 6.451-0.479 6.708-0.899 13.482-0.903 5.339-4.038 7.784-9.157 15.849-2.957 4.818-4.642 9.552-5.595 14.021-0.05 4.037 1.799 6.852 0.9 9.637-0.693 1.928-3.941 2.919-6.273 6.129-4.756 10.32-13.941 23.77-16.201 33.587-2.555 10.858-5.579 17.608-4.928 31.92 0.399 11.644-0.151 9.581 4.162 13.424 4.096 3.697 9.111 7.494 15.854 13.451 7.099 6.17 22.541 17.256 24.498 20.569 2.1 3.387 2.344 11.75 1.101 14.186-1.223 2.387-12.476 4.163-12.404 4.163-0.071 0 9.573 13.001 11.5 14.929 1.857 1.856 9.729 10.488 42.229 4.461 18.625-3.449 34.579-13.396 42.467-23.973 9.774-11.412 3.523-16.764 5.195-23.115 2.479-9.334 14.022-12.959 15.858-23.527 0.214-1.479 0.924-2.601 2.238-4.772 2.134-3.373 1.445-9.522 1.571-15.151 0.399-15.273-1.587-30.201-5.036-41.237-3.185-10.342-8.184-17.625-12.446-27.03-8.548-18.76-8.288-27.333-16.034-39.204-7.598-11.837-5.289-19.221-15.428-18.544-13.543 0.994-26.863 22.413-40.481 22.942z"/>
+ <path fill="#9b9b9b" d="m159.868 135.844c-8.805 0.308-21.068-23.492-22.381-16.401-0.481 5.991-0.594 6.314-1.085 12.73-1.053 5.232-4.253 8.013-9.243 15.922-2.946 4.829-4.515 9.5-5.314 13.85 0.133 4.194 2.471 6.937 1.565 9.658-0.749 1.986-4.43 2.866-7.091 6.347-5.056 10.229-14.021 23.689-16.249 33.329-2.572 10.868-5.621 17.591-4.921 31.876 0.405 11.172-0.261 9.463 4.04 13.346 4.058 3.713 9.166 7.58 15.892 13.521 7.082 6.155 22.601 17.265 24.548 20.567 2.092 3.373 2.388 11.834 1.152 14.256-1.21 2.377-12.454 4.222-12.383 4.222-0.071 0 9.523 12.888 11.45 14.813 1.854 1.854 9.692 10.424 42.138 4.412 18.645-3.447 34.871-13.324 42.345-23.996 9.171-11.143 3.007-16.762 4.669-23.08 2.472-9.317 14.572-12.959 16.401-23.514 0.214-1.473 0.958-2.588 2.265-4.75 2.142-3.408 1.421-9.539 1.568-15.145 0.466-15.324-1.564-30.196-5.012-41.198-3.187-10.313-8.179-17.587-12.433-26.976-8.533-18.73-8.301-27.316-16.054-39.149-7.401-11.482-5.426-18.548-15.313-17.855-13.373 1.029-26.958 22.694-40.554 23.215z"/>
+ <path fill="#a3a3a3" d="m159.851 136.929c-8.727 0.301-20.622-23.156-22.071-16.604-0.509 5.529-0.71 5.919-1.271 11.976-1.203 5.126-4.47 8.243-9.328 15.996-2.936 4.84-4.39 9.448-5.036 13.679 0.316 4.351 3.143 7.023 2.231 9.68-0.804 2.043-4.919 2.812-7.908 6.563-5.356 10.137-14.101 23.607-16.298 33.072-2.589 10.877-5.661 17.574-4.913 31.832 0.412 10.699-0.37 9.342 3.918 13.268 4.021 3.729 9.221 7.664 15.93 13.59 7.064 6.139 22.661 17.271 24.599 20.563 2.081 3.363 2.43 11.922 1.204 14.33-1.198 2.365-12.434 4.278-12.363 4.278-0.07 0 9.477 12.774 11.399 14.697 1.851 1.851 9.659 10.36 42.048 4.364 18.666-3.447 35.162-13.254 42.223-24.021 8.568-10.873 2.49-16.761 4.144-23.045 2.464-9.301 15.121-12.958 16.943-23.498 0.215-1.467 0.992-2.579 2.29-4.729 2.148-3.441 1.398-9.553 1.566-15.139 0.532-15.373-1.541-30.189-4.987-41.158-3.188-10.285-8.174-17.549-12.419-26.921-8.518-18.701-8.313-27.3-16.073-39.096-7.204-11.126-5.564-17.875-15.196-17.165-13.21 1.064-27.058 22.975-40.632 23.488z"/>
+ <path fill="#aaa" d="m159.834 138.014c-8.646 0.293-20.176-22.819-21.761-16.808-0.536 5.069-0.826 5.526-1.457 11.224-1.354 5.02-4.687 8.472-9.416 16.069-2.924 4.851-4.262 9.396-4.756 13.508 0.501 4.507 3.814 7.109 2.897 9.702-0.858 2.1-5.406 2.759-8.725 6.782-5.657 10.045-14.181 23.524-16.347 32.812-2.606 10.888-5.703 17.557-4.906 31.787 0.418 10.229-0.479 9.225 3.795 13.189 3.984 3.745 9.275 7.749 15.968 13.66 7.048 6.124 22.723 17.279 24.651 20.559 2.07 3.352 2.472 12.008 1.255 14.402-1.186 2.355-12.414 4.337-12.343 4.337-0.071 0 9.428 12.66 11.348 14.581 1.85 1.848 9.624 10.297 41.958 4.314 18.687-3.444 35.453-13.18 42.102-24.043 7.965-10.602 1.973-16.758 3.616-23.01 2.457-9.283 15.67-12.957 17.487-23.482 0.214-1.461 1.026-2.568 2.315-4.709 2.155-3.477 1.375-9.568 1.563-15.131 0.6-15.424-1.518-30.184-4.963-41.119-3.192-10.257-8.17-17.511-12.405-26.866-8.502-18.672-8.328-27.284-16.095-39.042-7.005-10.771-5.701-17.203-15.078-16.476-13.04 1.098-27.152 23.255-40.703 23.76z"/>
+ <path fill="#b2b2b2" d="m159.816 139.099c-8.567 0.286-19.729-22.483-21.45-17.012-0.563 4.608-0.942 5.132-1.643 10.471-1.506 4.914-4.904 8.701-9.502 16.143-2.913 4.862-4.137 9.344-4.477 13.336 0.685 4.665 4.486 7.195 3.564 9.725-0.915 2.157-5.897 2.705-9.543 6.999-5.958 9.953-14.262 23.443-16.396 32.554-2.624 10.898-5.745 17.54-4.9 31.744 0.426 9.757-0.588 9.105 3.674 13.111 3.945 3.761 9.33 7.834 16.006 13.729 7.032 6.109 22.783 17.288 24.702 20.557 2.06 3.338 2.515 12.094 1.306 14.473-1.173 2.346-12.392 4.395-12.321 4.395-0.07 0 9.379 12.549 11.296 14.465 1.847 1.848 9.591 10.234 41.868 4.268 18.706-3.444 35.745-13.11 41.979-24.066 7.361-10.332 1.456-16.757 3.091-22.974 2.45-9.269 16.219-12.958 18.03-23.47 0.213-1.455 1.06-2.557 2.34-4.688 2.164-3.509 1.352-9.583 1.562-15.124 0.665-15.473-1.494-30.177-4.938-41.08-3.195-10.228-8.166-17.472-12.393-26.811-8.486-18.642-8.341-27.267-16.114-38.987-6.809-10.416-5.838-16.531-14.962-15.787-12.873 1.129-27.25 23.531-40.779 24.029z"/>
+ <path fill="#bababa" d="m159.799 140.184c-8.487 0.279-19.282-22.146-21.141-17.215-0.591 4.147-1.057 4.737-1.828 9.717-1.656 4.808-5.121 8.931-9.588 16.217-2.902 4.873-4.01 9.292-4.197 13.165 0.868 4.822 5.158 7.281 4.23 9.747-0.971 2.215-6.385 2.651-10.361 7.216-6.258 9.861-14.339 23.36-16.442 32.297-2.643 10.906-5.787 17.521-4.894 31.699 0.432 9.285-0.697 8.986 3.552 13.032 3.908 3.776 9.384 7.919 16.043 13.799 7.016 6.093 22.845 17.296 24.753 20.552 2.051 3.328 2.559 12.18 1.358 14.547-1.161 2.334-12.372 4.451-12.301 4.451-0.071 0 9.33 12.436 11.245 14.35 1.844 1.844 9.555 10.17 41.777 4.219 18.727-3.443 36.036-13.039 41.857-24.09 6.759-10.063 0.939-16.756 2.565-22.939 2.442-9.25 16.768-12.957 18.572-23.453 0.213-1.451 1.095-2.547 2.365-4.668 2.171-3.543 1.329-9.599 1.56-15.117 0.732-15.522-1.471-30.172-4.913-41.042-3.197-10.2-8.161-17.433-12.379-26.756-8.471-18.612-8.354-27.25-16.135-38.933-6.609-10.061-5.976-15.858-14.845-15.098-12.706 1.165-27.347 23.813-40.853 24.303z"/>
+ <path fill="#c1c1c1" d="m159.781 141.269c-8.408 0.271-18.837-21.81-20.83-17.419-0.619 3.687-1.173 4.344-2.014 8.965-1.808 4.701-5.338 9.16-9.674 16.29-2.892 4.884-3.885 9.24-3.918 12.994 1.052 4.978 5.829 7.367 4.896 9.769-1.026 2.272-6.874 2.598-11.178 7.434-6.56 9.769-14.419 23.277-16.491 32.039-2.66 10.916-5.829 17.504-4.887 31.656 0.438 8.813-0.807 8.867 3.43 12.953 3.87 3.793 9.438 8.004 16.082 13.868 6.997 6.077 22.904 17.304 24.803 20.55 2.041 3.314 2.601 12.266 1.409 14.617-1.149 2.324-12.351 4.51-12.28 4.51-0.07 0 9.282 12.321 11.194 14.233 1.841 1.842 9.521 10.106 41.688 4.17 18.746-3.44 36.326-12.967 41.734-24.112 6.156-9.793 0.423-16.754 2.038-22.904 2.438-9.235 17.318-12.957 19.117-23.438 0.212-1.444 1.128-2.536 2.39-4.647 2.18-3.578 1.306-9.613 1.558-15.11 0.799-15.571-1.447-30.165-4.889-41.002-3.2-10.172-8.156-17.395-12.364-26.701-8.456-18.583-8.367-27.234-16.155-38.88-6.413-9.705-6.114-15.185-14.729-14.408-12.541 1.197-27.445 24.091-40.93 24.573z"/>
+ <path fill="#c9c9c9" d="m159.764 142.354c-8.329 0.264-18.392-21.473-20.521-17.622-0.646 3.225-1.289 3.949-2.2 8.211-1.957 4.596-5.555 9.39-9.761 16.364-2.879 4.895-3.757 9.188-3.638 12.823 1.235 5.135 6.502 7.453 5.562 9.791-1.081 2.329-7.362 2.544-11.995 7.651-6.859 9.677-14.499 23.195-16.54 31.78-2.677 10.927-5.87 17.488-4.879 31.611 0.444 8.344-0.916 8.748 3.307 12.875 3.834 3.81 9.492 8.09 16.121 13.939 6.98 6.061 22.965 17.311 24.854 20.545 2.031 3.303 2.643 12.352 1.461 14.69-1.137 2.313-12.33 4.567-12.26 4.567-0.07 0 9.233 12.209 11.143 14.117 1.839 1.84 9.486 10.043 41.599 4.122 18.767-3.44 36.618-12.896 41.612-24.137 5.554-9.522-0.094-16.751 1.513-22.868 2.43-9.219 17.866-12.957 19.659-23.424 0.213-1.439 1.162-2.525 2.415-4.627 2.188-3.612 1.282-9.629 1.556-15.104 0.865-15.621-1.424-30.158-4.864-40.962-3.202-10.144-8.153-17.357-12.351-26.646-8.441-18.554-8.381-27.218-16.176-38.826-6.216-9.35-6.251-14.513-14.612-13.719-12.374 1.235-27.543 24.375-41.005 24.849z"/>
+ <path fill="#d1d1d1" d="m159.747 143.439c-8.25 0.256-17.944-21.137-20.21-17.826-0.675 2.765-1.406 3.555-2.386 7.459-2.108 4.489-5.772 9.619-9.847 16.437-2.869 4.906-3.631 9.136-3.358 12.652 1.419 5.292 7.174 7.538 6.228 9.812-1.137 2.387-7.852 2.491-12.813 7.869-7.161 9.586-14.579 23.114-16.588 31.522-2.695 10.938-5.912 17.471-4.873 31.568 0.451 7.871-1.025 8.629 3.185 12.797 3.796 3.824 9.547 8.174 16.158 14.008 6.964 6.047 23.026 17.32 24.905 20.541 2.021 3.292 2.686 12.439 1.513 14.764-1.125 2.303-12.31 4.625-12.239 4.625-0.07 0 9.186 12.094 11.092 14.002 1.836 1.836 9.45 9.978 41.509 4.072 18.786-3.439 36.909-12.824 41.49-24.16 4.948-9.252-0.611-16.748 0.985-22.832 2.423-9.203 18.415-12.957 20.203-23.41 0.212-1.434 1.196-2.514 2.44-4.605 2.193-3.646 1.259-9.645 1.553-15.098 0.932-15.67-1.4-30.151-4.84-40.922-3.205-10.115-8.148-17.319-12.336-26.592-8.427-18.524-8.396-27.201-16.197-38.771-6.017-8.995-6.388-13.84-14.495-13.03-12.207 1.266-27.64 24.652-41.079 25.118z"/>
+ <path fill="#d8d8d8" d="m159.729 144.524c-8.17 0.249-17.498-20.8-19.9-18.03-0.702 2.304-1.521 3.162-2.571 6.706-2.259 4.383-5.988 9.848-9.933 16.511-2.858 4.917-3.504 9.084-3.079 12.48 1.604 5.449 7.846 7.625 6.895 9.835-1.193 2.444-8.342 2.438-13.631 8.087-7.461 9.493-14.658 23.031-16.637 31.262-2.712 10.947-5.953 17.455-4.865 31.524 0.458 7.399-1.135 8.511 3.063 12.718 3.758 3.842 9.601 8.26 16.196 14.078 6.946 6.031 23.087 17.328 24.956 20.538 2.011 3.28 2.729 12.524 1.563 14.835-1.112 2.293-12.289 4.684-12.218 4.684-0.071 0 9.136 11.981 11.04 13.886 1.834 1.834 9.417 9.913 41.419 4.024 18.807-3.438 37.2-12.752 41.368-24.184 4.346-8.982-1.128-16.747 0.46-22.798 2.416-9.187 18.964-12.956 20.746-23.394 0.211-1.429 1.229-2.504 2.465-4.586 2.202-3.681 1.236-9.658 1.551-15.091 0.998-15.72-1.377-30.146-4.814-40.884-3.208-10.086-8.145-17.28-12.323-26.536-8.411-18.495-8.408-27.185-16.217-38.717-5.82-8.64-6.526-13.168-14.38-12.341-12.04 1.303-27.736 24.934-41.154 25.393z"/>
+ <path fill="#e0e0e0" d="m159.712 145.609c-8.091 0.241-17.052-20.464-19.59-18.233-0.729 1.843-1.637 2.767-2.757 5.953-2.409 4.276-6.206 10.077-10.02 16.584-2.847 4.928-3.378 9.032-2.8 12.309 1.787 5.606 8.519 7.711 7.561 9.857-1.248 2.502-8.829 2.384-14.448 8.304-7.761 9.402-14.738 22.95-16.684 31.006-2.731 10.955-5.996 17.436-4.859 31.48 0.464 6.928-1.244 8.389 2.939 12.639 3.722 3.857 9.656 8.344 16.234 14.148 6.932 6.014 23.148 17.336 25.008 20.533 2 3.268 2.771 12.611 1.615 14.907-1.1 2.282-12.268 4.741-12.198 4.741-0.069 0 9.089 11.867 10.989 13.77 1.831 1.831 9.382 9.85 41.329 3.977 18.827-3.438 37.492-12.683 41.246-24.207 3.743-8.715-1.646-16.746-0.066-22.762 2.409-9.171 19.514-12.957 21.289-23.381 0.211-1.422 1.265-2.494 2.49-4.564 2.21-3.715 1.213-9.674 1.549-15.084 1.065-15.77-1.354-30.139-4.791-40.844-3.21-10.058-8.14-17.241-12.309-26.481-8.396-18.466-8.421-27.168-16.237-38.664-5.622-8.284-6.663-12.495-14.262-11.651-11.872 1.335-27.833 25.212-41.228 25.663z"/>
+ <path fill="#e8e8e8" d="m159.694 146.694c-8.012 0.234-16.605-20.127-19.279-18.437-0.757 1.383-1.753 2.373-2.943 5.2-2.56 4.171-6.423 10.307-10.105 16.658-2.835 4.939-3.251 8.979-2.52 12.138 1.97 5.763 9.189 7.796 8.226 9.879-1.303 2.559-9.318 2.33-15.265 8.521-8.063 9.31-14.818 22.867-16.733 30.748-2.748 10.967-6.037 17.419-4.853 31.436 0.472 6.457-1.353 8.271 2.818 12.562 3.685 3.873 9.711 8.429 16.273 14.218 6.913 6 23.207 17.344 25.058 20.529 1.991 3.257 2.814 12.697 1.666 14.98-1.087 2.271-12.247 4.799-12.177 4.799-0.07 0 9.04 11.755 10.938 13.654 1.829 1.828 9.349 9.785 41.239 3.926 18.847-3.435 37.783-12.609 41.124-24.229 3.14-8.444-2.161-16.743-0.592-22.728 2.401-9.152 20.062-12.955 21.831-23.364 0.211-1.417 1.298-2.483 2.516-4.544 2.217-3.748 1.19-9.689 1.547-15.076 1.132-15.82-1.331-30.133-4.766-40.806-3.213-10.03-8.136-17.203-12.296-26.427-8.38-18.436-8.435-27.151-16.257-38.609-5.425-7.929-6.802-11.822-14.146-10.962-11.706 1.368-27.931 25.491-41.304 25.934z"/>
+ <path fill="#efefef" d="m159.677 147.779c-7.934 0.226-16.16-19.791-18.97-18.64-0.785 0.921-1.869 1.979-3.13 4.447-2.71 4.064-6.639 10.536-10.19 16.731-2.824 4.95-3.125 8.928-2.24 11.967 2.152 5.919 9.86 7.882 8.892 9.901-1.358 2.616-9.808 2.277-16.083 8.739-8.363 9.218-14.896 22.784-16.781 30.489-2.766 10.977-6.079 17.402-4.846 31.393 0.478 5.984-1.462 8.152 2.696 12.482 3.646 3.889 9.765 8.514 16.311 14.287 6.896 5.983 23.269 17.352 25.109 20.526 1.98 3.245 2.855 12.782 1.718 15.052-1.076 2.262-12.227 4.857-12.156 4.857-0.07 0 8.991 11.641 10.887 13.537 1.826 1.826 9.313 9.723 41.148 3.879 18.868-3.434 38.074-12.538 41.002-24.254 2.537-8.174-2.678-16.741-1.119-22.69 2.396-9.138 20.612-12.957 22.375-23.351 0.212-1.412 1.332-2.473 2.541-4.523 2.226-3.783 1.166-9.704 1.545-15.07 1.197-15.869-1.307-30.125-4.741-40.766-3.215-10.002-8.131-17.165-12.282-26.372-8.365-18.407-8.447-27.135-16.277-38.555-5.228-7.574-6.938-11.15-14.029-10.272-11.541 1.402-28.029 25.771-41.38 26.206z"/>
+ <path fill="#f7f7f7" d="m159.66 148.864c-7.854 0.219-15.714-19.454-18.66-18.844-0.812 0.461-1.983 1.585-3.314 3.694-2.86 3.958-6.856 10.766-10.278 16.805-2.813 4.961-2.998 8.876-1.96 11.796 2.337 6.076 10.533 7.968 9.558 9.923-1.415 2.673-10.296 2.223-16.899 8.956-8.664 9.126-14.978 22.702-16.83 30.23-2.783 10.986-6.121 17.386-4.839 31.349 0.484 5.515-1.571 8.033 2.573 12.403 3.609 3.906 9.82 8.6 16.35 14.357 6.88 5.969 23.329 17.36 25.16 20.523 1.971 3.232 2.898 12.869 1.77 15.124-1.063 2.252-12.206 4.915-12.136 4.915-0.07 0 8.942 11.527 10.835 13.422 1.824 1.822 9.279 9.658 41.059 3.83 18.889-3.434 38.366-12.467 40.881-24.278 1.934-7.903-3.195-16.739-1.646-22.655 2.388-9.121 21.161-12.955 22.918-23.336 0.211-1.404 1.366-2.461 2.566-4.502 2.232-3.816 1.143-9.719 1.542-15.063 1.265-15.92-1.283-30.12-4.717-40.727-3.219-9.974-8.128-17.127-12.269-26.317-8.349-18.378-8.461-27.119-16.298-38.501-5.029-7.219-7.075-10.478-13.912-9.584-11.373 1.438-28.126 26.053-41.454 26.48z"/>
+ <path fill="#fff" d="m159.642 149.949c-7.774 0.211-15.268-19.118-18.35-19.048-0.84 0-2.1 1.191-3.501 2.941-3.011 3.852-7.072 10.995-10.363 16.878-2.803 4.972-2.872 8.824-1.682 11.625 2.521 6.233 11.205 8.054 10.225 9.945-1.471 2.731-10.785 2.17-17.719 9.174-8.964 9.034-15.056 22.621-16.877 29.973-2.801 10.995-6.163 17.368-4.832 31.304 0.49 5.043-1.681 7.914 2.451 12.325 3.571 3.923 9.874 8.685 16.387 14.427 6.863 5.953 23.391 17.368 25.211 20.521 1.962 3.221 2.942 12.954 1.821 15.196-1.051 2.24-12.185 4.972-12.115 4.972-0.069 0 8.895 11.416 10.784 13.307 1.821 1.82 9.244 9.595 40.97 3.781 18.907-3.431 38.656-12.396 40.758-24.302 1.331-7.633-3.712-16.736-2.171-22.619 2.381-9.104 21.71-12.956 23.461-23.321 0.21-1.399 1.399-2.45 2.591-4.481 2.24-3.852 1.12-9.734 1.54-15.057 1.331-15.968-1.26-30.113-4.692-40.688-3.221-9.945-8.123-17.088-12.255-26.262-8.334-18.348-8.474-27.102-16.318-38.447-4.832-6.863-7.213-9.805-13.796-8.894-11.205 1.469-28.222 26.33-41.528 26.75z"/>
+ </g>
+ <path fill="#995900" d="m152.553 88.8575c5.256-0.648 12.456 0.648 15.769 3.096 3.096 2.304 5.256 3.528 8.063 4.464 9.433 3.096 21.816 4.536 21.24 13.032-0.648 10.151-3.6 14.688-12.024 17.351-6.768 2.088-18.863 13.824-28.224 13.824-4.176 0-10.008 0.216-13.392-1.008-3.24-1.152-7.776-6.624-13.104-11.016-5.328-4.32-10.296-8.928-10.439-14.976-0.217-6.407 3.96-8.496 9.863-13.607 3.097-2.736 8.712-7.272 12.601-9.288 3.599-1.799 5.903-1.439 9.647-1.872z"/>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#9e5f00" d="m165.068 78.951c5.225-0.644 12.384 0.645 15.677 3.079 3.078 2.29 5.227 3.51 8.018 4.438 9.375 3.078 21.729 4.529 21.159 12.973-0.641 10.09-3.669 14.581-12.041 17.223-6.723 2.073-18.768 13.589-28.07 13.64-4.21 0.032-9.926 0.234-13.287-0.977-3.215-1.142-7.737-6.608-13.031-10.969-5.291-4.292-10.26-8.774-10.317-14.765-0.153-6.252 3.912-8.411 9.773-13.488 3.071-2.71 8.594-7.303 12.463-9.333 3.563-1.803 5.933-1.392 9.656-1.821z"/>
+ <path fill="#a36400" d="m165.177 79.044c5.195-0.641 12.313 0.64 15.587 3.06 3.06 2.278 5.194 3.494 7.971 4.413 9.317 3.06 21.641 4.522 21.078 12.914-0.634 10.027-3.737 14.474-12.058 17.094-6.678 2.057-18.673 13.352-27.919 13.454-4.241 0.064-9.842 0.252-13.18-0.945-3.19-1.133-7.7-6.592-12.96-10.921-5.254-4.264-10.222-8.622-10.192-14.555-0.093-6.099 3.863-8.329 9.681-13.369 3.048-2.685 8.478-7.335 12.328-9.379 3.526-1.804 5.963-1.338 9.664-1.766z"/>
+ <path fill="#a86a00" d="m165.287 79.138c5.165-0.637 12.241 0.637 15.496 3.043 3.042 2.264 5.165 3.476 7.924 4.387 9.26 3.042 21.556 4.515 20.998 12.854-0.627 9.968-3.805 14.368-12.074 16.967-6.633 2.042-18.576 13.117-27.766 13.27-4.276 0.096-9.759 0.27-13.075-0.914-3.165-1.123-7.661-6.577-12.887-10.874-5.217-4.236-10.187-8.468-10.069-14.345-0.03-5.943 3.815-8.244 9.589-13.249 3.023-2.66 8.36-7.366 12.191-9.424 3.49-1.808 5.993-1.291 9.673-1.715z"/>
+ <path fill="#ad7000" d="m165.396 79.23c5.135-0.633 12.17 0.633 15.404 3.025 3.025 2.251 5.137 3.46 7.88 4.361 9.201 3.025 21.467 4.508 20.917 12.796-0.62 9.905-3.874 14.26-12.093 16.837-6.586 2.027-18.479 12.882-27.611 13.086-4.311 0.127-9.677 0.287-12.971-0.883-3.14-1.113-7.622-6.561-12.814-10.826-5.18-4.208-10.148-8.315-9.945-14.135 0.031-5.789 3.768-8.16 9.497-13.129 2.999-2.635 8.244-7.398 12.055-9.47 3.454-1.808 6.023-1.24 9.681-1.662z"/>
+ <path fill="#b27600" d="m165.506 79.325c5.105-0.63 12.099 0.629 15.314 3.007 3.007 2.237 5.104 3.442 7.832 4.335 9.145 3.007 21.38 4.501 20.837 12.737-0.614 9.844-3.943 14.154-12.109 16.709-6.541 2.011-18.385 12.645-27.46 12.9-4.342 0.16-9.592 0.306-12.862-0.851-3.115-1.103-7.584-6.545-12.743-10.779-5.144-4.18-10.112-8.162-9.821-13.924 0.092-5.634 3.718-8.076 9.405-13.009 2.975-2.609 8.126-7.429 11.919-9.514 3.416-1.812 6.052-1.192 9.688-1.611z"/>
+ <path fill="#b77b00" d="m165.615 79.417c5.075-0.626 12.026 0.626 15.224 2.989 2.989 2.225 5.075 3.425 7.786 4.31 9.087 2.989 21.292 4.494 20.756 12.678-0.606 9.781-4.012 14.046-12.126 16.581-6.496 1.997-18.289 12.41-27.307 12.716-4.376 0.191-9.51 0.323-12.758-0.82-3.09-1.094-7.546-6.53-12.671-10.732-5.106-4.152-10.074-8.008-9.697-13.713 0.155-5.479 3.67-7.992 9.313-12.889 2.951-2.585 8.011-7.461 11.783-9.56 3.38-1.814 6.083-1.143 9.697-1.56z"/>
+ <path fill="#bc8100" d="m165.725 79.511c5.044-0.622 11.954 0.622 15.133 2.972 2.971 2.211 5.045 3.408 7.739 4.284 9.029 2.971 21.205 4.487 20.675 12.619-0.6 9.719-4.079 13.939-12.143 16.451-6.45 1.982-18.192 12.175-27.153 12.532-4.41 0.223-9.428 0.341-12.653-0.789-3.065-1.084-7.507-6.514-12.598-10.684-5.069-4.124-10.038-7.855-9.574-13.504 0.217-5.324 3.622-7.908 9.222-12.77 2.926-2.559 7.894-7.492 11.646-9.605 3.344-1.816 6.113-1.092 9.706-1.506z"/>
+ <path fill="#c18700" d="m165.834 79.604c5.015-0.618 11.883 0.619 15.043 2.954 2.953 2.198 5.015 3.391 7.693 4.259 8.972 2.953 21.118 4.48 20.594 12.559-0.593 9.66-4.147 13.833-12.159 16.324-6.405 1.967-18.098 11.94-27.002 12.347-4.441 0.255-9.343 0.359-12.546-0.757-3.04-1.074-7.469-6.498-12.526-10.637-5.032-4.096-10-7.701-9.45-13.293 0.278-5.169 3.574-7.823 9.13-12.649 2.903-2.534 7.776-7.524 11.511-9.651 3.306-1.821 6.141-1.044 9.712-1.456z"/>
+ <path fill="#c68d00" d="m165.944 79.697c4.984-0.615 11.811 0.614 14.952 2.936 2.935 2.184 4.983 3.374 7.646 4.233 8.915 2.935 21.031 4.473 20.515 12.5-0.586 9.597-4.218 13.726-12.177 16.195-6.36 1.951-18.002 11.703-26.849 12.162-4.476 0.287-9.261 0.377-12.441-0.726-3.015-1.064-7.431-6.482-12.453-10.589-4.995-4.068-9.965-7.549-9.326-13.083 0.34-5.015 3.524-7.741 9.038-12.531 2.878-2.508 7.658-7.555 11.374-9.696 3.269-1.82 6.171-0.992 9.721-1.401z"/>
+ <path fill="#cc9200" d="m166.054 79.791c4.952-0.61 11.738 0.611 14.86 2.918 2.918 2.172 4.954 3.357 7.601 4.207 8.857 2.918 20.942 4.466 20.432 12.442-0.578 9.536-4.285 13.62-12.192 16.066-6.314 1.936-17.906 11.468-26.696 11.978-4.509 0.319-9.178 0.394-12.335-0.696-2.989-1.054-7.393-6.466-12.382-10.541-4.959-4.04-9.928-7.395-9.202-12.873 0.401-4.859 3.477-7.655 8.945-12.411 2.854-2.482 7.542-7.586 11.239-9.741 3.233-1.824 6.201-0.943 9.73-1.349z"/>
+ <path fill="#d19800" d="m166.163 79.883c4.923-0.606 11.668 0.608 14.771 2.901 2.9 2.158 4.924 3.339 7.554 4.181 8.801 2.9 20.855 4.459 20.352 12.383-0.571 9.474-4.353 13.512-12.21 15.938-6.269 1.921-17.81 11.233-26.543 11.793-4.542 0.351-9.094 0.413-12.229-0.664-2.965-1.044-7.354-6.45-12.311-10.494-4.921-4.012-9.89-7.241-9.079-12.662 0.465-4.705 3.431-7.571 8.855-12.29 2.83-2.458 7.425-7.618 11.102-9.787 3.197-1.827 6.231-0.893 9.738-1.299z"/>
+ <path fill="#d69e00" d="m166.273 79.978c4.893-0.603 11.596 0.603 14.679 2.882 2.883 2.145 4.895 3.323 7.507 4.156 8.744 2.882 20.77 4.452 20.272 12.324-0.565 9.412-4.422 13.406-12.228 15.81-6.224 1.905-17.714 10.996-26.39 11.608-4.576 0.383-9.012 0.431-12.124-0.633-2.94-1.034-7.316-6.434-12.237-10.446-4.884-3.984-9.854-7.089-8.955-12.452 0.525-4.551 3.382-7.489 8.764-12.171 2.805-2.432 7.307-7.649 10.965-9.832 3.16-1.829 6.261-0.845 9.747-1.246z"/>
+ <path fill="#dba300" d="m166.382 80.07c4.863-0.599 11.525 0.6 14.59 2.865 2.864 2.131 4.862 3.305 7.461 4.13 8.686 2.864 20.682 4.445 20.19 12.264-0.559 9.352-4.491 13.299-12.244 15.681-6.179 1.89-17.619 10.761-26.237 11.423-4.608 0.415-8.929 0.449-12.018-0.601-2.915-1.024-7.277-6.418-12.166-10.399-4.847-3.956-9.815-6.935-8.831-12.241 0.587-4.396 3.333-7.404 8.671-12.051 2.782-2.407 7.191-7.681 10.83-9.878 3.123-1.829 6.29-0.793 9.754-1.193z"/>
+ <path fill="#e0a900" d="m166.492 80.164c4.832-0.595 11.453 0.596 14.498 2.847 2.847 2.118 4.833 3.289 7.414 4.104 8.629 2.846 20.595 4.438 20.111 12.205-0.553 9.29-4.56 13.193-12.262 15.553-6.134 1.875-17.522 10.526-26.085 11.239-4.642 0.447-8.845 0.467-11.912-0.57-2.89-1.015-7.238-6.402-12.093-10.351-4.81-3.928-9.78-6.782-8.708-12.032 0.649-4.241 3.285-7.32 8.58-11.932 2.757-2.381 7.073-7.712 10.693-9.923 3.088-1.831 6.321-0.743 9.764-1.14z"/>
+ <path fill="#e5af00" d="m166.601 80.257c4.803-0.592 11.382 0.592 14.407 2.829 2.829 2.105 4.804 3.271 7.368 4.079 8.571 2.828 20.507 4.431 20.029 12.146-0.544 9.228-4.627 13.085-12.277 15.423-6.089 1.861-17.427 10.29-25.932 11.055-4.676 0.478-8.763 0.484-11.807-0.539-2.865-1.005-7.2-6.387-12.021-10.304-4.772-3.9-9.742-6.629-8.583-11.821 0.711-4.085 3.236-7.236 8.487-11.812 2.732-2.357 6.957-7.744 10.557-9.968 3.052-1.834 6.351-0.694 9.772-1.088z"/>
+ <path fill="#eab500" d="m166.711 80.351c4.772-0.588 11.31 0.589 14.317 2.811 2.811 2.092 4.771 3.254 7.321 4.054 8.514 2.81 20.42 4.424 19.948 12.087-0.538 9.165-4.695 12.979-12.294 15.295-6.044 1.845-17.332 10.054-25.779 10.869-4.708 0.511-8.68 0.503-11.7-0.507-2.84-0.995-7.163-6.371-11.949-10.257-4.736-3.872-9.706-6.475-8.46-11.61 0.773-3.931 3.188-7.152 8.396-11.692 2.709-2.331 6.839-7.775 10.421-10.013 3.013-1.839 6.38-0.645 9.779-1.037z"/>
+ <path fill="#efba00" d="m166.82 80.443c4.742-0.584 11.238 0.585 14.226 2.794 2.794 2.078 4.743 3.237 7.276 4.027 8.456 2.793 20.332 4.417 19.868 12.029-0.531 9.104-4.766 12.872-12.313 15.167-5.997 1.83-17.234 9.819-25.626 10.685-4.742 0.542-8.596 0.52-11.595-0.476-2.815-0.985-7.124-6.355-11.877-10.209-4.699-3.844-9.668-6.322-8.336-11.4 0.835-3.778 3.14-7.068 8.304-11.573 2.686-2.306 6.724-7.807 10.285-10.059 2.978-1.84 6.411-0.595 9.788-0.985z"/>
+ <path fill="#f4c000" d="m166.93 80.537c4.711-0.58 11.166 0.582 14.135 2.776 2.775 2.066 4.713 3.22 7.229 4.002 8.399 2.775 20.246 4.41 19.787 11.969-0.522 9.043-4.832 12.765-12.328 15.039-5.952 1.815-17.139 9.584-25.473 10.501-4.776 0.574-8.513 0.538-11.49-0.445-2.79-0.976-7.085-6.34-11.804-10.162-4.662-3.816-9.632-6.168-8.213-11.189 0.896-3.623 3.092-6.984 8.213-11.454 2.66-2.281 6.604-7.838 10.147-10.104 2.942-1.844 6.441-0.547 9.797-0.933z"/>
+ <path fill="#f9c600" d="m167.039 80.63c4.683-0.577 11.095 0.577 14.045 2.758 2.758 2.052 4.683 3.203 7.184 3.976 8.341 2.757 20.157 4.403 19.706 11.91-0.518 8.981-4.901 12.659-12.346 14.911-5.906 1.799-17.044 9.347-25.32 10.315-4.809 0.606-8.431 0.556-11.384-0.413-2.765-0.966-7.048-6.324-11.732-10.114-4.625-3.788-9.594-6.016-8.088-10.98 0.958-3.467 3.043-6.9 8.12-11.333 2.637-2.256 6.488-7.87 10.013-10.15 2.902-1.844 6.468-0.495 9.802-0.88z"/>
+ </g>
+ <path fill="#fc0" d="m154.744 90.7245c4.65-0.573 11.022 0.574 13.954 2.74 2.739 2.039 4.651 3.186 7.136 3.951 8.284 2.739 20.071 4.396 19.626 11.851-0.51 8.919-4.97 12.551-12.362 14.781-5.861 1.784-16.947 9.112-25.168 10.131-4.842 0.638-8.347 0.574-11.277-0.382-2.74-0.956-7.01-6.308-11.66-10.067-4.588-3.76-9.559-5.862-7.965-10.769 1.02-3.313 2.995-6.816 8.028-11.213 2.612-2.23 6.371-7.901 9.876-10.195 2.867-1.847 6.499-0.447 9.812-0.828z"/>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fc0" d="m167.982 83.609c1.008 2.088 3.6 2.376 5.328 3.312 1.655 0.936 2.592 1.152 3.239 0.792 1.44-0.792 0.36-3.384-1.079-4.32-1.368-0.935-8.064-1.151-7.488 0.216z"/>
+ <path fill="#f9c600" d="m168.125 83.631c0.982 2.035 3.508 2.316 5.193 3.229 1.614 0.912 2.526 1.123 3.158 0.771 1.402-0.771 0.35-3.298-1.054-4.21-1.332-0.913-7.859-1.123-7.297 0.21z"/>
+ <path fill="#f4c000" d="m168.267 83.653c0.957 1.982 3.418 2.255 5.058 3.144 1.572 0.889 2.461 1.094 3.076 0.752 1.367-0.752 0.342-3.213-1.025-4.101-1.299-0.889-7.656-1.094-7.109 0.205z"/>
+ <path fill="#efba00" d="m168.409 83.674c0.932 1.929 3.327 2.195 4.924 3.06 1.53 0.865 2.395 1.064 2.993 0.732 1.331-0.732 0.333-3.127-0.998-3.992-1.264-0.864-7.451-1.064-6.919 0.2z"/>
+ <path fill="#eab500" d="m168.552 83.696c0.905 1.876 3.234 2.135 4.787 2.977 1.488 0.841 2.329 1.035 2.912 0.711 1.294-0.711 0.323-3.041-0.971-3.882-1.228-0.841-7.246-1.036-6.728 0.194z"/>
+ <path fill="#e5af00" d="m168.694 83.718c0.881 1.823 3.144 2.075 4.653 2.892 1.446 0.818 2.264 1.006 2.83 0.692 1.257-0.692 0.313-2.956-0.943-3.773-1.195-0.818-7.043-1.007-6.54 0.189z"/>
+ <path fill="#e0a900" d="m168.837 83.739c0.855 1.771 3.053 2.015 4.519 2.809 1.403 0.793 2.198 0.977 2.747 0.671 1.221-0.671 0.306-2.87-0.916-3.664-1.161-0.793-6.839-0.976-6.35 0.184z"/>
+ <path fill="#dba300" d="m168.979 83.761c0.829 1.718 2.962 1.955 4.383 2.725 1.363 0.77 2.132 0.948 2.666 0.651 1.184-0.651 0.296-2.784-0.889-3.554-1.125-0.77-6.634-0.948-6.16 0.178z"/>
+ <path fill="#d69e00" d="m169.121 83.782c0.804 1.665 2.871 1.895 4.249 2.641 1.32 0.747 2.066 0.918 2.583 0.631 1.148-0.631 0.287-2.698-0.861-3.444-1.091-0.746-6.43-0.919-5.971 0.172z"/>
+ <path fill="#d19800" d="m169.264 83.804c0.777 1.612 2.778 1.834 4.112 2.557 1.279 0.723 2.001 0.889 2.501 0.611 1.112-0.611 0.278-2.612-0.834-3.335-1.055-0.722-6.224-0.889-5.779 0.167z"/>
+ <path fill="#cc9200" d="m169.406 83.826c0.753 1.559 2.688 1.774 3.979 2.473 1.236 0.699 1.936 0.86 2.42 0.591 1.074-0.591 0.269-2.527-0.808-3.226-1.021-0.699-6.021-0.86-5.591 0.162z"/>
+ <path fill="#c68c00" d="m169.549 83.847c0.728 1.506 2.597 1.714 3.844 2.389 1.194 0.675 1.869 0.831 2.337 0.571 1.039-0.571 0.26-2.441-0.779-3.116-0.988-0.675-5.818-0.831-5.402 0.156z"/>
+ <path fill="#c18700" d="m169.691 83.869c0.702 1.453 2.506 1.654 3.709 2.305 1.152 0.652 1.803 0.802 2.254 0.551 1.002-0.551 0.251-2.355-0.751-3.006-0.953-0.652-5.613-0.802-5.212 0.15z"/>
+ <path fill="#bc8100" d="m169.833 83.89c0.677 1.4 2.415 1.594 3.574 2.221 1.111 0.628 1.738 0.772 2.173 0.531 0.965-0.531 0.241-2.27-0.725-2.897-0.917-0.627-5.408-0.772-5.022 0.145z"/>
+ <path fill="#b77b00" d="m169.976 83.912c0.65 1.347 2.322 1.533 3.438 2.137 1.069 0.604 1.673 0.743 2.091 0.511 0.93-0.511 0.233-2.184-0.696-2.788-0.884-0.603-5.205-0.743-4.833 0.14z"/>
+ <path fill="#b27500" d="m170.118 83.934c0.626 1.294 2.232 1.473 3.304 2.053 1.027 0.581 1.606 0.714 2.009 0.491 0.893-0.491 0.224-2.098-0.669-2.678-0.85-0.58-5.001-0.715-4.644 0.134z"/>
+ <path fill="#ad7000" d="m170.261 83.955c0.6 1.242 2.14 1.413 3.168 1.97 0.984 0.557 1.541 0.685 1.927 0.47 0.855-0.47 0.214-2.012-0.644-2.569-0.812-0.555-4.794-0.684-4.451 0.129z"/>
+ <path fill="#a86a00" d="m170.403 83.977c0.574 1.189 2.05 1.353 3.034 1.886 0.942 0.533 1.475 0.656 1.844 0.45 0.82-0.45 0.205-1.926-0.615-2.459-0.779-0.533-4.591-0.656-4.263 0.123z"/>
+ <path fill="#a36400" d="m170.545 83.998c0.55 1.136 1.959 1.292 2.899 1.802 0.901 0.509 1.41 0.626 1.762 0.43 0.783-0.43 0.197-1.841-0.587-2.35-0.745-0.508-4.387-0.626-4.074 0.118z"/>
+ <path fill="#9e5e00" d="m170.688 84.02c0.522 1.083 1.867 1.232 2.764 1.718 0.859 0.486 1.343 0.597 1.68 0.41 0.746-0.41 0.188-1.755-0.561-2.241-0.709-0.484-4.182-0.597-3.883 0.113z"/>
+ <path fill="#995900" d="m170.83 84.042c0.498 1.03 1.776 1.172 2.629 1.634 0.817 0.462 1.278 0.568 1.599 0.39 0.71-0.39 0.178-1.669-0.533-2.131-0.676-0.461-3.979-0.568-3.695 0.107z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fc0" d="m152.875 86.29c-0.325 0.813 1.952 2.359 3.091 1.301 1.222-1.057 2.686-2.033 3.175-2.359 2.195-1.465 1.383-2.522-2.278-1.871-3.663 0.651-3.663 2.115-3.988 2.929z"/>
+ <path fill="#f9c600" d="m152.934 86.279c-0.318 0.794 1.906 2.304 3.019 1.271 1.193-1.033 2.623-1.986 3.102-2.305 2.145-1.431 1.351-2.463-2.226-1.828-3.578 0.637-3.578 2.067-3.895 2.862z"/>
+ <path fill="#f4c000" d="m152.993 86.269c-0.31 0.775 1.861 2.25 2.948 1.241 1.164-1.008 2.56-1.939 3.026-2.25 2.095-1.397 1.319-2.405-2.173-1.784-3.491 0.62-3.491 2.017-3.801 2.793z"/>
+ <path fill="#efba00" d="m153.051 86.258c-0.302 0.757 1.817 2.195 2.878 1.211 1.136-0.984 2.497-1.892 2.952-2.195 2.044-1.363 1.287-2.347-2.118-1.741-3.409 0.606-3.409 1.968-3.712 2.725z"/>
+ <path fill="#eab500" d="m153.11 86.248c-0.295 0.738 1.771 2.141 2.805 1.181 1.108-0.959 2.437-1.845 2.88-2.141 1.993-1.329 1.255-2.289-2.066-1.698-3.324 0.591-3.324 1.92-3.619 2.658z"/>
+ <path fill="#e5af00" d="m153.169 86.238c-0.287 0.719 1.727 2.086 2.733 1.151 1.08-0.935 2.374-1.798 2.807-2.086 1.942-1.296 1.224-2.23-2.015-1.655s-3.238 1.87-3.525 2.59z"/>
+ <path fill="#e0a900" d="m153.228 86.228c-0.28 0.7 1.681 2.032 2.661 1.121 1.052-0.91 2.312-1.751 2.732-2.031 1.893-1.262 1.191-2.172-1.961-1.611-3.152 0.559-3.152 1.82-3.432 2.521z"/>
+ <path fill="#dba300" d="m153.286 86.217c-0.271 0.681 1.636 1.977 2.591 1.09 1.023-0.886 2.25-1.704 2.659-1.977 1.84-1.228 1.159-2.114-1.909-1.568-3.068 0.547-3.068 1.773-3.341 2.455z"/>
+ <path fill="#d69e00" d="m153.345 86.207c-0.265 0.662 1.591 1.922 2.519 1.061 0.995-0.862 2.188-1.657 2.586-1.922 1.789-1.194 1.127-2.055-1.855-1.525-2.985 0.53-2.985 1.723-3.25 2.386z"/>
+ <path fill="#d19800" d="m153.404 86.197c-0.257 0.643 1.546 1.868 2.447 1.03 0.967-0.837 2.126-1.61 2.512-1.868 1.739-1.16 1.095-1.997-1.803-1.481-2.899 0.516-2.899 1.674-3.156 2.319z"/>
+ <path fill="#cc9200" d="m153.463 86.187c-0.25 0.625 1.5 1.813 2.375 1 0.939-0.813 2.064-1.563 2.439-1.813 1.688-1.126 1.063-1.938-1.75-1.438-2.814 0.5-2.814 1.625-3.064 2.251z"/>
+ <path fill="#c68c00" d="m153.521 86.176c-0.242 0.605 1.456 1.758 2.304 0.97 0.911-0.788 2.002-1.516 2.366-1.758 1.637-1.092 1.031-1.88-1.698-1.395-2.729 0.486-2.729 1.576-2.972 2.183z"/>
+ <path fill="#c18700" d="m153.58 86.166c-0.233 0.587 1.41 1.704 2.233 0.939 0.882-0.763 1.938-1.469 2.292-1.704 1.586-1.058 0.999-1.822-1.646-1.352-2.644 0.472-2.644 1.529-2.879 2.117z"/>
+ <path fill="#bc8100" d="m153.639 86.156c-0.228 0.568 1.364 1.649 2.16 0.91 0.854-0.739 1.878-1.422 2.219-1.649 1.536-1.024 0.967-1.764-1.593-1.308s-2.559 1.477-2.786 2.047z"/>
+ <path fill="#b77b00" d="m153.698 86.146c-0.22 0.549 1.32 1.594 2.089 0.879 0.825-0.715 1.815-1.375 2.146-1.595 1.484-0.99 0.935-1.705-1.54-1.265s-2.475 1.43-2.695 1.981z"/>
+ <path fill="#b27500" d="m153.756 86.135c-0.211 0.53 1.275 1.54 2.019 0.85 0.797-0.69 1.753-1.328 2.072-1.54 1.434-0.957 0.902-1.646-1.487-1.221s-2.391 1.38-2.604 1.911z"/>
+ <path fill="#ad7000" d="m153.815 86.125c-0.204 0.512 1.229 1.486 1.946 0.82 0.769-0.666 1.69-1.281 1.997-1.486 1.385-0.922 0.871-1.588-1.434-1.178s-2.304 1.331-2.509 1.844z"/>
+ <path fill="#a86a00" d="m153.874 86.114c-0.196 0.493 1.185 1.431 1.875 0.79 0.74-0.642 1.628-1.234 1.924-1.431 1.332-0.889 0.84-1.53-1.381-1.135s-2.221 1.283-2.418 1.776z"/>
+ <path fill="#a36400" d="m153.933 86.104c-0.189 0.474 1.139 1.376 1.803 0.759 0.712-0.617 1.566-1.187 1.851-1.376 1.281-0.855 0.808-1.472-1.329-1.092-2.135 0.38-2.135 1.234-2.325 1.709z"/>
+ <path fill="#9e5e00" d="m153.991 86.094c-0.181 0.455 1.095 1.322 1.732 0.729 0.684-0.592 1.504-1.14 1.776-1.321 1.231-0.821 0.775-1.414-1.274-1.048-2.051 0.364-2.051 1.184-2.234 1.64z"/>
+ <path fill="#995900" d="m154.05 86.083c-0.174 0.436 1.05 1.267 1.66 0.699 0.656-0.568 1.442-1.093 1.704-1.267 1.181-0.787 0.743-1.355-1.223-1.005s-1.966 1.136-2.141 1.573z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fc0" d="m156.951 107.887c-0.229 2.858 6.343-4.286 6.743-4.915 0.856-1.543 3.715-5.886 4.172-7.715 0.857-3.2 2.401-5.543 1.429-8.915-0.343-1.086-2.742-1.372-3.829-0.687-3.086 1.829-2.629 4.058-2.972 6.115-1.143 5.831-5.143 11.717-5.543 16.117z"/>
+ <path fill="#ffcc02" d="m157.22 107.441c-0.22 2.787 6.178-4.188 6.566-4.802 0.833-1.506 3.614-5.745 4.056-7.529 0.831-3.122 2.333-5.408 1.382-8.695-0.337-1.058-2.678-1.333-3.735-0.663-3.006 1.788-2.557 3.96-2.889 5.967-1.105 5.685-4.997 11.431-5.38 15.722z"/>
+ <path fill="#ffcc05" d="m157.488 106.995c-0.209 2.715 6.014-4.091 6.392-4.69 0.811-1.469 3.513-5.603 3.941-7.342 0.804-3.043 2.264-5.273 1.331-8.474-0.329-1.031-2.61-1.295-3.64-0.64-2.927 1.747-2.486 3.863-2.806 5.818-1.068 5.541-4.851 11.146-5.218 15.328z"/>
+ <path fill="#ffcc07" d="m157.757 106.548c-0.198 2.645 5.85-3.993 6.217-4.577 0.785-1.431 3.409-5.461 3.824-7.156 0.779-2.964 2.196-5.138 1.282-8.253-0.322-1.003-2.543-1.257-3.545-0.618-2.847 1.706-2.414 3.766-2.722 5.67-1.031 5.398-4.706 10.862-5.056 14.934z"/>
+ <path fill="#ffcd0a" d="m158.026 106.102c-0.189 2.573 5.684-3.896 6.04-4.465 0.762-1.394 3.309-5.32 3.709-6.969 0.753-2.886 2.129-5.004 1.233-8.033-0.315-0.976-2.478-1.219-3.45-0.595-2.768 1.665-2.343 3.668-2.64 5.522-0.993 5.254-4.558 10.577-4.892 14.54z"/>
+ <path fill="#ffcd0c" d="m158.294 105.655c-0.179 2.503 5.52-3.798 5.865-4.351 0.738-1.357 3.207-5.179 3.594-6.783 0.727-2.807 2.061-4.869 1.185-7.813-0.309-0.948-2.411-1.18-3.356-0.572-2.687 1.623-2.271 3.571-2.556 5.374-0.958 5.11-4.414 10.291-4.732 14.145z"/>
+ <path fill="#ffcd0f" d="m158.563 105.209c-0.169 2.431 5.354-3.701 5.688-4.239 0.715-1.319 3.106-5.037 3.479-6.596 0.7-2.728 1.992-4.734 1.135-7.592-0.301-0.92-2.344-1.142-3.261-0.549-2.608 1.583-2.199 3.474-2.473 5.226-0.919 4.965-4.267 10.005-4.568 13.75z"/>
+ <path fill="#ffcd11" d="m158.831 104.762c-0.159 2.361 5.19-3.602 5.515-4.126 0.69-1.282 3.004-4.896 3.361-6.409 0.674-2.649 1.924-4.599 1.087-7.372-0.295-0.893-2.277-1.104-3.167-0.526-2.527 1.541-2.128 3.376-2.389 5.077-0.883 4.822-4.122 9.721-4.407 13.356z"/>
+ <path fill="#ffce14" d="m159.1 104.316c-0.149 2.289 5.024-3.505 5.338-4.014 0.667-1.244 2.901-4.754 3.247-6.223 0.646-2.571 1.854-4.464 1.037-7.151-0.287-0.865-2.211-1.065-3.072-0.504-2.448 1.5-2.056 3.279-2.306 4.929-0.845 4.679-3.976 9.437-4.244 12.963z"/>
+ <path fill="#ffce16" d="m159.369 103.869c-0.139 2.219 4.86-3.407 5.162-3.9 0.643-1.208 2.801-4.613 3.131-6.037 0.622-2.492 1.787-4.329 0.988-6.93-0.28-0.838-2.146-1.027-2.978-0.481-2.368 1.459-1.983 3.182-2.223 4.781-0.807 4.533-3.829 9.151-4.08 12.567z"/>
+ <path fill="#ffce19" d="m159.637 103.423c-0.13 2.147 4.695-3.31 4.986-3.788 0.62-1.17 2.699-4.471 3.016-5.85 0.596-2.414 1.719-4.195 0.939-6.71-0.273-0.81-2.079-0.989-2.883-0.458-2.289 1.418-1.913 3.084-2.139 4.632-0.77 4.391-3.684 8.866-3.919 12.174z"/>
+ <path fill="#ffce1c" d="m159.906 102.977c-0.119 2.076 4.531-3.213 4.811-3.676 0.597-1.133 2.599-4.33 2.899-5.664 0.57-2.335 1.651-4.06 0.891-6.49-0.267-0.782-2.012-0.95-2.787-0.435-2.21 1.377-1.842 2.987-2.057 4.484-0.734 4.247-3.539 8.582-3.757 11.781z"/>
+ <path fill="#ffcf1e" d="m160.174 102.53c-0.108 2.005 4.366-3.115 4.637-3.563 0.571-1.096 2.496-4.189 2.784-5.478 0.543-2.256 1.581-3.925 0.841-6.269-0.26-0.754-1.945-0.912-2.693-0.412-2.129 1.336-1.77 2.889-1.973 4.336-0.697 4.103-3.394 8.297-3.596 11.386z"/>
+ <path fill="#ffcf21" d="m160.443 102.084c-0.099 1.934 4.201-3.018 4.46-3.45 0.548-1.059 2.394-4.047 2.668-5.291 0.517-2.178 1.514-3.79 0.793-6.049-0.253-0.727-1.879-0.874-2.599-0.39-2.051 1.295-1.698 2.792-1.891 4.188-0.658 3.959-3.246 8.012-3.431 10.992z"/>
+ <path fill="#ffcf23" d="m160.712 101.637c-0.089 1.863 4.036-2.919 4.283-3.337 0.526-1.021 2.294-3.905 2.553-5.104 0.491-2.099 1.447-3.655 0.744-5.828-0.246-0.699-1.813-0.835-2.505-0.367-1.969 1.253-1.625 2.694-1.805 4.04-0.623 3.814-3.101 7.726-3.27 10.596z"/>
+ <path fill="#ffcf26" d="m160.98 101.191c-0.079 1.792 3.872-2.822 4.107-3.225 0.502-0.984 2.192-3.764 2.438-4.918 0.464-2.02 1.378-3.52 0.694-5.607-0.238-0.672-1.746-0.797-2.41-0.344-1.89 1.212-1.555 2.597-1.723 3.891-0.583 3.671-2.953 7.442-3.106 10.203z"/>
+ <path fill="#ffd028" d="m161.249 100.744c-0.068 1.721 3.707-2.724 3.933-3.112 0.478-0.947 2.091-3.623 2.321-4.731 0.439-1.942 1.311-3.386 0.646-5.387-0.232-0.645-1.68-0.758-2.316-0.321-1.81 1.171-1.481 2.5-1.639 3.743-0.548 3.527-2.809 7.156-2.945 9.808z"/>
+ <path fill="#ffd02b" d="m161.517 100.298c-0.06 1.65 3.543-2.627 3.757-2.999 0.454-0.91 1.989-3.481 2.206-4.545 0.413-1.863 1.242-3.25 0.597-5.167-0.225-0.617-1.613-0.72-2.221-0.298-1.73 1.13-1.411 2.402-1.557 3.595-0.509 3.383-2.662 6.871-2.782 9.414z"/>
+ <path fill="#ffd02d" d="m161.786 99.852c-0.049 1.579 3.377-2.529 3.581-2.887 0.431-0.872 1.887-3.34 2.091-4.359 0.387-1.784 1.173-3.116 0.547-4.946-0.217-0.589-1.546-0.682-2.126-0.275-1.649 1.089-1.339 2.305-1.472 3.446-0.474 3.24-2.518 6.587-2.621 9.021z"/>
+ <path fill="#ffd030" d="m162.055 99.405c-0.039 1.508 3.212-2.432 3.404-2.773 0.407-0.835 1.786-3.199 1.976-4.172 0.359-1.706 1.104-2.981 0.499-4.726-0.211-0.562-1.481-0.644-2.032-0.253-1.571 1.048-1.268 2.208-1.389 3.298-0.436 3.096-2.372 6.302-2.458 8.626z"/>
+ <path fill="#ffd133" d="m162.323 98.958c-0.029 1.437 3.048-2.334 3.23-2.661 0.383-0.798 1.684-3.057 1.858-3.986 0.334-1.627 1.037-2.846 0.45-4.505-0.204-0.534-1.414-0.605-1.938-0.23-1.49 1.007-1.195 2.11-1.306 3.15-0.397 2.953-2.224 6.018-2.294 8.232z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fc0" d="m179.646 95.994c-3.168 3.456-5.4 6.767-7.2 9-1.872 2.304-6.48 5.04-4.176 7.704 1.943 2.376 9.936-1.944 16.128-6.552 6.12-4.608 15.696-8.711 11.016-13.967-2.448-2.664-8.208-2.088-10.439-0.648-1.729 1.078-2.737 1.655-5.329 4.463z"/>
+ <path fill="#ffcc02" d="m179.782 96.147c-3.118 3.378-5.313 6.628-7.086 8.809-1.841 2.249-6.375 4.945-4.13 7.534 1.893 2.31 9.724-1.943 15.795-6.469 6.001-4.525 15.38-8.574 10.82-13.682-2.387-2.588-8.022-1.998-10.209-0.584-1.692 1.062-2.665 1.67-5.19 4.392z"/>
+ <path fill="#ffcc05" d="m179.919 96.3c-3.068 3.3-5.227 6.488-6.973 8.619-1.81 2.193-6.271 4.85-4.085 7.364 1.843 2.243 9.513-1.943 15.463-6.386 5.882-4.442 15.064-8.437 10.623-13.396-2.323-2.513-7.835-1.907-9.978-0.52-1.655 1.044-2.593 1.684-5.05 4.319z"/>
+ <path fill="#ffcc07" d="m180.055 96.454c-3.02 3.222-5.14 6.347-6.859 8.428-1.78 2.138-6.166 4.754-4.04 7.194 1.793 2.177 9.302-1.942 15.131-6.303 5.762-4.359 14.748-8.299 10.427-13.11-2.261-2.437-7.648-1.817-9.747-0.456-1.619 1.025-2.522 1.698-4.912 4.247z"/>
+ <path fill="#ffcd0a" d="m180.191 96.607c-2.97 3.143-5.052 6.207-6.745 8.237-1.749 2.082-6.063 4.659-3.994 7.023 1.743 2.111 9.09-1.941 14.798-6.219 5.644-4.276 14.433-8.162 10.231-12.824-2.199-2.361-7.463-1.727-9.518-0.392-1.581 1.008-2.45 1.713-4.772 4.175z"/>
+ <path fill="#ffcd0c" d="m180.327 96.761c-2.92 3.065-4.965 6.066-6.631 8.047-1.718 2.027-5.957 4.564-3.949 6.853 1.693 2.044 8.878-1.94 14.466-6.136 5.524-4.194 14.116-8.024 10.034-12.538-2.137-2.286-7.275-1.636-9.285-0.328-1.546 0.988-2.38 1.726-4.635 4.102z"/>
+ <path fill="#ffcd0f" d="m180.464 96.914c-2.871 2.987-4.879 5.926-6.518 7.857-1.688 1.971-5.854 4.468-3.903 6.683 1.643 1.978 8.666-1.94 14.133-6.053 5.404-4.111 13.801-7.887 9.839-12.251-2.075-2.21-7.091-1.546-9.056-0.264-1.509 0.969-2.308 1.738-4.495 4.028z"/>
+ <path fill="#ffcd11" d="m180.6 97.067c-2.821 2.909-4.792 5.786-6.404 7.667-1.657 1.916-5.748 4.373-3.858 6.512 1.593 1.912 8.455-1.938 13.802-5.969 5.284-4.028 13.484-7.75 9.641-11.966-2.012-2.134-6.902-1.456-8.823-0.199-1.474 0.951-2.238 1.752-4.358 3.955z"/>
+ <path fill="#ffce14" d="m180.736 97.221c-2.771 2.83-4.705 5.645-6.29 7.476-1.626 1.86-5.644 4.278-3.813 6.342 1.542 1.845 8.244-1.938 13.47-5.886 5.166-3.945 13.169-7.612 9.444-11.68-1.949-2.059-6.716-1.365-8.592-0.135-1.437 0.933-2.166 1.766-4.219 3.883z"/>
+ <path fill="#ffce16" d="m180.872 97.375c-2.722 2.752-4.617 5.504-6.176 7.286-1.595 1.805-5.539 4.182-3.767 6.172 1.49 1.779 8.031-1.937 13.136-5.803 5.046-3.862 12.853-7.475 9.249-11.394-1.889-1.983-6.53-1.274-8.362-0.071-1.4 0.914-2.095 1.779-4.08 3.81z"/>
+ <path fill="#ffce19" d="m181.009 97.528c-2.673 2.674-4.53 5.364-6.063 7.095-1.564 1.749-5.435 4.087-3.722 6.001 1.44 1.713 7.82-1.936 12.804-5.719 4.927-3.78 12.537-7.338 9.052-11.108-1.825-1.907-6.343-1.185-8.13-0.007-1.364 0.896-2.024 1.793-3.941 3.738z"/>
+ <path fill="#ffce1c" d="m181.145 97.682c-2.623 2.595-4.444 5.225-5.949 6.904-1.534 1.693-5.33 3.992-3.676 5.831 1.39 1.646 7.608-1.935 12.471-5.636 4.808-3.697 12.221-7.2 8.856-10.822-1.764-1.832-6.157-1.094-7.9 0.057-1.327 0.878-1.952 1.807-3.802 3.666z"/>
+ <path fill="#ffcf1e" d="m181.281 97.835c-2.573 2.517-4.357 5.084-5.835 6.714-1.503 1.638-5.226 3.896-3.631 5.661 1.34 1.58 7.396-1.935 12.139-5.553 4.689-3.614 11.905-7.063 8.659-10.536-1.701-1.756-5.97-1.004-7.668 0.121-1.291 0.86-1.881 1.821-3.664 3.593z"/>
+ <path fill="#ffcf21" d="m181.417 97.988c-2.522 2.439-4.27 4.944-5.721 6.524-1.472 1.582-5.121 3.801-3.586 5.491 1.29 1.513 7.186-1.934 11.807-5.47 4.569-3.531 11.589-6.926 8.463-10.25-1.639-1.68-5.783-0.914-7.438 0.186-1.254 0.84-1.809 1.834-3.525 3.519z"/>
+ <path fill="#ffcf23" d="m181.554 98.142c-2.476 2.361-4.185 4.803-5.608 6.333-1.441 1.527-5.017 3.706-3.54 5.32 1.24 1.447 6.974-1.933 11.474-5.386 4.45-3.448 11.273-6.788 8.268-9.964-1.577-1.605-5.599-0.823-7.207 0.25-1.22 0.822-1.74 1.848-3.387 3.447z"/>
+ <path fill="#ffcf26" d="m181.69 98.295c-2.425 2.283-4.098 4.663-5.494 6.143-1.411 1.471-4.912 3.61-3.495 5.15 1.19 1.381 6.763-1.932 11.142-5.303 4.331-3.366 10.957-6.65 8.07-9.679-1.514-1.529-5.411-0.732-6.976 0.313-1.182 0.805-1.667 1.863-3.247 3.376z"/>
+ <path fill="#ffd028" d="m181.826 98.449c-2.375 2.204-4.009 4.522-5.38 5.952-1.38 1.416-4.808 3.515-3.449 4.98 1.14 1.314 6.551-1.932 10.81-5.22 4.211-3.283 10.641-6.513 7.874-9.393-1.452-1.454-5.226-0.642-6.745 0.378-1.147 0.786-1.597 1.876-3.11 3.303z"/>
+ <path fill="#ffd02b" d="m181.962 98.602c-2.324 2.127-3.922 4.382-5.266 5.762-1.349 1.36-4.703 3.42-3.404 4.809 1.089 1.248 6.34-1.93 10.478-5.136 4.092-3.2 10.325-6.376 7.677-9.106-1.389-1.378-5.038-0.552-6.513 0.441-1.111 0.768-1.526 1.89-2.972 3.23z"/>
+ <path fill="#ffd02d" d="m182.099 98.756c-2.276 2.048-3.836 4.241-5.153 5.571-1.318 1.305-4.599 3.324-3.359 4.639 1.039 1.182 6.128-1.93 10.146-5.053 3.973-3.117 10.009-6.238 7.48-8.82-1.328-1.303-4.852-0.462-6.282 0.506-1.074 0.748-1.454 1.903-2.832 3.157z"/>
+ <path fill="#ffd030" d="m182.235 98.909c-2.228 1.97-3.749 4.101-5.039 5.381-1.288 1.249-4.494 3.229-3.313 4.469 0.988 1.115 5.916-1.929 9.813-4.97 3.853-3.034 9.693-6.101 7.285-8.535-1.267-1.227-4.666-0.371-6.052 0.57-1.038 0.731-1.384 1.918-2.694 3.085z"/>
+ <path fill="#ffd133" d="m182.371 99.063c-2.177 1.892-3.662 3.96-4.925 5.19-1.257 1.193-4.39 3.133-3.268 4.298 0.938 1.049 5.704-1.928 9.479-4.886 3.734-2.952 9.377-5.963 7.088-8.249-1.203-1.151-4.479-0.281-5.821 0.634-0.999 0.713-1.31 1.931-2.553 3.013z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fff" d="m186.414 168.569c0.864-2.808 28.872-9.432 33.48-7.272 4.536 2.16 26.279 33.768 22.392 35.496-3.888 1.657-12.24-10.512-24.408-16.128s-32.328-9.216-31.464-12.096z"/>
+ <path fill="#f9f9f9" d="m187.239 168.626c0.848-2.761 28.145-9.076 32.69-6.997 4.476 2.079 25.768 32.897 21.943 34.591-3.824 1.625-11.965-10.346-23.94-15.874-11.976-5.527-31.541-8.89-30.693-11.72z"/>
+ <path fill="#f4f4f4" d="m188.063 168.683c0.832-2.714 27.418-8.72 31.899-6.722 4.417 1.998 25.259 32.026 21.497 33.685-3.76 1.595-11.689-10.18-23.474-15.619-11.782-5.438-30.754-8.565-29.922-11.344z"/>
+ <path fill="#efefef" d="m188.888 168.74c0.814-2.668 26.69-8.364 31.109-6.447 4.357 1.917 24.746 31.155 21.049 32.779-3.695 1.563-11.416-10.014-23.007-15.364-11.59-5.349-29.967-8.239-29.151-10.968z"/>
+ <path fill="#eaeaea" d="m189.712 168.797c0.801-2.621 25.964-8.009 30.32-6.173 4.299 1.837 24.235 30.285 20.603 31.874-3.633 1.532-11.142-9.847-22.54-15.109-11.4-5.261-29.182-7.914-28.383-10.592z"/>
+ <path fill="#e5e5e5" d="m190.537 168.853c0.783-2.573 25.236-7.652 29.53-5.897 4.239 1.756 23.723 29.414 20.155 30.968-3.569 1.501-10.867-9.681-22.074-14.854-11.206-5.172-28.395-7.589-27.611-10.217z"/>
+ <path fill="#e0e0e0" d="m191.361 168.91c0.768-2.527 24.51-7.296 28.74-5.622 4.18 1.675 23.212 28.543 19.708 30.063-3.505 1.469-10.593-9.516-21.607-14.6-11.014-5.083-27.608-7.263-26.841-9.841z"/>
+ <path fill="#dbdbdb" d="m192.186 168.967c0.751-2.48 23.781-6.941 27.95-5.347 4.119 1.593 22.7 27.671 19.26 29.157-3.441 1.438-10.318-9.349-21.141-14.345-10.821-4.994-26.821-6.938-26.069-9.465z"/>
+ <path fill="#d6d6d6" d="m193.01 169.024c0.735-2.433 23.057-6.585 27.16-5.073 4.062 1.513 22.19 26.801 18.813 28.252-3.377 1.407-10.043-9.183-20.673-14.09-10.629-4.906-26.035-6.612-25.3-9.089z"/>
+ <path fill="#d1d1d1" d="m193.835 169.081c0.72-2.387 22.328-6.229 26.37-4.798 4.001 1.432 21.678 25.93 18.365 27.346-3.313 1.376-9.768-9.017-20.206-13.835-10.437-4.817-25.248-6.287-24.529-8.713z"/>
+ <path fill="#ccc" d="m194.659 169.137c0.703-2.339 21.603-5.873 25.58-4.521 3.942 1.351 21.167 25.059 17.918 26.44-3.249 1.345-9.493-8.851-19.739-13.58-10.245-4.729-24.462-5.963-23.759-8.339z"/>
+ <path fill="#c6c6c6" d="m195.484 169.194c0.687-2.292 20.874-5.517 24.79-4.247 3.882 1.27 20.655 24.188 17.47 25.535-3.185 1.314-9.219-8.685-19.271-13.326-10.054-4.639-23.676-5.636-22.989-7.962z"/>
+ <path fill="#c1c1c1" d="m196.308 169.251c0.671-2.246 20.147-5.161 24-3.973 3.822 1.19 20.145 23.318 17.022 24.63-3.121 1.283-8.943-8.519-18.805-13.071-9.859-4.551-22.888-5.311-22.217-7.586z"/>
+ <path fill="#bcbcbc" d="m197.133 169.308c0.654-2.199 19.421-4.805 23.21-3.698 3.764 1.109 19.634 22.447 16.575 23.724-3.057 1.252-8.669-8.353-18.338-12.816-9.668-4.462-22.102-4.985-21.447-7.21z"/>
+ <path fill="#b7b7b7" d="m197.957 169.365c0.64-2.152 18.693-4.45 22.42-3.423 3.705 1.027 19.122 21.575 16.129 22.818-2.993 1.221-8.395-8.186-17.872-12.561-9.476-4.373-21.315-4.66-20.677-6.834z"/>
+ <path fill="#b2b2b2" d="m198.782 169.421c0.622-2.105 17.966-4.093 21.63-3.147 3.646 0.946 18.61 20.704 15.681 21.912-2.93 1.19-8.12-8.02-17.404-12.306-9.284-4.284-20.53-4.335-19.907-6.459z"/>
+ <path fill="#adadad" d="m199.606 169.478c0.606-2.058 17.239-3.737 20.84-2.873 3.586 0.866 18.099 19.834 15.234 21.008-2.866 1.158-7.847-7.855-16.938-12.052-9.091-4.196-19.742-4.009-19.136-6.083z"/>
+ <path fill="#a8a8a8" d="m200.431 169.535c0.59-2.011 16.512-3.382 20.05-2.598 3.525 0.785 17.588 18.963 14.786 20.102-2.803 1.127-7.571-7.688-16.472-11.797-8.898-4.107-18.955-3.684-18.364-5.707z"/>
+ <path fill="#a3a3a3" d="m201.255 169.592c0.574-1.965 15.785-3.026 19.261-2.323 3.467 0.704 17.076 18.092 14.339 19.196-2.738 1.096-7.296-7.522-16.004-11.542-8.707-4.018-18.17-3.358-17.596-5.331z"/>
+ <path fill="#9e9e9e" d="m202.08 169.649c0.559-1.918 15.059-2.67 18.47-2.048 3.407 0.623 16.565 17.221 13.892 18.29-2.674 1.065-7.022-7.356-15.537-11.287-8.515-3.929-17.383-3.033-16.825-4.955z"/>
+ <path fill="#999" d="m202.904 169.705c0.542-1.871 14.331-2.314 17.68-1.773 3.349 0.542 16.055 16.35 13.444 17.385-2.61 1.034-6.747-7.19-15.07-11.032-8.322-3.841-16.596-2.708-16.054-4.58z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fff" d="m151.134 211.625c2.881 0.144 0.145 16.271 0.145 32.903s2.231 22.464 0.144 24.552-5.688-5.399-5.688-22.031c-0.001-16.632 2.519-35.568 5.399-35.424z"/>
+ <path fill="#f9f9f9" d="m151.105 212.016c2.783 0.162 0.109 16.052 0.097 32.419-0.012 16.366 2.188 22.208 0.164 24.237-2.02 2.029-5.561-5.383-5.546-21.752 0.012-16.367 2.502-35.065 5.285-34.904z"/>
+ <path fill="#f4f4f4" d="m151.075 212.407c2.687 0.18 0.076 15.832 0.051 31.934-0.023 16.102 2.143 21.951 0.185 23.924-1.953 1.968-5.435-5.367-5.405-21.473 0.024-16.103 2.484-34.564 5.169-34.385z"/>
+ <path fill="#efefef" d="m151.046 212.797c2.588 0.197 0.041 15.613 0.004 31.449-0.036 15.836 2.098 21.694 0.204 23.609-1.886 1.907-5.308-5.352-5.263-21.195 0.037-15.835 2.467-34.058 5.055-33.863z"/>
+ <path fill="#eaeaea" d="m151.017 213.189c2.49 0.214 0.007 15.392-0.043 30.962-0.05 15.571 2.052 21.439 0.224 23.297-1.818 1.848-5.181-5.334-5.122-20.916 0.049-15.571 2.45-33.557 4.941-33.343z"/>
+ <path fill="#e5e5e5" d="m150.987 213.581c2.394 0.23-0.027 15.17-0.089 30.477s2.007 21.182 0.244 22.982c-1.751 1.787-5.055-5.32-4.98-20.638 0.061-15.305 2.431-33.053 4.825-32.821z"/>
+ <path fill="#e0e0e0" d="m150.958 213.971c2.297 0.248-0.062 14.951-0.136 29.99-0.074 15.041 1.962 20.927 0.264 22.668-1.683 1.728-4.928-5.301-4.839-20.356 0.074-15.04 2.414-32.551 4.711-32.302z"/>
+ <path fill="#dbdbdb" d="m150.928 214.362c2.199 0.266-0.096 14.73-0.182 29.506-0.087 14.775 1.915 20.67 0.282 22.354-1.615 1.667-4.8-5.286-4.696-20.078 0.087-14.776 2.397-32.048 4.596-31.782z"/>
+ <path fill="#d6d6d6" d="m150.899 214.752c2.102 0.283-0.13 14.511-0.229 29.021-0.099 14.511 1.87 20.413 0.303 22.04-1.549 1.607-4.674-5.27-4.556-19.799 0.1-14.51 2.38-31.545 4.482-31.262z"/>
+ <path fill="#d1d1d1" d="m150.87 215.144c2.005 0.301-0.165 14.29-0.274 28.535-0.112 14.245 1.824 20.155 0.321 21.725-1.479 1.548-4.547-5.252-4.413-19.519 0.11-14.245 2.361-31.043 4.366-30.741z"/>
+ <path fill="#ccc" d="m150.84 215.536c1.908 0.317-0.197 14.069-0.32 28.049-0.124 13.979 1.779 19.899 0.342 21.412-1.413 1.486-4.42-5.238-4.272-19.242 0.122-13.979 2.343-30.54 4.25-30.219z"/>
+ <path fill="#c6c6c6" d="m150.811 215.926c1.811 0.334-0.233 13.85-0.368 27.564-0.136 13.713 1.735 19.643 0.362 21.096-1.346 1.428-4.293-5.219-4.131-18.961 0.136-13.712 2.327-30.035 4.137-29.699z"/>
+ <path fill="#c1c1c1" d="m150.781 216.317c1.714 0.354-0.267 13.629-0.414 27.078s1.69 19.387 0.382 20.783c-1.277 1.367-4.166-5.203-3.989-18.682 0.148-13.449 2.308-29.533 4.021-29.179z"/>
+ <path fill="#bcbcbc" d="m150.752 216.708c1.616 0.371-0.301 13.41-0.461 26.594-0.161 13.184 1.646 19.13 0.402 20.469-1.211 1.307-4.04-5.188-3.847-18.402 0.16-13.185 2.29-29.033 3.906-28.661z"/>
+ <path fill="#b7b7b7" d="m150.723 217.099c1.519 0.387-0.336 13.188-0.509 26.106-0.173 12.92 1.601 18.875 0.423 20.156-1.144 1.246-3.913-5.171-3.706-18.123 0.172-12.919 2.273-28.529 3.792-28.139z"/>
+ <path fill="#b2b2b2" d="m150.693 217.491c1.422 0.404-0.37 12.969-0.554 25.621-0.186 12.653 1.555 18.617 0.441 19.842-1.076 1.187-3.786-5.156-3.563-17.846 0.184-12.652 2.255-28.024 3.676-27.617z"/>
+ <path fill="#adadad" d="m150.664 217.881c1.325 0.422-0.404 12.748-0.601 25.136-0.198 12.388 1.51 18.36 0.462 19.528-1.008 1.125-3.66-5.139-3.423-17.566 0.197-12.389 2.238-27.521 3.562-27.098z"/>
+ <path fill="#a8a8a8" d="m150.634 218.272c1.229 0.439-0.438 12.527-0.646 24.65-0.21 12.123 1.464 18.104 0.48 19.213-0.939 1.066-3.531-5.121-3.279-17.285 0.208-12.123 2.219-27.019 3.445-26.578z"/>
+ <path fill="#a3a3a3" d="m150.605 218.663c1.13 0.457-0.474 12.309-0.694 24.166-0.222 11.857 1.419 17.848 0.501 18.899-0.873 1.006-3.405-5.106-3.139-17.009 0.222-11.855 2.202-26.515 3.332-26.056z"/>
+ <path fill="#9e9e9e" d="m150.576 219.054c1.033 0.474-0.507 12.088-0.741 23.68-0.234 11.593 1.374 17.591 0.521 18.585-0.806 0.946-3.279-5.089-2.997-16.729 0.233-11.591 2.184-26.011 3.217-25.536z"/>
+ <path fill="#999" d="m150.546 219.444c0.937 0.492-0.541 11.868-0.787 23.195-0.246 11.326 1.329 17.335 0.541 18.271-0.737 0.885-3.151-5.074-2.855-16.449 0.245-11.328 2.166-25.509 3.101-25.017z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fff" d="m157.434 167.161c1.735 0.192 12.437-2.218 12.822-1.254 0.386 0.772-6.651 2.893-8.966 5.303-0.771 0.771-2.796 2.603-4.049 2.41-0.964-0.096-1.543-2.121-2.989-3.664-3.471-3.47-5.688-3.181-5.013-4.531 0.579-1.06 5.207 1.446 8.195 1.736z"/>
+ <path fill="#fbfbfb" d="m157.479 167.201c1.7 0.188 12.176-2.171 12.554-1.227 0.377 0.755-6.512 2.832-8.778 5.191-0.755 0.755-2.736 2.549-3.964 2.36-0.942-0.094-1.51-2.077-2.926-3.587-3.398-3.397-5.568-3.115-4.907-4.436 0.565-1.038 5.096 1.415 8.021 1.699z"/>
+ <path fill="#f8f8f8" d="m157.525 167.241c1.663 0.184 11.914-2.124 12.283-1.201 0.369 0.739-6.372 2.771-8.589 5.08-0.738 0.739-2.679 2.494-3.879 2.309-0.924-0.092-1.479-2.032-2.863-3.51-3.325-3.324-5.449-3.048-4.803-4.341 0.555-1.015 4.988 1.385 7.851 1.663z"/>
+ <path fill="#f5f5f5" d="m157.57 167.281c1.626 0.18 11.652-2.078 12.014-1.175 0.361 0.723-6.231 2.711-8.4 4.969-0.723 0.722-2.619 2.439-3.793 2.258-0.903-0.09-1.446-1.987-2.802-3.433-3.252-3.251-5.329-2.981-4.695-4.245 0.54-0.993 4.876 1.354 7.676 1.626z"/>
+ <path fill="#f2f2f2" d="m157.615 167.321c1.59 0.176 11.391-2.031 11.745-1.148 0.352 0.706-6.093 2.649-8.212 4.856-0.707 0.707-2.562 2.385-3.709 2.208-0.883-0.088-1.413-1.943-2.738-3.356-3.179-3.178-5.209-2.914-4.591-4.15 0.529-0.971 4.768 1.324 7.505 1.59z"/>
+ <path fill="#efefef" d="m157.66 167.361c1.554 0.172 11.13-1.985 11.475-1.122 0.346 0.69-5.952 2.589-8.022 4.745-0.69 0.69-2.503 2.33-3.624 2.157-0.863-0.086-1.381-1.898-2.675-3.279-3.106-3.105-5.09-2.847-4.486-4.055 0.517-0.948 4.658 1.294 7.332 1.554z"/>
+ <path fill="#ebebeb" d="m157.705 167.401c1.518 0.168 10.868-1.938 11.206-1.096 0.336 0.674-5.813 2.528-7.835 4.634-0.674 0.674-2.444 2.275-3.539 2.106-0.842-0.084-1.348-1.853-2.612-3.202-3.032-3.032-4.97-2.78-4.38-3.959 0.505-0.926 4.549 1.263 7.16 1.517z"/>
+ <path fill="#e8e8e8" d="m157.751 167.441c1.48 0.164 10.606-1.892 10.936-1.069 0.329 0.657-5.673 2.467-7.646 4.522-0.658 0.657-2.385 2.22-3.453 2.055-0.822-0.082-1.315-1.809-2.549-3.124-2.96-2.96-4.851-2.714-4.275-3.865 0.491-0.904 4.438 1.233 6.987 1.481z"/>
+ <path fill="#e5e5e5" d="m157.796 167.481c1.444 0.16 10.346-1.845 10.666-1.043 0.32 0.641-5.532 2.406-7.458 4.41-0.641 0.642-2.325 2.166-3.367 2.005-0.803-0.08-1.284-1.764-2.486-3.047-2.887-2.887-4.732-2.647-4.17-3.769 0.48-0.882 4.329 1.202 6.815 1.444z"/>
+ <path fill="#e2e2e2" d="m157.841 167.521c1.407 0.156 10.083-1.799 10.397-1.017 0.312 0.625-5.394 2.346-7.271 4.299-0.625 0.625-2.267 2.111-3.282 1.954-0.782-0.078-1.251-1.719-2.423-2.97-2.814-2.814-4.612-2.58-4.065-3.674 0.469-0.859 4.221 1.172 6.644 1.408z"/>
+ <path fill="#dfdfdf" d="m157.886 167.56c1.37 0.152 9.821-1.751 10.127-0.99 0.304 0.609-5.254 2.285-7.081 4.188-0.609 0.609-2.208 2.056-3.198 1.903-0.761-0.076-1.218-1.675-2.36-2.893-2.741-2.741-4.492-2.513-3.959-3.579 0.456-0.837 4.111 1.142 6.471 1.371z"/>
+ <path fill="#dbdbdb" d="m157.931 167.6c1.335 0.148 9.561-1.704 9.857-0.963 0.296 0.592-5.114 2.223-6.893 4.076-0.593 0.593-2.149 2.001-3.113 1.853-0.741-0.074-1.186-1.631-2.297-2.817-2.668-2.667-4.373-2.446-3.854-3.483 0.445-0.815 4.003 1.111 6.3 1.334z"/>
+ <path fill="#d8d8d8" d="m157.977 167.64c1.298 0.144 9.299-1.658 9.587-0.937 0.288 0.576-4.974 2.163-6.704 3.964-0.576 0.577-2.091 1.947-3.027 1.803-0.721-0.072-1.153-1.586-2.234-2.74-2.596-2.594-4.253-2.379-3.748-3.388 0.431-0.792 3.891 1.081 6.126 1.298z"/>
+ <path fill="#d5d5d5" d="m158.022 167.68c1.261 0.14 9.037-1.611 9.317-0.911 0.28 0.56-4.834 2.102-6.516 3.853-0.56 0.561-2.032 1.892-2.942 1.752-0.7-0.07-1.12-1.541-2.172-2.663-2.521-2.521-4.133-2.312-3.643-3.292 0.421-0.77 3.784 1.05 5.956 1.261z"/>
+ <path fill="#d2d2d2" d="m158.067 167.72c1.225 0.136 8.775-1.564 9.049-0.884 0.271 0.543-4.695 2.041-6.327 3.741-0.545 0.544-1.974 1.837-2.857 1.701-0.682-0.068-1.09-1.497-2.109-2.585-2.449-2.449-4.014-2.246-3.538-3.198 0.407-0.748 3.673 1.02 5.782 1.225z"/>
+ <path fill="#cfcfcf" d="m158.112 167.76c1.188 0.132 8.515-1.518 8.779-0.858 0.264 0.527-4.555 1.98-6.139 3.63-0.527 0.528-1.915 1.782-2.772 1.65-0.66-0.066-1.057-1.452-2.046-2.508-2.376-2.376-3.895-2.179-3.433-3.103 0.397-0.725 3.565 0.99 5.611 1.189z"/>
+ <path fill="#ccc" d="m158.157 167.8c1.152 0.128 8.253-1.472 8.51-0.832 0.255 0.511-4.415 1.92-5.95 3.518-0.512 0.512-1.855 1.728-2.688 1.6-0.64-0.064-1.023-1.407-1.983-2.431-2.303-2.303-3.773-2.112-3.326-3.007 0.383-0.703 3.454 0.959 5.437 1.152z"/>
+ <path fill="#c8c8c8" d="m158.203 167.84c1.115 0.124 7.991-1.425 8.239-0.805 0.248 0.494-4.274 1.858-5.761 3.406-0.496 0.496-1.798 1.673-2.603 1.549-0.62-0.063-0.992-1.363-1.921-2.354-2.229-2.229-3.655-2.045-3.221-2.912 0.372-0.681 3.346 0.929 5.267 1.116z"/>
+ <path fill="#c5c5c5" d="m158.248 167.88c1.079 0.12 7.73-1.379 7.97-0.779 0.239 0.478-4.135 1.798-5.572 3.295-0.479 0.479-1.739 1.618-2.518 1.498-0.6-0.06-0.959-1.318-1.857-2.277-2.157-2.157-3.535-1.978-3.116-2.816 0.359-0.659 3.235 0.898 5.093 1.079z"/>
+ <path fill="#c2c2c2" d="m158.293 167.92c1.042 0.116 7.469-1.332 7.701-0.753 0.231 0.462-3.995 1.737-5.385 3.184-0.463 0.463-1.68 1.563-2.432 1.447-0.579-0.058-0.927-1.273-1.796-2.2-2.084-2.084-3.415-1.911-3.01-2.721 0.348-0.636 3.127 0.868 4.922 1.043z"/>
+ <path fill="#bfbfbf" d="m158.338 167.959c1.007 0.112 7.207-1.285 7.432-0.726 0.223 0.446-3.855 1.676-5.196 3.072-0.447 0.447-1.621 1.509-2.347 1.397-0.56-0.056-0.895-1.229-1.732-2.123-2.011-2.011-3.296-1.844-2.905-2.626 0.334-0.614 3.016 0.838 4.748 1.006z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m194.253 11.922c-1.222 2.631-3.812 23.214-0.248 20.892 3.594-2.341 13.57-5.312 19.886-7.013 7.003-1.886-17.188-19.463-19.638-13.879z"/>
+ <path fill="#060606" d="m194.485 12.307c-1.21 2.594-3.704 22.255-0.234 20.007 3.491-2.262 13.077-5.1 19.039-6.782 6.59-1.905-16.436-18.609-18.805-13.225z"/>
+ <path fill="#0c0c0c" d="m194.717 12.691c-1.198 2.557-3.595 21.296-0.221 19.124 3.391-2.184 12.586-4.888 18.194-6.551 6.177-1.924-15.684-17.757-17.973-12.573z"/>
+ <path fill="#131313" d="m194.949 13.076c-1.187 2.52-3.487 20.337-0.207 18.239 3.288-2.105 12.093-4.676 17.348-6.321 5.763-1.941-14.933-16.903-17.141-11.918z"/>
+ <path fill="#191919" d="m195.181 13.46c-1.177 2.483-3.379 19.378-0.193 17.355 3.187-2.027 11.6-4.464 16.502-6.09 5.349-1.959-14.182-16.05-16.309-11.265z"/>
+ <path fill="#1f1f1f" d="m195.413 13.845c-1.164 2.446-3.27 18.419-0.18 16.471 3.086-1.949 11.107-4.252 15.657-5.859 4.935-1.978-13.43-15.198-15.477-10.612z"/>
+ <path fill="#262626" d="m195.645 14.229c-1.153 2.409-3.162 17.46-0.166 15.586 2.983-1.87 10.616-4.04 14.811-5.628 4.521-1.995-12.679-14.344-14.645-9.958z"/>
+ <path fill="#2c2c2c" d="m195.878 14.614c-1.142 2.372-3.055 16.501-0.152 14.702 2.882-1.792 10.123-3.828 13.965-5.398 4.107-2.013-11.929-13.49-13.813-9.304z"/>
+ <path fill="#333" d="m196.11 14.999c-1.131 2.335-2.946 15.542-0.14 13.817 2.78-1.713 9.631-3.616 13.119-5.167 3.695-2.031-11.175-12.637-12.979-8.65z"/>
+ <path fill="#393939" d="m196.342 15.383c-1.118 2.299-2.838 14.583-0.126 12.934 2.68-1.636 9.139-3.404 12.274-4.937 3.28-2.049-10.425-11.784-12.148-7.997z"/>
+ <path fill="#3f3f3f" d="m196.574 15.768c-1.108 2.261-2.729 13.624-0.112 12.049 2.577-1.557 8.646-3.192 11.429-4.706 2.865-2.068-9.675-10.931-11.317-7.343z"/>
+ <path fill="#464646" d="m196.806 16.152c-1.097 2.225-2.622 12.665-0.1 11.165 2.477-1.479 8.154-2.98 10.583-4.475 2.453-2.086-8.922-10.078-10.483-6.69z"/>
+ <path fill="#4c4c4c" d="m197.038 16.537c-1.085 2.188-2.513 11.706-0.085 10.28 2.374-1.4 7.661-2.768 9.737-4.244 2.039-2.104-8.171-9.225-9.652-6.036z"/>
+ <path fill="#525252" d="m197.27 16.921c-1.073 2.151-2.405 10.747-0.071 9.396 2.272-1.322 7.168-2.556 8.891-4.013 1.625-2.122-7.42-8.371-8.82-5.383z"/>
+ <path fill="#595959" d="m197.502 17.306c-1.062 2.113-2.297 9.788-0.058 8.512 2.172-1.244 6.677-2.344 8.046-3.783 1.211-2.14-6.669-7.518-7.988-4.729z"/>
+ <path fill="#5f5f5f" d="m197.734 17.69c-1.05 2.077-2.188 8.829-0.044 7.627 2.069-1.165 6.184-2.132 7.2-3.552 0.797-2.157-5.917-6.664-7.156-4.075z"/>
+ <path fill="#666" d="m197.966 18.075c-1.038 2.04-2.079 7.87-0.029 6.743 1.968-1.087 5.69-1.92 6.354-3.321 0.382-2.176-5.167-5.812-6.325-3.422z"/>
+ <path fill="#6c6c6c" d="m198.198 18.459c-1.027 2.003-1.972 6.911-0.017 5.859 1.866-1.008 5.198-1.708 5.509-3.09-0.03-2.194-4.415-4.959-5.492-2.769z"/>
+ <path fill="#727272" d="m198.43 18.844c-1.017 1.966-1.863 5.952-0.003 4.975 1.765-0.93 4.706-1.496 4.662-2.86-0.443-2.212-3.662-4.106-4.659-2.115z"/>
+ <path fill="#797979" d="m198.662 19.228c-1.004 1.929-1.755 4.993 0.011 4.09 1.663-0.852 4.215-1.284 3.817-2.629-0.858-2.23-2.912-3.251-3.828-1.461z"/>
+ <path fill="#7f7f7f" d="m198.894 19.612c-0.993 1.892-1.647 4.034 0.023 3.206 1.563-0.773 3.723-1.072 2.973-2.398-1.272-2.248-2.161-2.399-2.996-0.808z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m143.502 46.386c-0.72 2.16 8.712 5.112 10.801 6.984 2.808 2.52 3.023 7.488 6.336 5.472 2.159-1.296 0.504-4.176-3.456-8.568-5.833-6.481-13.033-5.689-13.681-3.888z"/>
+ <path fill="#050505" d="m143.991 46.582c-0.716 2.073 8.275 4.9 10.336 6.741 2.745 2.457 2.961 7.249 6.146 5.313 2.094-1.254 0.449-4.072-3.343-8.28-5.574-6.203-12.491-5.505-13.139-3.774z"/>
+ <path fill="#0a0a0a" d="m144.479 46.779c-0.71 1.987 7.839 4.688 9.873 6.498 2.682 2.394 2.897 7.009 5.956 5.154 2.028-1.212 0.395-3.968-3.228-7.993-5.319-5.926-11.953-5.321-12.601-3.659z"/>
+ <path fill="#0f0f0f" d="m144.967 46.976c-0.704 1.9 7.403 4.476 9.41 6.254 2.62 2.33 2.835 6.77 5.766 4.995 1.964-1.171 0.342-3.864-3.112-7.706-5.064-5.647-11.415-5.137-12.064-3.543z"/>
+ <path fill="#141414" d="m145.456 47.172c-0.701 1.813 6.966 4.263 8.946 6.011 2.557 2.266 2.772 6.53 5.575 4.835 1.897-1.129 0.287-3.76-2.998-7.418-4.807-5.369-10.874-4.952-11.523-3.428z"/>
+ <path fill="#191919" d="m145.944 47.369c-0.696 1.726 6.53 4.051 8.483 5.768 2.493 2.203 2.71 6.291 5.385 4.676 1.833-1.087 0.231-3.656-2.884-7.13-4.551-5.093-10.335-4.769-10.984-3.314z"/>
+ <path fill="#1e1e1e" d="m146.433 47.565c-0.692 1.64 6.093 3.839 8.019 5.525 2.431 2.14 2.647 6.052 5.194 4.517 1.768-1.046 0.179-3.552-2.77-6.843-4.293-4.814-9.794-4.585-10.443-3.199z"/>
+ <path fill="#232323" d="m146.921 47.762c-0.686 1.553 5.657 3.627 7.558 5.282 2.367 2.076 2.583 5.813 5.003 4.357 1.702-1.003 0.124-3.448-2.654-6.555-4.04-4.537-9.257-4.401-9.907-3.084z"/>
+ <path fill="#282828" d="m147.409 47.959c-0.681 1.466 5.221 3.415 7.094 5.039 2.305 2.013 2.521 5.573 4.813 4.198 1.637-0.962 0.07-3.344-2.54-6.268-3.782-4.26-8.717-4.218-9.367-2.969z"/>
+ <path fill="#2d2d2d" d="m147.898 48.156c-0.677 1.379 4.784 3.203 6.63 4.795 2.242 1.949 2.457 5.333 4.622 4.039 1.572-0.92 0.016-3.24-2.425-5.98-3.526-3.983-8.177-4.034-8.827-2.854z"/>
+ <path fill="#333" d="m148.386 48.353c-0.673 1.292 4.348 2.99 6.167 4.552 2.179 1.886 2.394 5.095 4.432 3.88 1.506-0.878-0.038-3.136-2.312-5.693-3.268-3.705-7.636-3.85-8.287-2.739z"/>
+ <path fill="#383838" d="m148.875 48.549c-0.668 1.206 3.911 2.778 5.703 4.309 2.116 1.823 2.331 4.855 4.242 3.721 1.439-0.836-0.093-3.032-2.197-5.405-3.013-3.428-7.098-3.667-7.748-2.625z"/>
+ <path fill="#3d3d3d" d="m149.363 48.746c-0.662 1.119 3.475 2.566 5.24 4.065 2.053 1.759 2.268 4.616 4.052 3.562 1.375-0.795-0.147-2.928-2.082-5.118-2.757-3.15-6.559-3.483-7.21-2.509z"/>
+ <path fill="#424242" d="m149.851 48.942c-0.657 1.032 3.039 2.354 4.776 3.823 1.99 1.696 2.205 4.376 3.861 3.402 1.31-0.753-0.201-2.824-1.967-4.831-2.5-2.871-6.018-3.298-6.67-2.394z"/>
+ <path fill="#474747" d="m150.34 49.139c-0.652 0.946 2.603 2.142 4.313 3.58 1.927 1.632 2.143 4.137 3.671 3.243 1.244-0.712-0.256-2.72-1.853-4.543-2.245-2.595-5.48-3.115-6.131-2.28z"/>
+ <path fill="#4c4c4c" d="m150.828 49.336c-0.647 0.859 2.166 1.93 3.851 3.336 1.863 1.569 2.079 3.898 3.48 3.084 1.179-0.67-0.31-2.616-1.739-4.255-1.988-2.317-4.94-2.932-5.592-2.165z"/>
+ <path fill="#515151" d="m151.317 49.533c-0.645 0.772 1.729 1.718 3.386 3.093 1.802 1.505 2.018 3.658 3.29 2.925 1.114-0.628-0.364-2.512-1.624-3.968-1.732-2.04-4.4-2.748-5.052-2.05z"/>
+ <path fill="#565656" d="m151.805 49.729c-0.639 0.685 1.293 1.505 2.923 2.85 1.738 1.442 1.954 3.419 3.1 2.766 1.048-0.586-0.418-2.408-1.509-3.681-1.476-1.762-3.862-2.563-4.514-1.935z"/>
+ <path fill="#5b5b5b" d="m152.293 49.926c-0.633 0.598 0.857 1.293 2.46 2.606 1.677 1.379 1.892 3.18 2.91 2.606 0.983-0.544-0.473-2.304-1.395-3.393-1.22-1.483-3.322-2.379-3.975-1.819z"/>
+ <path fill="#606060" d="m152.782 50.123c-0.629 0.512 0.42 1.081 1.996 2.363 1.613 1.315 1.828 2.94 2.719 2.447 0.918-0.502-0.525-2.2-1.28-3.105-0.963-1.207-2.782-2.196-3.435-1.705z"/>
+ <path fill="#666" d="m153.27 50.319c-0.624 0.425-0.017 0.869 1.533 2.12 1.55 1.252 1.765 2.701 2.528 2.288 0.853-0.461-0.581-2.096-1.166-2.818-0.706-0.929-2.242-2.012-2.895-1.59z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m193.47 45.594c-0.072 1.08 2.951 1.728 4.896 2.448 1.944 0.648 5.76 3.24 7.56 5.256 1.801 1.944 5.688 7.704 6.553 6.192 0.863-1.368-2.017-5.328-2.809-6.984s-3.239-5.256-7.128-6.48c-3.384-1.008-9-1.297-9.072-0.432z"/>
+ <path fill="#060606" d="m193.779 45.67c-0.071 1.05 2.869 1.685 4.758 2.387 1.891 0.633 5.598 3.161 7.345 5.122 1.747 1.893 5.535 7.493 6.376 6.027 0.84-1.328-1.936-5.173-2.738-6.795-0.8-1.622-3.175-5.09-6.952-6.301-3.282-0.995-8.718-1.28-8.789-0.44z"/>
+ <path fill="#0c0c0c" d="m194.088 45.747c-0.07 1.021 2.785 1.641 4.62 2.327 1.836 0.618 5.436 3.081 7.131 4.988 1.692 1.842 5.382 7.282 6.198 5.862 0.814-1.288-1.855-5.019-2.67-6.607-0.808-1.587-3.11-4.925-6.776-6.122-3.178-0.983-8.433-1.264-8.503-0.448z"/>
+ <path fill="#131313" d="m194.397 45.824c-0.071 0.991 2.702 1.598 4.481 2.267 1.782 0.603 5.272 3.001 6.916 4.854 1.64 1.791 5.229 7.071 6.022 5.697 0.788-1.248-1.776-4.865-2.603-6.418-0.815-1.554-3.044-4.759-6.599-5.942-3.073-0.973-8.148-1.251-8.217-0.458z"/>
+ <path fill="#191919" d="m194.706 45.9c-0.069 0.961 2.618 1.555 4.345 2.206 1.728 0.588 5.109 2.922 6.7 4.721 1.586 1.74 5.075 6.86 5.846 5.531 0.764-1.207-1.696-4.711-2.532-6.23-0.824-1.519-2.979-4.593-6.424-5.763-2.972-0.959-7.866-1.234-7.935-0.465z"/>
+ <path fill="#1f1f1f" d="m195.015 45.977c-0.07 0.931 2.534 1.511 4.207 2.146 1.672 0.573 4.945 2.843 6.485 4.586 1.531 1.689 4.921 6.649 5.668 5.367 0.738-1.167-1.616-4.557-2.464-6.042-0.832-1.485-2.914-4.428-6.247-5.583-2.868-0.948-7.581-1.219-7.649-0.474z"/>
+ <path fill="#262626" d="m195.324 46.054c-0.069 0.901 2.451 1.468 4.069 2.085 1.618 0.557 4.784 2.763 6.271 4.453 1.479 1.638 4.769 6.438 5.491 5.201 0.714-1.127-1.536-4.402-2.396-5.854-0.839-1.451-2.848-4.263-6.07-5.404-2.765-0.934-7.298-1.202-7.365-0.481z"/>
+ <path fill="#2c2c2c" d="m195.632 46.13c-0.067 0.872 2.369 1.424 3.933 2.025 1.563 0.542 4.621 2.684 6.056 4.318 1.424 1.587 4.615 6.228 5.315 5.036 0.688-1.086-1.456-4.248-2.326-5.665-0.848-1.416-2.783-4.097-5.896-5.224-2.662-0.923-7.015-1.187-7.082-0.49z"/>
+ <path fill="#333" d="m195.941 46.207c-0.068 0.842 2.285 1.381 3.794 1.964 1.51 0.527 4.458 2.605 5.842 4.185 1.37 1.536 4.461 6.016 5.138 4.871 0.662-1.046-1.377-4.093-2.258-5.476-0.855-1.382-2.718-3.932-5.718-5.045-2.56-0.911-6.732-1.172-6.798-0.499z"/>
+ <path fill="#393939" d="m196.25 46.284c-0.066 0.813 2.202 1.338 3.656 1.904 1.456 0.512 4.296 2.525 5.627 4.051 1.317 1.485 4.308 5.805 4.961 4.706 0.638-1.006-1.296-3.939-2.188-5.288-0.863-1.348-2.652-3.766-5.542-4.866-2.457-0.899-6.449-1.157-6.514-0.507z"/>
+ <path fill="#3f3f3f" d="m196.559 46.36c-0.067 0.783 2.118 1.295 3.518 1.844 1.402 0.497 4.133 2.446 5.412 3.917 1.263 1.434 4.155 5.594 4.785 4.541 0.612-0.966-1.217-3.785-2.12-5.1-0.872-1.313-2.587-3.6-5.366-4.687-2.353-0.886-6.165-1.141-6.229-0.515z"/>
+ <path fill="#464646" d="m196.868 46.437c-0.065 0.753 2.035 1.251 3.38 1.783 1.349 0.482 3.972 2.367 5.197 3.783 1.21 1.383 4.002 5.383 4.608 4.375 0.588-0.926-1.137-3.63-2.052-4.911-0.879-1.279-2.521-3.435-5.189-4.507-2.25-0.874-5.881-1.125-5.944-0.523z"/>
+ <path fill="#4c4c4c" d="m197.177 46.514c-0.066 0.723 1.95 1.208 3.241 1.723 1.293 0.467 3.809 2.287 4.983 3.649 1.155 1.332 3.848 5.172 4.431 4.21 0.563-0.885-1.057-3.476-1.982-4.723-0.888-1.245-2.456-3.269-5.014-4.328-2.146-0.862-5.597-1.109-5.659-0.531z"/>
+ <path fill="#525252" d="m197.486 46.591c-0.066 0.693 1.868 1.164 3.104 1.662 1.239 0.452 3.646 2.208 4.769 3.515 1.102 1.281 3.695 4.961 4.254 4.045 0.537-0.845-0.976-3.321-1.913-4.534-0.896-1.21-2.391-3.103-4.838-4.148-2.044-0.851-5.315-1.095-5.376-0.54z"/>
+ <path fill="#595959" d="m197.795 46.667c-0.064 0.664 1.784 1.121 2.968 1.602 1.184 0.437 3.481 2.128 4.552 3.381 1.049 1.23 3.542 4.75 4.078 3.88 0.512-0.805-0.897-3.167-1.846-4.346-0.902-1.176-2.325-2.938-4.66-3.969-1.942-0.838-5.031-1.078-5.092-0.548z"/>
+ <path fill="#5f5f5f" d="m198.104 46.744c-0.065 0.634 1.701 1.078 2.829 1.541 1.13 0.421 3.318 2.049 4.338 3.248 0.994 1.179 3.388 4.539 3.899 3.715 0.487-0.765-0.815-3.013-1.775-4.157-0.911-1.142-2.261-2.772-4.485-3.79-1.837-0.826-4.746-1.064-4.806-0.557z"/>
+ <path fill="#666" d="m198.413 46.821c-0.063 0.604 1.617 1.034 2.691 1.481 1.076 0.406 3.157 1.969 4.123 3.113 0.94 1.128 3.234 4.328 3.724 3.55 0.462-0.725-0.737-2.858-1.707-3.969-0.919-1.108-2.195-2.606-4.309-3.61-1.734-0.814-4.463-1.049-4.522-0.565z"/>
+ <path fill="#6c6c6c" d="m198.721 46.897c-0.063 0.574 1.534 0.991 2.554 1.42 1.021 0.391 2.994 1.89 3.908 2.979 0.887 1.077 3.082 4.117 3.548 3.384 0.436-0.685-0.657-2.704-1.64-3.78-0.927-1.074-2.13-2.44-4.132-3.431-1.631-0.8-4.179-1.031-4.238-0.572z"/>
+ <path fill="#727272" d="m199.03 46.974c-0.063 0.544 1.451 0.948 2.416 1.36 0.967 0.376 2.831 1.811 3.694 2.846 0.833 1.026 2.928 3.906 3.369 3.219 0.411-0.644-0.576-2.549-1.569-3.592-0.936-1.04-2.064-2.275-3.956-3.251-1.528-0.79-3.896-1.017-3.954-0.582z"/>
+ <path fill="#797979" d="m199.339 47.051c-0.062 0.515 1.368 0.904 2.278 1.299 0.913 0.361 2.669 1.731 3.479 2.712 0.779 0.975 2.774 3.695 3.193 3.054 0.386-0.604-0.497-2.396-1.501-3.403-0.942-1.005-1.999-2.11-3.78-3.072-1.424-0.778-3.612-1.002-3.669-0.59z"/>
+ <path fill="#7f7f7f" d="m199.648 47.127c-0.063 0.485 1.284 0.861 2.14 1.239 0.859 0.346 2.506 1.652 3.265 2.578 0.726 0.924 2.621 3.484 3.017 2.889 0.361-0.564-0.417-2.241-1.432-3.215-0.951-0.971-1.935-1.944-3.604-2.893-1.323-0.765-3.33-0.986-3.386-0.598z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#995900" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.017 11.592-31.104 19.152-13.968 9.576-18.792 13.824-23.328 18.359-7.056 7.057-13.752 9.432-24.48 9.432s-15.552-2.231-18.863-5.184c-3.313-2.88-6.984-10.225-6.624-21.168 0.288-10.872 3.744-20.809 5.399-37.729 0.721-7.271 0.648-16.271 0.648-24.264 0-10.08 0.144-18.648 2.304-19.943 3.889-2.448 4.752-2.592 9.36-2.592 4.607 0 6.696 0.287 8.208 1.799 1.439 1.44 0.864 4.752 0.359 9.433-0.432 4.681 1.801 6.192 4.032 8.136 2.232 1.872 4.248 4.248 11.305 4.824 7.056 0.504 9.647-0.648 12.96-2.736 3.312-2.088 7.991-5.832 9.72-7.992 1.656-2.088 5.76-9.287 6.552-9.287 0.719 0 5.472-1.656 8.136 2.232z"/>
+ <path fill="#9e5e00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.12 11.556-31.26 19.008-13.885 9.371-18.903 13.54-23.521 17.902-6.912 6.74-13.414 9.084-23.915 9.019-10.411-0.047-15.116-2.181-18.414-5.118-3.297-2.867-6.931-9.966-6.613-20.578 0.205-10.851 3.701-20.683 5.256-37.279 0.666-7.379 0.407-16.303 0.335-24.375-0.076-10.068-0.072-18.627 2.084-19.922 3.889-2.444 4.752-2.592 9.36-2.592 4.607 0 6.7 0.291 8.208 1.799 1.491 1.492 0.767 4.887 0.205 9.408-0.63 4.658 1.458 6.486 3.795 8.607 2.34 2.059 4.489 4.471 11.534 5.021 7.232 0.482 10.015-0.832 13.362-3.106 3.303-2.207 7.773-5.903 9.513-8.168 1.641-2.132 5.727-9.386 6.519-9.386 0.719 0 5.472-1.656 8.136 2.232z"/>
+ <path fill="#a36400" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.226 11.52-31.414 18.863-13.803 9.166-19.016 13.256-23.717 17.447-6.768 6.422-13.075 8.733-23.35 8.604-10.094-0.094-14.682-2.131-17.964-5.055-3.283-2.852-6.876-9.705-6.603-19.987 0.122-10.828 3.657-20.556 5.112-36.828 0.612-7.487 0.165-16.336 0.021-24.487-0.15-10.058-0.287-18.605 1.865-19.9 3.889-2.44 4.752-2.592 9.36-2.592 4.607 0 6.703 0.295 8.208 1.799 1.541 1.541 0.67 5.02 0.051 9.383-0.828 4.637 1.116 6.781 3.556 9.078 2.448 2.248 4.731 4.695 11.766 5.221 7.409 0.461 10.383-1.016 13.767-3.477 3.29-2.326 7.552-5.977 9.302-8.346 1.627-2.175 5.695-9.482 6.487-9.482 0.72-0.001 5.473-1.657 8.137 2.231z"/>
+ <path fill="#a86a00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.329 11.484-31.568 18.72-13.721 8.961-19.127 12.972-23.911 16.989-6.624 6.105-12.737 8.384-22.785 8.189-9.777-0.141-14.245-2.08-17.514-4.99-3.27-2.836-6.822-9.445-6.591-19.396 0.038-10.807 3.613-20.43 4.968-36.378 0.558-7.597-0.076-16.368-0.292-24.599-0.228-10.047-0.504-18.584 1.645-19.879 3.889-2.438 4.752-2.592 9.36-2.592 4.607 0 6.707 0.299 8.208 1.799 1.591 1.593 0.573 5.152-0.104 9.357-1.025 4.615 0.774 7.077 3.319 9.551 2.556 2.434 4.972 4.918 11.995 5.418 7.585 0.439 10.75-1.199 14.17-3.849 3.279-2.444 7.333-6.048 9.093-8.521 1.613-2.219 5.663-9.58 6.455-9.58 0.719 0.001 5.472-1.655 8.136 2.233z"/>
+ <path fill="#ad7000" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.434 11.447-31.724 18.576-13.637 8.756-19.238 12.687-24.106 16.531-6.479 5.789-12.397 8.035-22.219 7.776-9.461-0.188-13.809-2.03-17.063-4.925-3.254-2.823-6.769-9.188-6.581-18.807-0.043-10.785 3.571-20.305 4.824-35.928 0.504-7.705-0.316-16.402-0.604-24.711-0.303-10.037-0.72-18.563 1.425-19.857 3.889-2.434 4.752-2.592 9.36-2.592 4.607 0 6.711 0.303 8.208 1.799 1.642 1.643 0.475 5.285-0.259 9.332-1.225 4.594 0.432 7.373 3.082 10.022 2.664 2.621 5.212 5.142 12.225 5.616 7.762 0.418 11.117-1.383 14.573-4.219 3.269-2.563 7.113-6.121 8.885-8.698 1.598-2.261 5.63-9.677 6.422-9.677 0.719 0.002 5.472-1.654 8.136 2.234z"/>
+ <path fill="#b27500" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.538 11.412-31.879 18.432-13.554 8.551-19.35 12.402-24.3 16.074-6.336 5.473-12.06 7.686-21.654 7.361-9.144-0.233-13.374-1.979-16.613-4.859-3.24-2.809-6.714-8.928-6.57-18.216-0.126-10.765 3.528-20.179 4.68-35.478 0.45-7.813-0.558-16.435-0.918-24.822-0.378-10.026-0.936-18.541 1.206-19.836 3.889-2.43 4.752-2.592 9.36-2.592 4.607 0 6.714 0.305 8.208 1.799 1.691 1.693 0.378 5.418-0.414 9.307-1.422 4.572 0.09 7.668 2.844 10.494 2.772 2.808 5.454 5.363 12.456 5.814 7.938 0.396 11.484-1.566 14.977-4.591 3.258-2.682 6.894-6.192 8.676-8.874 1.584-2.304 5.598-9.773 6.39-9.773 0.718 0 5.471-1.656 8.135 2.232z"/>
+ <path fill="#b77b00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.643 11.376-32.033 18.288-13.472 8.345-19.461 12.118-24.494 15.616-6.192 5.156-11.723 7.338-21.089 6.949-8.827-0.281-12.938-1.93-16.164-4.795-3.226-2.795-6.66-8.67-6.56-17.627-0.209-10.742 3.485-20.052 4.536-35.027 0.396-7.92-0.799-16.467-1.23-24.934-0.454-10.015-1.152-18.52 0.985-19.814 3.889-2.426 4.752-2.592 9.36-2.592 4.607 0 6.718 0.31 8.208 1.799 1.743 1.744 0.281 5.553-0.569 9.281-1.62 4.551-0.252 7.963 2.607 10.967 2.88 2.994 5.694 5.586 12.686 6.012 8.115 0.373 11.852-1.75 15.379-4.961 3.248-2.801 6.676-6.264 8.469-9.051 1.568-2.348 5.564-9.871 6.356-9.871 0.72 0 5.473-1.656 8.137 2.232z"/>
+ <path fill="#bc8100" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.747 11.34-32.188 18.145-13.389 8.139-19.574 11.834-24.689 15.159-6.048 4.839-11.383 6.988-20.523 6.534-8.51-0.328-12.503-1.879-15.714-4.73-3.211-2.779-6.606-8.41-6.549-17.035-0.292-10.721 3.441-19.926 4.393-34.578 0.342-8.028-1.041-16.498-1.545-25.045-0.529-10.004-1.368-18.498 0.767-19.793 3.889-2.422 4.752-2.592 9.36-2.592 4.607 0 6.721 0.313 8.208 1.799 1.793 1.793 0.184 5.686-0.723 9.256-1.818 4.529-0.595 8.259 2.367 11.438 2.988 3.184 5.938 5.811 12.917 6.211 8.291 0.352 12.22-1.934 15.783-5.332 3.236-2.92 6.454-6.336 8.258-9.227 1.556-2.391 5.533-9.969 6.325-9.969 0.72-0.001 5.473-1.657 8.137 2.231z"/>
+ <path fill="#c18700" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.852 11.304-32.343 18-13.306 7.936-19.685 11.549-24.883 14.703-5.904 4.521-11.045 6.638-19.959 6.119-8.193-0.375-12.067-1.828-15.264-4.666-3.197-2.764-6.553-8.149-6.537-16.444-0.375-10.699 3.397-19.8 4.248-34.128 0.288-8.137-1.282-16.531-1.858-25.156-0.604-9.994-1.584-18.477 0.547-19.771 3.889-2.42 4.752-2.592 9.36-2.592 4.607 0 6.725 0.316 8.208 1.799 1.843 1.845 0.087 5.818-0.878 9.231-2.017 4.507-0.937 8.554 2.131 11.909 3.096 3.369 6.178 6.033 13.146 6.408 8.468 0.33 12.587-2.117 16.187-5.703 3.225-3.038 6.235-6.408 8.049-9.402 1.541-2.436 5.501-10.066 6.293-10.066 0.72-0.001 5.473-1.657 8.137 2.231z"/>
+ <path fill="#c68c00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-20.955 11.268-32.498 17.855-13.223 7.73-19.796 11.266-25.077 14.246-5.761 4.204-10.706 6.289-19.394 5.707-7.877-0.423-11.631-1.779-14.813-4.602-3.183-2.751-6.498-7.891-6.527-15.855-0.457-10.677 3.355-19.674 4.104-33.678 0.234-8.244-1.521-16.563-2.17-25.268-0.681-9.983-1.8-18.455 0.327-19.75 3.889-2.416 4.752-2.592 9.36-2.592 4.607 0 6.729 0.32 8.208 1.799 1.894 1.895-0.011 5.951-1.033 9.207-2.214 4.484-1.278 8.848 1.895 12.379 3.203 3.558 6.418 6.258 13.377 6.607 8.644 0.309 12.952-2.301 16.589-6.074 3.215-3.156 6.016-6.479 7.841-9.58 1.526-2.477 5.468-10.162 6.26-10.162 0.718 0.001 5.471-1.655 8.135 2.233z"/>
+ <path fill="#cc9200" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.061 11.232-32.652 17.712-13.141 7.524-19.908 10.979-25.272 13.788-5.616 3.888-10.368 5.939-18.828 5.292-7.56-0.468-11.195-1.728-14.363-4.536-3.168-2.736-6.444-7.632-6.517-15.264-0.54-10.656 3.313-19.549 3.96-33.229 0.181-8.352-1.764-16.596-2.483-25.38-0.757-9.972-2.017-18.433 0.107-19.728 3.889-2.412 4.752-2.592 9.36-2.592 4.607 0 6.731 0.323 8.208 1.799 1.944 1.945-0.108 6.084-1.188 9.181-2.412 4.464-1.62 9.144 1.656 12.853 3.313 3.744 6.66 6.479 13.608 6.803 8.819 0.289 13.319-2.483 16.991-6.443 3.204-3.275 5.797-6.553 7.633-9.756 1.512-2.52 5.436-10.26 6.228-10.26 0.719 0 5.472-1.656 8.136 2.232z"/>
+ <path fill="#d19800" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.164 11.195-32.808 17.568-13.057 7.318-20.019 10.695-25.466 13.33-5.473 3.571-10.03 5.592-18.263 4.879-7.243-0.516-10.761-1.678-13.914-4.472-3.153-2.722-6.391-7.372-6.506-14.674-0.623-10.634 3.27-19.422 3.816-32.778 0.126-8.459-2.005-16.627-2.797-25.49-0.832-9.961-2.232-18.412-0.112-19.707 3.889-2.408 4.752-2.592 9.36-2.592 4.607 0 6.736 0.328 8.208 1.799 1.995 1.996-0.205 6.219-1.343 9.156-2.61 4.442-1.962 9.438 1.419 13.323 3.42 3.931 6.9 6.703 13.838 7.002 8.997 0.267 13.687-2.668 17.395-6.815 3.194-3.395 5.577-6.623 7.424-9.932 1.497-2.564 5.403-10.357 6.195-10.357 0.721 0 5.474-1.656 8.138 2.232z"/>
+ <path fill="#d69e00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.27 11.16-32.962 17.424-12.975 7.114-20.132 10.412-25.661 12.874-5.327 3.254-9.69 5.242-17.697 4.464-6.927-0.563-10.325-1.627-13.464-4.406-3.14-2.707-6.337-7.113-6.494-14.084-0.706-10.611 3.225-19.295 3.672-32.328 0.072-8.567-2.247-16.66-3.111-25.603-0.907-9.95-2.448-18.39-0.331-19.685 3.889-2.404 4.752-2.592 9.36-2.592 4.607 0 6.739 0.332 8.208 1.799 2.045 2.045-0.302 6.352-1.497 9.131-2.808 4.421-2.304 9.734 1.18 13.795 3.528 4.119 7.144 6.927 14.069 7.199 9.173 0.246 14.055-2.851 17.799-7.185 3.182-3.514 5.356-6.696 7.214-10.108 1.483-2.607 5.371-10.455 6.163-10.455 0.719 0 5.472-1.656 8.136 2.232z"/>
+ <path fill="#dba300" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.373 11.124-33.116 17.279-12.893 6.91-20.243 10.127-25.855 12.418-5.184 2.937-9.353 4.892-17.133 4.05-6.609-0.609-9.889-1.577-13.014-4.343-3.125-2.692-6.282-6.854-6.483-13.492-0.789-10.592 3.182-19.17 3.528-31.879 0.018-8.676-2.488-16.692-3.425-25.713-0.982-9.94-2.664-18.369-0.551-19.664 3.889-2.401 4.752-2.592 9.36-2.592 4.607 0 6.743 0.334 8.208 1.799 2.095 2.097-0.399 6.484-1.652 9.105-3.006 4.398-2.646 10.029 0.943 14.268 3.636 4.305 7.384 7.148 14.299 7.397 9.349 0.224 14.422-3.034 18.202-7.558 3.171-3.631 5.137-6.768 7.005-10.284 1.469-2.649 5.339-10.552 6.131-10.552 0.72 0.001 5.473-1.655 8.137 2.233z"/>
+ <path fill="#e0a900" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.478 11.088-33.271 17.136-12.81 6.704-20.354 9.843-26.05 11.96-5.04 2.62-9.015 4.543-16.567 3.637-6.293-0.656-9.453-1.527-12.563-4.277-3.11-2.68-6.229-6.596-6.474-12.903-0.871-10.569 3.141-19.044 3.384-31.428-0.035-8.784-2.728-16.726-3.735-25.826-1.06-9.929-2.88-18.347-0.771-19.642 3.889-2.397 4.752-2.592 9.36-2.592 4.607 0 6.747 0.338 8.208 1.799 2.146 2.146-0.497 6.617-1.808 9.08-3.203 4.377-2.987 10.324 0.706 14.738 3.744 4.493 7.624 7.373 14.529 7.596 9.526 0.203 14.789-3.217 18.605-7.926 3.161-3.752 4.918-6.841 6.797-10.463 1.454-2.693 5.306-10.648 6.098-10.648 0.719-0.001 5.472-1.657 8.136 2.231z"/>
+ <path fill="#e5af00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.582 11.052-33.427 16.992-12.726 6.498-20.466 9.558-26.244 11.502-4.896 2.304-8.676 4.193-16.002 3.222-5.976-0.702-9.018-1.476-12.114-4.212-3.096-2.664-6.174-6.336-6.462-12.313-0.953-10.547 3.097-18.918 3.24-30.978-0.09-8.892-2.97-16.758-4.05-25.938-1.134-9.918-3.096-18.324-0.99-19.619 3.889-2.395 4.752-2.592 9.36-2.592 4.607 0 6.75 0.342 8.208 1.799 2.196 2.197-0.594 6.75-1.962 9.055-3.402 4.355-3.33 10.619 0.468 15.21 3.852 4.681 7.866 7.597 14.76 7.794 9.702 0.18 15.156-3.402 19.008-8.298 3.15-3.87 4.698-6.912 6.589-10.638 1.439-2.736 5.273-10.746 6.065-10.746 0.72 0 5.473-1.656 8.137 2.232z"/>
+ <path fill="#eab500" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.687 11.016-33.582 16.848-12.643 6.293-20.576 9.274-26.438 11.045-4.752 1.987-8.338 3.846-15.438 2.809-5.658-0.75-8.582-1.426-11.664-4.147-3.08-2.649-6.119-6.077-6.45-11.722-1.037-10.526 3.053-18.792 3.096-30.528-0.144-9-3.211-16.79-4.363-26.049-1.21-9.907-3.312-18.304-1.21-19.599 3.889-2.391 4.752-2.592 9.36-2.592 4.607 0 6.754 0.346 8.208 1.799 2.247 2.248-0.691 6.885-2.117 9.029-3.6 4.336-3.672 10.916 0.231 15.682 3.96 4.867 8.106 7.82 14.989 7.992 9.879 0.158 15.523-3.586 19.411-8.668 3.141-3.99 4.479-6.984 6.38-10.814 1.426-2.78 5.241-10.844 6.033-10.844 0.721-0.001 5.474-1.657 8.138 2.231z"/>
+ <path fill="#efba00" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.791 10.98-33.735 16.703-12.562 6.089-20.69 8.99-26.633 10.589-4.608 1.67-7.999 3.496-14.872 2.394-5.343-0.796-8.147-1.375-11.215-4.082-3.066-2.636-6.065-5.818-6.439-11.132-1.12-10.504 3.009-18.666 2.952-30.077-0.198-9.109-3.453-16.822-4.677-26.162-1.285-9.896-3.528-18.281-1.43-19.576 3.889-2.387 4.752-2.592 9.36-2.592 4.607 0 6.757 0.35 8.208 1.799 2.297 2.297-0.788 7.018-2.271 9.004-3.798 4.314-4.014 11.211-0.008 16.154 4.068 5.055 8.35 8.043 15.221 8.189 10.056 0.137 15.892-3.77 19.815-9.039 3.128-4.107 4.258-7.057 6.17-10.99 1.411-2.824 5.209-10.941 6.001-10.941 0.72-0.001 5.473-1.657 8.137 2.231z"/>
+ <path fill="#f4c000" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.896 10.943-33.891 16.561-12.478 5.883-20.801 8.704-26.827 10.131-4.464 1.353-7.661 3.146-14.307 1.979-5.025-0.843-7.711-1.325-10.765-4.019-3.053-2.621-6.012-5.558-6.429-10.541-1.203-10.482 2.966-18.539 2.809-29.627-0.253-9.217-3.694-16.855-4.99-26.272-1.361-9.886-3.744-18.261-1.649-19.556 3.889-2.383 4.752-2.592 9.36-2.592 4.607 0 6.761 0.353 8.208 1.799 2.347 2.349-0.885 7.15-2.426 8.979-3.996 4.291-4.356 11.505-0.245 16.625 4.176 5.241 8.59 8.265 15.451 8.388 10.23 0.115 16.258-3.953 20.218-9.41 3.117-4.227 4.039-7.129 5.961-11.168 1.396-2.865 5.177-11.037 5.969-11.037 0.72 0 5.473-1.656 8.137 2.232z"/>
+ <path fill="#f9c600" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-21.999 10.908-34.046 16.416-12.395 5.678-20.912 8.421-27.021 9.674-4.32 1.036-7.322 2.797-13.741 1.566-4.709-0.891-7.275-1.275-10.314-3.953-3.037-2.607-5.958-5.299-6.419-9.951-1.284-10.461 2.925-18.414 2.664-29.178-0.306-9.324-3.934-16.887-5.302-26.385-1.437-9.875-3.96-18.238-1.869-19.533 3.889-2.379 4.752-2.592 9.36-2.592 4.607 0 6.765 0.356 8.208 1.799 2.397 2.398-0.983 7.283-2.581 8.955-4.194 4.269-4.698 11.799-0.482 17.096 4.284 5.429 8.83 8.488 15.682 8.586 10.407 0.094 16.625-4.137 20.621-9.781 3.106-4.345 3.819-7.199 5.753-11.344 1.382-2.909 5.144-11.135 5.936-11.135 0.718 0 5.471-1.656 8.135 2.232z"/>
+ <path fill="#fc0" d="m303.631 262.529c4.464 6.479-0.145 14.904 3.096 20.089 5.328 8.496 16.056 17.063 20.16 19.439 2.952 1.8 7.128 3.527 6.983 8.783-0.216 5.977-3.168 7.561-4.823 9.217-3.313 3.313-22.104 10.872-34.2 16.271-12.313 5.473-21.024 8.137-27.217 9.217-4.176 0.72-6.983 2.447-13.176 1.151-4.392-0.937-6.84-1.224-9.864-3.888-3.023-2.592-5.903-5.04-6.407-9.359-1.368-10.441 2.88-18.289 2.52-28.729-0.36-9.432-4.176-16.92-5.616-26.496-1.512-9.864-4.176-18.217-2.088-19.512 3.889-2.377 4.752-2.592 9.36-2.592 4.607 0 6.768 0.359 8.208 1.799 2.448 2.449-1.08 7.416-2.736 8.929-4.392 4.248-5.04 12.096-0.72 17.567 4.392 5.617 9.072 8.713 15.912 8.785 10.584 0.071 16.992-4.32 21.023-10.152 3.097-4.465 3.601-7.272 5.544-11.521 1.368-2.952 5.112-11.231 5.904-11.231 0.72 0.001 5.473-1.655 8.137 2.233z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fc0" d="m236.263 275.762c-0.709-0.258-3.932-15.209-2.191-16.239 3.351-1.997 4.253-2.319 8.377-2.319s6.057 0.322 7.346 1.61c2.126 2.127-1.159 6.702-2.448 7.991-3.738 3.673-10.375 9.215-11.084 8.957z"/>
+ <path fill="#ffcc02" d="m236.492 275.286c-0.77-0.326-4.102-14.719-2.368-15.742 3.344-1.992 4.278-2.211 8.322-2.211 4.124 0 5.976 0.269 7.282 1.602 2.105 2.136-1.119 6.572-2.398 7.852-3.727 3.663-10.081 8.811-10.838 8.499z"/>
+ <path fill="#ffcc05" d="m236.721 274.809c-0.832-0.393-4.273-14.229-2.547-15.247 3.339-1.983 4.306-2.101 8.269-2.101 4.124 0 5.896 0.213 7.217 1.592 2.087 2.146-1.076 6.443-2.346 7.714-3.718 3.653-9.788 8.409-10.593 8.042z"/>
+ <path fill="#ffcc07" d="m236.949 274.333c-0.892-0.461-4.443-13.74-2.722-14.75 3.331-1.979 4.33-1.992 8.213-1.992 4.124 0 5.814 0.158 7.151 1.582 2.068 2.156-1.033 6.316-2.294 7.574-3.707 3.644-9.494 8.007-10.348 7.586z"/>
+ <path fill="#ffcd0a" d="m237.178 273.855c-0.954-0.528-4.614-13.249-2.9-14.254 3.326-1.972 4.355-1.882 8.158-1.882 4.124 0 5.734 0.104 7.089 1.572 2.048 2.166-0.993 6.187-2.243 7.437-3.699 3.634-9.202 7.605-10.104 7.127z"/>
+ <path fill="#ffcd0c" d="m237.407 273.377c-1.015-0.596-4.785-12.758-3.077-13.758 3.319-1.965 4.382-1.771 8.104-1.771 4.124 0 5.653 0.049 7.023 1.563 2.029 2.176-0.951 6.057-2.19 7.299-3.69 3.623-8.91 7.201-9.86 6.667z"/>
+ <path fill="#ffcd0f" d="m237.636 272.901c-1.077-0.662-4.956-12.27-3.256-13.261 3.313-1.959 4.408-1.663 8.05-1.663 4.124 0 5.573-0.006 6.959 1.553 2.01 2.186-0.908 5.93-2.14 7.159-3.679 3.614-8.615 6.8-9.613 6.212z"/>
+ <path fill="#ffcd11" d="m237.864 272.424c-1.137-0.731-5.126-11.779-3.431-12.766 3.306-1.951 4.433-1.553 7.994-1.553 4.123 0 5.492-0.061 6.895 1.543 1.991 2.193-0.867 5.801-2.089 7.021-3.669 3.606-8.321 6.397-9.369 5.755z"/>
+ <path fill="#ffce14" d="m238.093 271.948c-1.197-0.799-5.297-11.289-3.607-12.27 3.299-1.946 4.459-1.443 7.938-1.443 4.124 0 5.412-0.115 6.83 1.533 1.973 2.204-0.824 5.671-2.037 6.883-3.659 3.596-8.028 5.993-9.124 5.297z"/>
+ <path fill="#ffce16" d="m238.322 271.471c-1.26-0.867-5.468-10.801-3.786-11.773 3.293-1.939 4.485-1.334 7.884-1.334 4.124 0 5.332-0.171 6.767 1.524 1.953 2.213-0.783 5.542-1.985 6.743-3.651 3.586-7.736 5.591-8.88 4.84z"/>
+ <path fill="#ffce19" d="m238.551 270.995c-1.32-0.935-5.639-10.312-3.963-11.277 3.286-1.934 4.511-1.225 7.829-1.225 4.124 0 5.252-0.226 6.702 1.514 1.934 2.224-0.741 5.414-1.934 6.605-3.64 3.576-7.442 5.187-8.634 4.383z"/>
+ <path fill="#ffce1c" d="m238.779 270.517c-1.382-1.002-5.809-9.821-4.14-10.781 3.279-1.926 4.535-1.114 7.774-1.114 4.124 0 5.171-0.279 6.637 1.504 1.914 2.233-0.698 5.285-1.882 6.467-3.63 3.566-7.148 4.784-8.389 3.924z"/>
+ <path fill="#ffcf1e" d="m239.008 270.04c-1.442-1.068-5.979-9.33-4.316-10.283 3.272-1.922 4.562-1.006 7.72-1.006 4.124 0 5.09-0.334 6.572 1.494 1.895 2.244-0.657 5.156-1.83 6.328-3.622 3.556-6.857 4.383-8.146 3.467z"/>
+ <path fill="#ffcf21" d="m239.237 269.563c-1.505-1.137-6.151-8.841-4.495-9.788 3.267-1.914 4.588-0.896 7.666-0.896 4.124 0 5.009-0.389 6.508 1.486 1.875 2.252-0.616 5.025-1.778 6.188-3.613 3.548-6.564 3.981-7.901 3.01z"/>
+ <path fill="#ffcf23" d="m239.466 269.086c-1.565-1.205-6.321-8.352-4.672-9.293 3.262-1.906 4.613-0.785 7.61-0.785 4.124 0 4.93-0.444 6.444 1.476 1.855 2.261-0.573 4.897-1.728 6.052-3.601 3.537-6.269 3.575-7.654 2.55z"/>
+ <path fill="#ffcf26" d="m239.694 268.61c-1.627-1.273-6.492-7.861-4.849-8.796 3.255-1.901 4.64-0.677 7.556-0.677 4.124 0 4.849-0.499 6.379 1.466 1.837 2.271-0.531 4.769-1.675 5.912-3.593 3.528-5.977 3.174-7.411 2.095z"/>
+ <path fill="#ffd028" d="m239.923 268.133c-1.688-1.34-6.663-7.373-5.025-8.301 3.248-1.895 4.665-0.566 7.501-0.566 4.124 0 4.768-0.555 6.314 1.456 1.817 2.28-0.489 4.64-1.624 5.774-3.583 3.519-5.684 2.771-7.166 1.637z"/>
+ <path fill="#ffd02b" d="m240.152 267.657c-1.749-1.408-6.834-6.883-5.203-7.805 3.241-1.889 4.69-0.457 7.446-0.457 4.124 0 4.687-0.609 6.25 1.447 1.798 2.289-0.448 4.51-1.573 5.635-3.572 3.509-5.39 2.367-6.92 1.18z"/>
+ <path fill="#ffd02d" d="m240.381 267.178c-1.811-1.475-7.005-6.391-5.381-7.307 3.235-1.881 4.717-0.348 7.393-0.348 4.124 0 4.606-0.664 6.185 1.438 1.779 2.299-0.405 4.381-1.521 5.496-3.564 3.501-5.098 1.965-6.676 0.721z"/>
+ <path fill="#ffd030" d="m240.609 266.702c-1.871-1.543-7.175-5.902-5.557-6.811 3.228-1.875 4.741-0.238 7.336-0.238 4.124 0 4.526-0.719 6.122 1.428 1.759 2.31-0.364 4.252-1.471 5.357-3.552 3.49-4.803 1.562-6.43 0.264z"/>
+ <path fill="#ffd133" d="m240.838 266.225c-1.933-1.611-7.346-5.413-5.734-6.314 3.222-1.869 4.768-0.129 7.281-0.129 4.124 0 4.446-0.773 6.058 1.418 1.74 2.318-0.322 4.123-1.418 5.219-3.545 3.48-4.512 1.16-6.187-0.194z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fc0" d="m302.769 263.374c3.742 5.461-0.062 12.76 2.638 17.117-6.809-6.258-9.938-8.834-19.324 0.367 2.577-3.742 3.129-6.257 4.725-9.814 1.104-2.455 4.354-9.57 5.029-9.57 0.613-0.001 4.724-1.35 6.932 1.9z"/>
+ <path fill="#ffcc02" d="m302.73 263.413c3.655 5.334 0.035 12.601 2.578 16.723-6.668-6.098-9.729-8.666-18.908 0.322 2.421-3.527 3.025-6.094 4.605-9.592 1.122-2.462 4.243-9.302 4.951-9.311 0.628-0.008 4.617-1.318 6.774 1.858z"/>
+ <path fill="#ffcc05" d="m302.691 263.45c3.568 5.209 0.132 12.441 2.517 16.332-6.526-5.938-9.519-8.5-18.492 0.277 2.268-3.314 2.924-5.934 4.488-9.372 1.141-2.468 4.132-9.032 4.873-9.052 0.641-0.013 4.508-1.284 6.614 1.815z"/>
+ <path fill="#ffcc07" d="m302.652 263.487c3.48 5.086 0.229 12.282 2.457 15.939-6.386-5.777-9.311-8.332-18.076 0.232 2.111-3.1 2.819-5.771 4.369-9.15 1.158-2.475 4.021-8.762 4.795-8.791 0.655-0.019 4.399-1.254 6.455 1.77z"/>
+ <path fill="#ffcd0a" d="m302.614 263.524c3.393 4.96 0.323 12.123 2.396 15.549-6.245-5.617-9.102-8.164-17.66 0.188 1.955-2.887 2.716-5.611 4.251-8.93 1.176-2.481 3.91-8.494 4.716-8.533 0.67-0.027 4.291-1.219 6.297 1.726z"/>
+ <path fill="#ffcd0c" d="m302.575 263.562c3.306 4.835 0.419 11.964 2.335 15.155-6.104-5.457-8.891-7.996-17.244 0.143 1.8-2.673 2.613-5.449 4.133-8.707 1.194-2.488 3.8-8.225 4.638-8.273 0.684-0.036 4.182-1.189 6.138 1.682z"/>
+ <path fill="#ffcd0f" d="m302.536 263.599c3.219 4.71 0.517 11.805 2.275 14.765-5.963-5.299-8.683-7.83-16.828 0.098 1.644-2.461 2.51-5.289 4.015-8.486 1.212-2.496 3.688-7.956 4.559-8.016 0.698-0.04 4.075-1.155 5.979 1.639z"/>
+ <path fill="#ffcd11" d="m302.497 263.637c3.131 4.585 0.612 11.645 2.216 14.371-5.822-5.137-8.474-7.661-16.413 0.053 1.489-2.245 2.406-5.125 3.896-8.264 1.229-2.504 3.576-7.688 4.479-7.756 0.714-0.046 3.968-1.123 5.822 1.596z"/>
+ <path fill="#ffce14" d="m302.458 263.674c3.044 4.459 0.708 11.486 2.154 13.979-5.681-4.978-8.263-7.493-15.996 0.009 1.334-2.033 2.303-4.965 3.779-8.043 1.247-2.511 3.464-7.418 4.4-7.498 0.728-0.052 3.859-1.089 5.663 1.553z"/>
+ <path fill="#ffce16" d="m302.42 263.711c2.956 4.336 0.804 11.328 2.094 13.588-5.54-4.817-8.055-7.326-15.58-0.036 1.178-1.819 2.199-4.804 3.659-7.822 1.267-2.517 3.354-7.149 4.323-7.237 0.741-0.061 3.75-1.058 5.504 1.507z"/>
+ <path fill="#ffce19" d="m302.381 263.749c2.868 4.211 0.9 11.168 2.033 13.196-5.398-4.657-7.845-7.159-15.164-0.081 1.022-1.605 2.097-4.642 3.542-7.601 1.283-2.524 3.241-6.88 4.244-6.979 0.755-0.067 3.642-1.026 5.345 1.465z"/>
+ <path fill="#ffce1c" d="m302.342 263.788c2.78 4.084 0.997 11.008 1.973 12.803-5.258-4.498-7.635-6.991-14.748-0.127 0.867-1.391 1.994-4.479 3.424-7.379 1.302-2.531 3.13-6.61 4.166-6.719 0.768-0.074 3.532-0.992 5.185 1.422z"/>
+ <path fill="#ffcf1e" d="m302.302 263.825c2.693 3.959 1.093 10.85 1.913 12.411-5.117-4.338-7.427-6.825-14.333-0.172 0.713-1.177 1.891-4.317 3.307-7.157 1.318-2.537 3.018-6.342 4.086-6.461 0.784-0.08 3.426-0.959 5.027 1.379z"/>
+ <path fill="#ffcf21" d="m302.263 263.862c2.606 3.834 1.188 10.689 1.853 12.02-4.976-4.178-7.217-6.657-13.916-0.217 0.556-0.963 1.786-4.156 3.188-6.936 1.337-2.545 2.906-6.072 4.008-6.202 0.797-0.086 3.318-0.927 4.867 1.335z"/>
+ <path fill="#ffcf23" d="m302.225 263.899c2.519 3.71 1.285 10.531 1.791 11.628-4.835-4.019-7.008-6.489-13.5-0.262 0.4-0.75 1.684-3.994 3.068-6.714 1.356-2.553 2.797-5.805 3.931-5.943 0.813-0.093 3.209-0.895 4.71 1.291z"/>
+ <path fill="#ffcf26" d="m302.186 263.937c2.431 3.584 1.381 10.371 1.73 11.235-4.693-3.857-6.798-6.322-13.084-0.307 0.245-0.535 1.58-3.832 2.951-6.492 1.373-2.56 2.686-5.535 3.852-5.685 0.828-0.1 3.101-0.861 4.551 1.249z"/>
+ <path fill="#ffd028" d="m302.147 263.974c2.344 3.46 1.477 10.213 1.671 10.845-4.553-3.699-6.589-6.156-12.668-0.354 0.089-0.321 1.477-3.67 2.832-6.271 1.392-2.565 2.574-5.267 3.772-5.425 0.842-0.104 2.994-0.828 4.393 1.205z"/>
+ <path fill="#ffd02b" d="m302.108 264.012c2.257 3.334 1.573 10.053 1.61 10.451-4.412-3.537-6.38-5.987-12.253-0.396-0.064-0.109 1.374-3.51 2.716-6.05 1.408-2.573 2.462-4.997 3.693-5.166 0.856-0.112 2.886-0.796 4.234 1.161z"/>
+ <path fill="#ffd02d" d="m302.069 264.049c2.17 3.209 1.67 9.894 1.55 10.061-4.271-3.379-6.17-5.82-11.836-0.441-0.221 0.104 1.271-3.35 2.596-5.83 1.428-2.58 2.352-4.728 3.615-4.906 0.87-0.12 2.777-0.765 4.075 1.116z"/>
+ <path fill="#ffd030" d="m302.03 264.086c2.082 3.084 1.767 9.736 1.49 9.668-4.131-3.219-5.961-5.652-11.42-0.486-0.377 0.318 1.167-3.188 2.478-5.607 1.445-2.586 2.239-4.459 3.536-4.647 0.884-0.127 2.669-0.732 3.916 1.072z"/>
+ <path fill="#ffd133" d="m301.991 264.124c1.995 2.959 1.862 9.576 1.43 9.277-3.989-3.059-5.752-5.486-11.005-0.531-0.532 0.531 1.064-3.027 2.36-5.387 1.463-2.594 2.128-4.189 3.458-4.389 0.899-0.133 2.561-0.699 3.757 1.03z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fc0" d="m305.862 283.481c5.977 7.848 17.064 16.271 21.024 18.576 2.88 1.656 7.056 3.6 6.983 8.783-0.144 5.904-3.168 7.561-4.823 9.217-3.313 3.313-22.177 10.943-34.2 16.271-12.24 5.4-21.097 8.209-27.217 9.217-4.104 0.647-7.056 2.375-13.176 1.151-4.32-0.864-6.912-1.296-9.864-3.888-2.951-2.52-5.976-5.184-6.407-9.359-1.225-10.369 3.672-16.921 8.424-25.921 3.888-7.2 11.735-8.64 16.632-7.991 17.568 2.375 16.416-8.641 21.24-13.465 4.464-4.463 17.208-8.064 21.384-2.591z"/>
+ <path fill="#ffcc02" d="m305.81 283.553c5.962 7.83 17.024 16.234 20.975 18.533 2.873 1.652 7.039 3.592 6.969 8.764-0.145 5.891-3.161 7.542-4.813 9.195-3.304 3.304-22.34 10.992-34.24 16.088-12.259 5.176-20.647 7.873-26.802 8.959-4.077 0.684-7.156 2.394-13.258 1.177-4.304-0.854-6.767-1.231-9.707-3.812-2.939-2.51-5.756-4.961-6.185-9.117-1.211-10.34 3.365-16.657 8.044-25.65 3.89-7.375 11.791-8.434 16.665-7.777 17.514 2.414 16.206-8.959 21.02-13.772 4.452-4.454 17.166-8.047 21.332-2.588z"/>
+ <path fill="#ffcc05" d="m305.76 283.627c5.946 7.812 16.982 16.195 20.925 18.488 2.866 1.648 7.022 3.584 6.951 8.743-0.144 5.876-3.153 7.524-4.801 9.173-3.298 3.297-22.506 11.043-34.28 15.907-12.279 4.949-20.201 7.538-26.389 8.699-4.051 0.721-7.256 2.413-13.341 1.202-4.286-0.846-6.619-1.168-9.55-3.733-2.924-2.501-5.536-4.741-5.959-8.877-1.198-10.312 3.058-16.394 7.664-25.379 3.89-7.552 11.845-8.229 16.698-7.563 17.458 2.453 15.995-9.279 20.797-14.08 4.443-4.443 17.127-8.026 21.285-2.58z"/>
+ <path fill="#ffcc07" d="m305.707 283.702c5.935 7.791 16.943 16.156 20.876 18.444 2.859 1.644 7.007 3.574 6.935 8.722-0.144 5.862-3.146 7.508-4.79 9.151-3.288 3.289-22.668 11.093-34.319 15.726-12.298 4.723-19.753 7.202-25.974 8.44-4.024 0.756-7.357 2.431-13.423 1.226-4.27-0.836-6.473-1.101-9.394-3.654-2.911-2.492-5.317-4.52-5.735-8.635-1.185-10.285 2.75-16.133 7.284-25.109 3.892-7.727 11.9-8.023 16.731-7.35 17.402 2.494 15.785-9.599 20.575-14.389 4.433-4.432 17.087-8.007 21.234-2.572z"/>
+ <path fill="#ffcd0a" d="m305.655 283.774c5.92 7.773 16.904 16.119 20.826 18.4 2.854 1.642 6.99 3.566 6.919 8.703-0.143 5.848-3.138 7.488-4.779 9.129-3.28 3.281-22.832 11.143-34.358 15.543-12.317 4.498-19.307 6.867-25.561 8.182-3.997 0.793-7.457 2.45-13.506 1.251-4.252-0.828-6.325-1.036-9.236-3.577-2.896-2.482-5.096-4.298-5.51-8.393-1.172-10.258 2.443-15.869 6.904-24.84 3.892-7.901 11.955-7.818 16.763-7.135 17.349 2.532 15.576-9.918 20.355-14.697 4.422-4.422 17.046-7.987 21.183-2.566z"/>
+ <path fill="#ffcd0c" d="m305.603 283.847c5.906 7.756 16.864 16.081 20.777 18.358 2.846 1.635 6.973 3.557 6.901 8.68-0.142 5.835-3.131 7.472-4.767 9.107-3.273 3.273-22.997 11.193-34.399 15.361-12.337 4.273-18.858 6.533-25.146 7.924-3.971 0.829-7.557 2.469-13.588 1.276-4.234-0.82-6.179-0.972-9.078-3.5-2.884-2.474-4.878-4.076-5.287-8.152-1.158-10.229 2.137-15.606 6.523-24.569 3.895-8.076 12.01-7.611 16.797-6.92 17.293 2.571 15.366-10.236 20.134-15.004 4.412-4.411 17.006-7.969 21.133-2.561z"/>
+ <path fill="#ffcd0f" d="m305.552 283.92c5.892 7.736 16.824 16.043 20.728 18.313 2.839 1.634 6.957 3.55 6.886 8.66-0.142 5.821-3.124 7.454-4.756 9.086-3.266 3.267-23.161 11.243-34.438 15.179-12.356 4.047-18.411 6.198-24.733 7.666-3.943 0.865-7.656 2.486-13.67 1.301-4.218-0.812-6.032-0.908-8.922-3.422-2.869-2.465-4.656-3.855-5.063-7.91-1.145-10.203 1.83-15.344 6.145-24.299 3.895-8.252 12.064-7.408 16.83-6.707 17.237 2.61 15.154-10.557 19.912-15.313 4.399-4.399 16.963-7.949 21.081-2.554z"/>
+ <path fill="#ffcd11" d="m305.501 283.993c5.877 7.719 16.782 16.004 20.678 18.271 2.833 1.628 6.939 3.54 6.869 8.639-0.143 5.807-3.116 7.436-4.745 9.064-3.257 3.258-23.324 11.293-34.479 14.996-12.375 3.822-17.963 5.863-24.319 7.408-3.917 0.9-7.757 2.504-13.752 1.324-4.2-0.802-5.886-0.842-8.765-3.344-2.856-2.454-4.438-3.633-4.838-7.669-1.132-10.173 1.521-15.081 5.764-24.029 3.896-8.426 12.119-7.2 16.863-6.491 17.183 2.649 14.945-10.875 19.689-15.621 4.391-4.389 16.926-7.93 21.035-2.548z"/>
+ <path fill="#ffce14" d="m305.448 284.066c5.863 7.701 16.743 15.966 20.629 18.228 2.826 1.625 6.924 3.531 6.853 8.619-0.142 5.793-3.108 7.418-4.733 9.043-3.25 3.25-23.489 11.342-34.518 14.813-12.396 3.598-17.517 5.529-23.905 7.148-3.891 0.938-7.857 2.524-13.834 1.351-4.185-0.793-5.74-0.776-8.609-3.267-2.841-2.444-4.217-3.412-4.613-7.426-1.118-10.146 1.216-14.818 5.385-23.76 3.896-8.602 12.174-6.996 16.896-6.277 17.128 2.688 14.735-11.195 19.468-15.929 4.378-4.38 16.883-7.911 20.981-2.543z"/>
+ <path fill="#ffce16" d="m305.396 284.139c5.85 7.682 16.703 15.928 20.579 18.184 2.82 1.62 6.907 3.523 6.837 8.598-0.141 5.779-3.101 7.4-4.722 9.021-3.242 3.242-23.653 11.393-34.559 14.631-12.414 3.372-17.068 5.194-23.491 6.891-3.862 0.975-7.957 2.543-13.917 1.375-4.167-0.783-5.592-0.713-8.451-3.188-2.827-2.437-3.997-3.19-4.389-7.187-1.105-10.117 0.908-14.555 5.004-23.487 3.898-8.776 12.229-6.79 16.928-6.063 17.074 2.728 14.525-11.515 19.248-16.236 4.37-4.371 16.845-7.894 20.933-2.539z"/>
+ <path fill="#ffce19" d="m305.344 284.211c5.836 7.664 16.663 15.891 20.529 18.141 2.813 1.617 6.892 3.516 6.82 8.578-0.14 5.765-3.093 7.382-4.71 8.999-3.235 3.233-23.817 11.442-34.598 14.448-12.434 3.146-16.621 4.859-23.077 6.633-3.837 1.01-8.058 2.561-13.999 1.4-4.15-0.775-5.446-0.648-8.295-3.111-2.814-2.426-3.777-2.969-4.164-6.944-1.094-10.09 0.601-14.293 4.624-23.22 3.898-8.951 12.282-6.584 16.961-5.848 17.019 2.767 14.314-11.834 19.025-16.545 4.361-4.359 16.806-7.872 20.884-2.531z"/>
+ <path fill="#ffce1c" d="m305.292 284.286c5.822 7.646 16.623 15.852 20.481 18.096 2.806 1.613 6.874 3.507 6.804 8.558-0.141 5.751-3.086 7.364-4.699 8.978-3.227 3.227-23.981 11.492-34.638 14.267-12.453 2.921-16.173 4.524-22.663 6.374-3.81 1.046-8.158 2.578-14.082 1.424-4.133-0.766-5.299-0.583-8.137-3.033-2.801-2.416-3.558-2.748-3.94-6.703-1.08-10.062 0.293-14.029 4.244-22.947 3.9-9.127 12.338-6.379 16.994-5.635 16.964 2.805 14.105-12.152 18.805-16.853 4.348-4.351 16.763-7.856 20.831-2.526z"/>
+ <path fill="#ffcf1e" d="m305.241 284.358c5.808 7.627 16.582 15.814 20.432 18.053 2.799 1.609 6.856 3.498 6.787 8.536-0.141 5.738-3.079 7.347-4.688 8.957-3.219 3.218-24.145 11.541-34.677 14.084-12.473 2.695-15.727 4.188-22.25 6.115-3.783 1.083-8.258 2.599-14.163 1.448-4.116-0.756-5.153-0.518-7.981-2.954-2.786-2.408-3.337-2.526-3.716-6.462-1.066-10.034-0.013-13.766 3.864-22.678 3.901-9.303 12.393-6.172 17.027-5.42 16.908 2.844 13.896-12.473 18.583-17.16 4.338-4.337 16.723-7.835 20.782-2.519z"/>
+ <path fill="#ffcf21" d="m305.189 284.431c5.793 7.608 16.542 15.776 20.382 18.009 2.792 1.605 6.84 3.49 6.771 8.516-0.14 5.725-3.071 7.33-4.677 8.936-3.211 3.211-24.309 11.591-34.717 13.902-12.491 2.47-15.278 3.854-21.836 5.856-3.756 1.119-8.357 2.616-14.246 1.474-4.099-0.748-5.006-0.453-7.823-2.877-2.772-2.398-3.118-2.306-3.492-6.22-1.053-10.007-0.319-13.505 3.484-22.407 3.903-9.479 12.448-5.969 17.062-5.207 16.853 2.883 13.684-12.791 18.36-17.469 4.328-4.328 16.683-7.819 20.732-2.513z"/>
+ <path fill="#ffcf23" d="m305.137 284.504c5.778 7.59 16.503 15.736 20.332 17.965 2.786 1.602 6.825 3.482 6.755 8.496-0.139 5.709-3.064 7.311-4.665 8.912-3.204 3.203-24.474 11.642-34.759 13.721-12.51 2.244-14.829 3.52-21.421 5.598-3.729 1.155-8.457 2.635-14.327 1.499-4.082-0.739-4.86-0.389-7.667-2.8-2.76-2.389-2.897-2.083-3.268-5.979-1.04-9.979-0.627-13.24 3.104-22.138 3.903-9.653 12.503-5.762 17.093-4.991 16.799 2.922 13.475-13.111 18.141-17.777 4.318-4.316 16.643-7.799 20.682-2.506z"/>
+ <path fill="#ffcf26" d="m305.086 284.579c5.765 7.57 16.463 15.697 20.282 17.92 2.779 1.599 6.809 3.474 6.738 8.476-0.139 5.696-3.056 7.293-4.654 8.892-3.194 3.194-24.637 11.69-34.797 13.536-12.529 2.021-14.382 3.185-21.007 5.341-3.703 1.191-8.559 2.652-14.411 1.523-4.065-0.73-4.713-0.324-7.509-2.723-2.745-2.379-2.679-1.861-3.043-5.735-1.027-9.952-0.936-12.979 2.724-21.868 3.905-9.828 12.557-5.557 17.126-4.777 16.744 2.961 13.265-13.431 17.919-18.084 4.307-4.309 16.602-7.783 20.632-2.501z"/>
+ <path fill="#ffd028" d="m305.033 284.651c5.752 7.553 16.423 15.66 20.234 17.878 2.771 1.593 6.791 3.464 6.722 8.454-0.139 5.682-3.049 7.275-4.643 8.869-3.188 3.188-24.801 11.74-34.838 13.355-12.548 1.793-13.935 2.85-20.593 5.082-3.676 1.228-8.658 2.67-14.493 1.547-4.048-0.721-4.565-0.258-7.353-2.644-2.731-2.37-2.457-1.64-2.818-5.495-1.014-9.923-1.242-12.716 2.345-21.597 3.905-10.004 12.611-5.351 17.158-4.563 16.689 3 13.055-13.75 17.698-18.393 4.297-4.295 16.562-7.761 20.581-2.493z"/>
+ <path fill="#ffd02b" d="m304.982 284.724c5.737 7.534 16.382 15.622 20.184 17.834 2.766 1.59 6.774 3.456 6.705 8.433-0.138 5.67-3.041 7.26-4.631 8.85-3.18 3.179-24.966 11.789-34.877 13.172-12.568 1.568-13.487 2.515-20.179 4.824-3.65 1.263-8.759 2.688-14.575 1.572-4.031-0.713-4.42-0.195-7.196-2.566-2.718-2.361-2.238-1.42-2.594-5.254-1.001-9.896-1.549-12.453 1.964-21.328 3.907-10.178 12.666-5.145 17.192-4.348 16.634 3.039 12.844-14.068 17.476-18.701 4.285-4.286 16.521-7.743 20.531-2.488z"/>
+ <path fill="#ffd02d" d="m304.93 284.797c5.723 7.516 16.342 15.584 20.135 17.789 2.758 1.588 6.758 3.449 6.688 8.414-0.138 5.654-3.034 7.24-4.619 8.826-3.173 3.172-25.13 11.84-34.918 12.99-12.587 1.344-13.039 2.18-19.766 4.564-3.622 1.301-8.856 2.709-14.657 1.599-4.014-0.704-4.272-0.13-7.039-2.489-2.702-2.352-2.018-1.197-2.369-5.012-0.987-9.868-1.855-12.189 1.584-21.057 3.908-10.354 12.722-4.94 17.226-4.135 16.578 3.078 12.634-14.389 17.254-19.009 4.275-4.273 16.481-7.721 20.481-2.48z"/>
+ <path fill="#ffd030" d="m304.879 284.87c5.709 7.498 16.302 15.547 20.085 17.748 2.752 1.582 6.741 3.438 6.673 8.391-0.139 5.642-3.027 7.224-4.609 8.806-3.164 3.164-25.293 11.89-34.956 12.808-12.606 1.119-12.592 1.844-19.352 4.308-3.596 1.336-8.958 2.726-14.739 1.622-3.997-0.695-4.127-0.065-6.882-2.411-2.69-2.343-1.799-0.976-2.146-4.771-0.974-9.84-2.163-11.928 1.204-20.787 3.91-10.529 12.777-4.734 17.258-3.92 16.524 3.117 12.424-14.707 17.034-19.316 4.263-4.267 16.439-7.706 20.43-2.478z"/>
+ <path fill="#ffd133" d="m304.826 284.943c5.695 7.479 16.263 15.509 20.036 17.703 2.745 1.579 6.726 3.431 6.656 8.372-0.137 5.627-3.02 7.205-4.597 8.783-3.157 3.156-25.458 11.939-34.997 12.625-12.626 0.893-12.145 1.51-18.938 4.049-3.569 1.373-9.058 2.745-14.822 1.646-3.979-0.686-3.979 0-6.725-2.332-2.676-2.334-1.578-0.756-1.921-4.529-0.961-9.813-2.471-11.665 0.824-20.516 3.91-10.705 12.83-4.529 17.29-3.707 16.47 3.156 12.215-15.027 16.813-19.625 4.255-4.253 16.401-7.684 20.381-2.469z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#995900" d="m52.494 273.618c-6.479 4.68-22.896 4.248-27.072 9.719-4.104 5.473 0.145 13.393 0.072 28.08 0 6.265-1.08 11.017-1.8 14.832-1.008 4.824-1.656 8.209 0.36 11.664 3.672 6.121 9.575 7.633 43.344 14.688 18.072 3.744 35.136 13.464 46.584 14.399 11.448 0.865 13.896-2.951 20.88-9.144 6.912-6.192 9.144-4.248 8.928-17.856-0.216-13.535-8.928-17.567-18.792-33.191s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.208 13.248-14.688 17.929z"/>
+ <path fill="#9e5e00" d="m52.598 273.905c-6.397 4.702-22.475 3.788-27.062 9.512-4.154 5.414 0.228 13.276 0.098 27.955-0.025 6.23-1.152 10.881-1.937 14.877-1.037 4.871-1.678 8.201 0.349 11.619 3.787 6.162 9.695 7.123 43.456 14.168 18.061 3.737 34.541 13.307 46.343 14.112 11.186 0.792 13.564-2.829 20.463-8.96 6.896-6.195 9.024-4.277 8.858-17.406-0.075-13.521-8.305-17.349-18.169-32.973s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.153 13.479-14.583 18.216z"/>
+ <path fill="#a36400" d="m52.703 274.193c-6.314 4.724-22.054 3.327-27.051 9.304-4.204 5.356 0.31 13.16 0.123 27.828-0.051 6.198-1.225 10.748-2.074 14.924-1.065 4.918-1.699 8.194 0.339 11.571 3.902 6.206 9.813 6.617 43.567 13.651 18.05 3.73 33.948 13.146 46.101 13.824 10.923 0.72 13.234-2.707 20.045-8.777 6.885-6.199 8.907-4.305 8.792-16.956 0.064-13.507-7.683-17.129-17.547-32.753s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.1 13.709-14.479 18.504z"/>
+ <path fill="#a86a00" d="m52.807 274.481c-6.231 4.745-21.633 2.866-27.04 9.094-4.255 5.299 0.393 13.047 0.148 27.702-0.076 6.167-1.297 10.616-2.211 14.972-1.095 4.965-1.721 8.188 0.328 11.524 4.018 6.25 9.932 6.108 43.679 13.134 18.039 3.721 33.354 12.988 45.86 13.535 10.659 0.648 12.902-2.585 19.627-8.593 6.869-6.203 8.788-4.335 8.723-16.507 0.205-13.492-7.06-16.909-16.924-32.533s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-8.045 13.94-14.374 18.792z"/>
+ <path fill="#ad7000" d="m52.912 274.769c-6.149 4.767-21.211 2.405-27.029 8.885-4.306 5.242 0.476 12.931 0.173 27.576-0.101 6.136-1.368 10.483-2.347 15.019-1.123 5.012-1.742 8.181 0.316 11.478 4.133 6.293 10.052 5.603 43.791 12.614 18.028 3.716 32.76 12.83 45.619 13.248 10.396 0.576 12.57-2.463 19.21-8.409 6.854-6.206 8.668-4.363 8.653-16.056 0.347-13.479-6.437-16.69-16.301-32.314s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.991 14.169-14.269 19.079z"/>
+ <path fill="#b27500" d="m53.016 275.057c-6.066 4.787-20.79 1.943-27.019 8.676-4.355 5.184 0.559 12.816 0.198 27.45-0.126 6.103-1.44 10.351-2.484 15.065-1.151 5.059-1.764 8.172 0.307 11.431 4.248 6.336 10.17 5.094 43.901 12.096 18.019 3.708 32.166 12.672 45.378 12.96 10.135 0.504 12.24-2.34 18.792-8.227 6.841-6.209 8.551-4.391 8.586-15.605 0.486-13.464-5.813-16.47-15.678-32.094s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.937 14.399-14.165 19.368z"/>
+ <path fill="#b77b00" d="m53.121 275.344c-5.983 4.811-20.369 1.484-27.008 8.469-4.406 5.126 0.641 12.7 0.224 27.324-0.151 6.068-1.512 10.216-2.621 15.111-1.181 5.105-1.785 8.166 0.295 11.385 4.363 6.379 10.289 4.586 44.014 11.576 18.008 3.701 31.572 12.515 45.137 12.672 9.872 0.433 11.909-2.217 18.375-8.041 6.825-6.215 8.431-4.422 8.518-15.156 0.627-13.45-5.191-16.251-15.056-31.875s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.884 14.631-14.062 19.655z"/>
+ <path fill="#bc8100" d="m53.225 275.633c-5.9 4.832-19.948 1.023-26.997 8.259-4.457 5.069 0.724 12.585 0.249 27.198-0.177 6.037-1.584 10.082-2.758 15.158-1.21 5.152-1.808 8.158 0.284 11.338 4.479 6.422 10.407 4.078 44.125 11.059 17.997 3.693 30.979 12.355 44.896 12.384 9.608 0.36 11.578-2.095 17.957-7.858 6.812-6.217 8.313-4.449 8.45-14.707 0.766-13.435-4.569-16.03-14.434-31.654s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.829 14.859-13.956 19.943z"/>
+ <path fill="#c18700" d="m53.329 275.92c-5.817 4.854-19.526 0.563-26.985 8.051-4.507 5.011 0.807 12.47 0.273 27.072-0.201 6.004-1.655 9.949-2.894 15.205-1.239 5.199-1.829 8.151 0.273 11.291 4.594 6.465 10.526 3.57 44.236 10.541 17.985 3.686 30.384 12.196 44.655 12.096 9.345 0.287 11.245-1.973 17.539-7.676 6.797-6.221 8.193-4.479 8.381-14.256 0.906-13.42-3.946-15.812-13.811-31.436s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.774 15.094-13.851 20.232z"/>
+ <path fill="#c68c00" d="m53.433 276.209c-5.734 4.875-19.104 0.101-26.975 7.84-4.558 4.955 0.89 12.355 0.299 26.947-0.227 5.973-1.728 9.816-3.031 15.252-1.267 5.246-1.851 8.145 0.263 11.244 4.709 6.508 10.646 3.063 44.349 10.022 17.975 3.679 29.79 12.038 44.413 11.808 9.083 0.217 10.915-1.851 17.122-7.492 6.782-6.224 8.074-4.506 8.313-13.806 1.048-13.405-3.323-15.592-13.188-31.216s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.722 15.322-13.749 20.521z"/>
+ <path fill="#cc9200" d="m53.538 276.497c-5.651 4.896-18.684-0.359-26.964 7.633-4.607 4.896 0.972 12.24 0.324 26.82-0.252 5.939-1.8 9.684-3.168 15.299-1.296 5.293-1.872 8.137 0.252 11.196 4.824 6.552 10.764 2.556 44.46 9.505 17.964 3.672 29.196 11.879 44.172 11.52 8.82 0.144 10.584-1.729 16.704-7.309 6.768-6.228 7.956-4.535 8.244-13.355 1.188-13.393-2.7-15.372-12.564-30.996s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.668 15.551-13.644 20.807z"/>
+ <path fill="#d19800" d="m53.642 276.786c-5.569 4.918-18.263-0.82-26.953 7.424-4.658 4.838 1.055 12.123 0.35 26.693-0.277 5.907-1.872 9.551-3.305 15.346-1.325 5.34-1.894 8.129 0.241 11.15 4.938 6.596 10.883 2.048 44.571 8.984 17.953 3.666 28.602 11.723 43.931 11.232 8.558 0.072 10.253-1.605 16.287-7.123 6.753-6.232 7.837-4.566 8.175-12.906 1.329-13.379-2.077-15.153-11.941-30.777s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.614 15.783-13.54 21.097z"/>
+ <path fill="#d69e00" d="m53.747 277.073c-5.486 4.94-17.842-1.281-26.942 7.215-4.709 4.781 1.138 12.01 0.374 26.568-0.302 5.875-1.943 9.417-3.441 15.393-1.354 5.387-1.915 8.123 0.23 11.104 5.055 6.639 11.002 1.541 44.684 8.467 17.942 3.658 28.008 11.563 43.688 10.944 8.296 0 9.923-1.483 15.869-6.941 6.74-6.235 7.72-4.593 8.108-12.456 1.468-13.363-1.455-14.933-11.319-30.557s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.56 16.012-13.435 21.383z"/>
+ <path fill="#dba300" d="m53.851 277.361c-5.403 4.962-17.421-1.741-26.932 7.007-4.759 4.723 1.221 11.893 0.399 26.441-0.327 5.843-2.016 9.283-3.578 15.439-1.383 5.434-1.937 8.115 0.22 11.057 5.169 6.682 11.12 1.033 44.795 7.949 17.932 3.649 27.414 11.404 43.448 10.656 8.031-0.072 9.59-1.361 15.451-6.758 6.725-6.238 7.6-4.623 8.039-12.006 1.609-13.35-0.832-14.714-10.696-30.338s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.504 16.245-13.33 21.673z"/>
+ <path fill="#e0a900" d="m53.956 277.649c-5.321 4.982-16.999-2.203-26.921 6.797-4.81 4.666 1.303 11.779 0.425 26.316-0.353 5.811-2.088 9.15-3.715 15.486-1.411 5.48-1.959 8.108 0.208 11.01 5.285 6.725 11.239 0.525 44.907 7.431 17.92 3.644 26.819 11.246 43.207 10.368 7.769-0.145 9.259-1.239 15.034-6.574 6.71-6.242 7.479-4.65 7.97-11.557 1.75-13.334-0.209-14.493-10.073-30.117s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.452 16.474-13.226 21.96z"/>
+ <path fill="#e5af00" d="m54.06 277.937c-5.238 5.004-16.578-2.664-26.91 6.588-4.86 4.608 1.386 11.664 0.45 26.19-0.378 5.777-2.16 9.018-3.853 15.533-1.439 5.526-1.979 8.101 0.198 10.963 5.4 6.768 11.358 0.018 45.018 6.912 17.91 3.635 26.227 11.088 42.967 10.08 7.506-0.217 8.928-1.117 14.615-6.391 6.696-6.246 7.362-4.68 7.902-11.105 1.89-13.32 0.414-14.274-9.45-29.898s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.397 16.704-13.121 22.248z"/>
+ <path fill="#eab500" d="m54.165 278.225c-5.155 5.025-16.157-3.124-26.899 6.38-4.91 4.55 1.469 11.548 0.476 26.063-0.403 5.746-2.232 8.885-3.989 15.58-1.469 5.573-2.002 8.094 0.188 10.916 5.515 6.812 11.477-0.49 45.129 6.394 17.899 3.629 25.633 10.93 42.725 9.792 7.243-0.288 8.598-0.993 14.199-6.206 6.681-6.25 7.243-4.709 7.833-10.656 2.031-13.306 1.037-14.055-8.827-29.679s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.346 16.935-13.019 22.536z"/>
+ <path fill="#efba00" d="m54.269 278.513c-5.073 5.048-15.736-3.585-26.889 6.171-4.961 4.492 1.552 11.434 0.5 25.938-0.428 5.713-2.304 8.752-4.125 15.627-1.498 5.621-2.023 8.086 0.176 10.869 5.631 6.854 11.596-0.996 45.241 5.875 17.889 3.623 25.038 10.771 42.483 9.504 6.981-0.359 8.266-0.871 13.781-6.022 6.668-6.253 7.125-4.737 7.766-10.206 2.17-13.291 1.659-13.835-8.205-29.459s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.289 17.164-12.912 22.823z"/>
+ <path fill="#f4c000" d="m54.374 278.801c-4.99 5.068-15.314-4.047-26.878 5.962-5.012 4.435 1.634 11.317 0.525 25.812-0.453 5.682-2.376 8.618-4.263 15.674-1.526 5.668-2.045 8.08 0.166 10.822 5.745 6.898 11.714-1.505 45.353 5.357 17.878 3.613 24.444 10.613 42.243 9.216 6.717-0.433 7.934-0.749 13.362-5.839 6.653-6.258 7.007-4.768 7.697-9.756 2.312-13.277 2.282-13.616-7.582-29.24s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.235 17.395-12.807 23.112z"/>
+ <path fill="#f9c600" d="m54.477 279.088c-4.906 5.092-14.893-4.506-26.866 5.754-5.062 4.377 1.717 11.203 0.551 25.686-0.479 5.648-2.448 8.485-4.399 15.721-1.555 5.715-2.066 8.072 0.155 10.775 5.86 6.941 11.833-2.012 45.464 4.839 17.867 3.607 23.851 10.454 42.001 8.929 6.455-0.504 7.604-0.627 12.946-5.656 6.638-6.26 6.886-4.795 7.628-9.307 2.452-13.262 2.905-13.396-6.959-29.02s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.182 17.626-12.705 23.399z"/>
+ <path fill="#fc0" d="m54.582 279.377c-4.823 5.111-14.472-4.969-26.855 5.543-5.112 4.32 1.8 11.088 0.576 25.561-0.504 5.616-2.521 8.352-4.536 15.768-1.584 5.76-2.088 8.064 0.144 10.729 5.977 6.984 11.952-2.52 45.576 4.32 17.856 3.6 23.256 10.295 41.76 8.64 6.192-0.576 7.272-0.504 12.528-5.472 6.624-6.264 6.768-4.824 7.56-8.856 2.592-13.248 3.528-13.176-6.336-28.8s-11.448-18.504-18-28.872c-6.552-10.224-19.512-28.8-26.928-29.017-5.904-0.144-9.216 3.024-12.888 6.769s-7.129 17.855-12.601 23.687z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fc0" d="m57.701 285.002c-4.278 4.539-18.28-1.36-24.892 3.631-4.732 3.5 2.398 7.908 1.426 20.873-0.389 4.926-3.824 5.834-2.398 12.64 1.103 5.121 2.27 4.991 4.214 7.325 5.315 6.223 4.084 1.686 34.355 7.777 16.011 3.242 20.938 9.271 37.596 7.779 5.575-0.518 6.612-0.453 11.279-4.926 5.964-5.575 2.917-4.408 3.565-7.973 2.269-11.863 0.453-13.938-8.428-28.004-8.88-14.066-8.102-14.844-13.936-24.113-5.834-9.141-13.872-25.799-20.549-25.93-5.25-0.129-8.297 2.723-11.603 6.094-3.305 3.372-5.768 19.643-10.629 24.827z"/>
+ <path fill="#ffcc02" d="m57.995 285.094c-4.461 4.701-18.604-1.196-25.06 3.705-4.701 3.514 2.578 8.05 1.608 20.68-0.4 4.896-3.733 5.877-2.458 12.634 0.986 5.093 2.357 4.938 4.334 7.201 5.686 6.131 4.673 1.826 34.119 7.743 15.918 3.211 20.815 9.215 37.372 7.732 5.541-0.513 6.479-0.463 11.155-4.849 5.865-5.407 2.858-4.287 3.412-8.058 2.066-11.787 0.442-13.981-8.188-27.649-8.83-13.983-8.143-14.698-13.941-23.913-5.8-9.085-13.701-25.805-20.338-25.934-5.219-0.129-8.248 2.705-11.533 6.057-3.287 3.352-5.644 19.505-10.482 24.651z"/>
+ <path fill="#ffcc05" d="m58.289 285.185c-4.644 4.866-18.93-1.031-25.229 3.78-4.669 3.527 2.759 8.191 1.792 20.488-0.413 4.866-3.642 5.918-2.519 12.625 0.872 5.066 2.447 4.887 4.455 7.078 6.057 6.04 5.263 1.969 33.883 7.709 15.825 3.18 20.693 9.159 37.148 7.686 5.508-0.506 6.345-0.471 11.03-4.77 5.768-5.24 2.803-4.168 3.26-8.142 1.865-11.716 0.432-14.027-7.949-27.298-8.78-13.899-8.183-14.553-13.948-23.713-5.764-9.03-13.529-25.811-20.126-25.938-5.188-0.129-8.198 2.688-11.465 6.021-3.266 3.331-5.517 19.368-10.332 24.474z"/>
+ <path fill="#ffcc07" d="m58.584 285.276c-4.827 5.03-19.255-0.865-25.397 3.855-4.639 3.541 2.938 8.332 1.975 20.295-0.425 4.838-3.551 5.961-2.578 12.619 0.757 5.039 2.536 4.834 4.575 6.955 6.428 5.949 5.852 2.108 33.646 7.674 15.733 3.147 20.571 9.103 36.925 7.639 5.475-0.501 6.211-0.48 10.905-4.693 5.67-5.072 2.745-4.045 3.107-8.224 1.663-11.642 0.42-14.073-7.711-26.946-8.73-13.814-8.223-14.406-13.952-23.511-5.729-8.976-13.358-25.817-19.916-25.944-5.156-0.127-8.148 2.674-11.396 5.984s-5.391 19.229-10.183 24.297z"/>
+ <path fill="#ffcd0a" d="m58.878 285.368c-5.01 5.193-19.579-0.701-25.565 3.93-4.607 3.555 3.117 8.475 2.157 20.102-0.437 4.809-3.459 6.004-2.639 12.613 0.643 5.011 2.626 4.781 4.695 6.83 6.799 5.857 6.442 2.25 33.411 7.64 15.641 3.118 20.45 9.048 36.701 7.593 5.44-0.494 6.076-0.488 10.781-4.615 5.57-4.904 2.688-3.926 2.954-8.308 1.462-11.569 0.409-14.118-7.472-26.593-8.68-13.732-8.263-14.262-13.958-23.311-5.695-8.922-13.188-25.824-19.705-25.951-5.125-0.127-8.1 2.658-11.326 5.949-3.227 3.289-5.266 19.091-10.034 24.121z"/>
+ <path fill="#ffcd0c" d="m59.173 285.458c-5.193 5.358-19.905-0.535-25.734 4.008-4.577 3.566 3.297 8.613 2.34 19.908-0.449 4.778-3.368 6.045-2.698 12.605 0.526 4.982 2.715 4.729 4.815 6.707 7.17 5.766 7.031 2.391 33.175 7.604 15.549 3.088 20.328 8.994 36.477 7.547 5.408-0.488 5.943-0.498 10.657-4.537 5.472-4.737 2.63-3.805 2.802-8.393 1.261-11.494 0.398-14.162-7.232-26.24-8.63-13.647-8.304-14.117-13.964-23.109-5.66-8.867-13.017-25.829-19.494-25.956-5.094-0.126-8.05 2.642-11.257 5.912-3.21 3.27-5.142 18.955-9.887 23.944z"/>
+ <path fill="#ffcd0f" d="m59.467 285.547c-5.376 5.523-20.229-0.369-25.903 4.084-4.545 3.58 3.478 8.756 2.523 19.715-0.461 4.75-3.277 6.088-2.758 12.599 0.411 4.955 2.804 4.677 4.936 6.584 7.541 5.675 7.621 2.532 32.938 7.569 15.456 3.056 20.206 8.938 36.253 7.5 5.375-0.482 5.811-0.506 10.533-4.459 5.374-4.57 2.572-3.686 2.649-8.477 1.058-11.42 0.387-14.209-6.995-25.888-8.58-13.563-8.344-13.972-13.969-22.909-5.626-8.813-12.846-25.834-19.283-25.961-5.063-0.125-8 2.625-11.188 5.877-3.188 3.251-5.015 18.818-9.736 23.766z"/>
+ <path fill="#ffcd11" d="m59.76 285.639c-5.559 5.688-20.555-0.205-26.071 4.158-4.515 3.594 3.657 8.896 2.706 19.521-0.473 4.721-3.186 6.131-2.818 12.594 0.297 4.926 2.894 4.623 5.057 6.459 7.911 5.584 8.21 2.674 32.703 7.535 15.362 3.025 20.084 8.883 36.027 7.453 5.342-0.477 5.677-0.515 10.409-4.381 5.275-4.402 2.516-3.564 2.497-8.561 0.855-11.348 0.375-14.254-6.756-25.535-8.53-13.479-8.385-13.825-13.976-22.709-5.59-8.758-12.673-25.842-19.071-25.965-5.031-0.125-7.951 2.608-11.119 5.838-3.168 3.232-4.888 18.684-9.588 23.593z"/>
+ <path fill="#ffce14" d="m60.055 285.73c-5.742 5.851-20.88-0.04-26.24 4.233-4.483 3.607 3.837 9.039 2.889 19.33-0.485 4.69-3.095 6.172-2.878 12.584 0.182 4.9 2.982 4.572 5.177 6.338 8.282 5.492 8.8 2.814 32.467 7.498 15.271 2.996 19.962 8.828 35.804 7.408 5.309-0.472 5.543-0.523 10.285-4.304 5.177-4.235 2.458-3.444 2.344-8.644 0.654-11.273 0.364-14.299-6.518-25.184-8.479-13.395-8.425-13.679-13.98-22.507-5.556-8.704-12.502-25.849-18.86-25.972-5-0.123-7.901 2.593-11.05 5.803s-4.765 18.547-9.44 23.417z"/>
+ <path fill="#ffce16" d="m60.349 285.821c-5.925 6.016-21.205 0.125-26.408 4.309-4.453 3.621 4.017 9.18 3.07 19.137-0.496 4.662-3.002 6.215-2.938 12.579 0.066 4.872 3.072 4.518 5.298 6.213 8.653 5.401 9.389 2.956 32.23 7.464 15.178 2.964 19.84 8.771 35.58 7.361 5.275-0.465 5.409-0.532 10.159-4.225 5.079-4.068 2.401-3.324 2.192-8.729 0.452-11.2 0.354-14.346-6.279-24.831-8.429-13.312-8.464-13.534-13.985-22.306-5.521-8.65-12.331-25.854-18.649-25.978-4.969-0.123-7.853 2.577-10.98 5.767-3.129 3.19-4.637 18.409-9.29 23.239z"/>
+ <path fill="#ffce19" d="m60.643 285.911c-6.107 6.18-21.529 0.291-26.577 4.385-4.421 3.635 4.197 9.322 3.254 18.945-0.508 4.631-2.911 6.256-2.997 12.571-0.049 4.845 3.161 4.465 5.418 6.089 9.023 5.309 9.979 3.098 31.994 7.43 15.085 2.934 19.718 8.717 35.355 7.314 5.242-0.459 5.276-0.541 10.036-4.148 4.98-3.899 2.344-3.203 2.039-8.811 0.25-11.127 0.342-14.391-6.04-24.479-8.38-13.228-8.505-13.389-13.991-22.105-5.486-8.596-12.16-25.859-18.438-25.982-4.938-0.123-7.803 2.561-10.911 5.73-3.109 3.17-4.513 18.272-9.142 23.061z"/>
+ <path fill="#ffce1c" d="m60.938 286.002c-6.291 6.344-21.855 0.455-26.746 4.459-4.391 3.648 4.377 9.463 3.437 18.752-0.521 4.603-2.82 6.299-3.058 12.564-0.163 4.817 3.251 4.413 5.539 5.965 9.395 5.219 10.567 3.24 31.758 7.396 14.993 2.903 19.597 8.661 35.132 7.269 5.209-0.453 5.143-0.55 9.912-4.07 4.882-3.732 2.286-3.082 1.887-8.895 0.048-11.053 0.329-14.436-5.802-24.126-8.33-13.144-8.545-13.243-13.997-21.905-5.451-8.541-11.988-25.865-18.228-25.988-4.906-0.121-7.753 2.545-10.843 5.695-3.088 3.149-4.385 18.132-8.991 22.884z"/>
+ <path fill="#ffcf1e" d="m61.232 286.092c-6.473 6.51-22.18 0.621-26.914 4.535-4.359 3.662 4.557 9.604 3.619 18.559-0.532 4.574-2.729 6.342-3.117 12.559-0.278 4.789 3.34 4.36 5.659 5.842 9.766 5.127 11.157 3.381 31.521 7.359 14.9 2.872 19.475 8.607 34.908 7.223 5.176-0.447 5.008-0.559 9.787-3.992 4.784-3.565 2.229-2.963 1.735-8.979-0.155-10.98 0.317-14.482-5.564-23.773-8.279-13.061-8.585-13.098-14.002-21.705-5.416-8.485-11.817-25.871-18.017-25.992-4.875-0.121-7.704 2.527-10.773 5.658-3.068 3.128-4.26 17.995-8.842 22.706z"/>
+ <path fill="#ffcf21" d="m61.526 286.184c-6.655 6.673-22.505 0.785-27.082 4.611-4.328 3.674 4.736 9.744 3.802 18.365-0.544 4.543-2.638 6.383-3.178 12.551-0.394 4.761 3.43 4.308 5.78 5.718 10.136 5.036 11.746 3.522 31.285 7.325 14.808 2.841 19.353 8.551 34.685 7.176 5.142-0.441 4.875-0.567 9.663-3.914 4.685-3.398 2.171-2.842 1.582-9.063-0.357-10.906 0.307-14.527-5.325-23.422-8.23-12.976-8.625-12.951-14.008-21.503-5.382-8.432-11.646-25.878-17.806-25.999-4.844-0.119-7.654 2.512-10.704 5.622-3.049 3.109-4.134 17.859-8.694 22.533z"/>
+ <path fill="#ffcf23" d="m61.821 286.275c-6.839 6.837-22.83 0.95-27.251 4.687-4.298 3.688 4.916 9.886 3.984 18.172-0.557 4.515-2.546 6.426-3.237 12.545-0.509 4.732 3.519 4.255 5.9 5.594 10.507 4.945 12.336 3.663 31.05 7.29 14.715 2.812 19.23 8.496 34.46 7.129 5.108-0.435 4.74-0.575 9.538-3.835 4.587-3.23 2.113-2.723 1.43-9.146-0.559-10.834 0.296-14.572-5.086-23.069-8.18-12.892-8.666-12.806-14.014-21.302-5.347-8.377-11.476-25.885-17.595-26.004-4.813-0.119-7.605 2.496-10.635 5.584-3.029 3.088-4.008 17.722-8.544 22.355z"/>
+ <path fill="#ffcf26" d="m62.115 286.366c-7.021 7.002-23.154 1.115-27.42 4.762-4.266 3.701 5.096 10.027 4.168 17.979-0.568 4.486-2.455 6.469-3.297 12.538-0.624 4.706 3.607 4.203 6.021 5.472 10.878 4.852 12.925 3.803 30.813 7.254 14.622 2.78 19.108 8.441 34.236 7.084 5.075-0.43 4.606-0.584 9.413-3.759 4.489-3.063 2.058-2.601 1.277-9.229-0.761-10.76 0.284-14.618-4.848-22.717-8.129-12.809-8.706-12.66-14.019-21.102-5.313-8.322-11.304-25.891-17.384-26.01-4.781-0.118-7.556 2.48-10.566 5.55-3.008 3.068-3.881 17.584-8.394 22.178z"/>
+ <path fill="#ffd028" d="m62.409 286.456c-7.204 7.166-23.479 1.281-27.588 4.838-4.235 3.715 5.275 10.168 4.351 17.787-0.58 4.455-2.364 6.51-3.357 12.53-0.738 4.679 3.697 4.149 6.142 5.347 11.249 4.763 13.515 3.946 30.577 7.221 14.529 2.748 18.986 8.386 34.012 7.037 5.043-0.424 4.474-0.594 9.289-3.68 4.392-2.897 2-2.481 1.125-9.314-0.963-10.686 0.273-14.664-4.608-22.364-8.079-12.726-8.746-12.517-14.024-20.901-5.277-8.269-11.133-25.896-17.173-26.015-4.75-0.116-7.506 2.464-10.497 5.513-2.992 3.047-3.759 17.447-8.249 22.001z"/>
+ <path fill="#ffd02b" d="m62.704 286.547c-7.388 7.33-23.805 1.445-27.757 4.912-4.204 3.729 5.455 10.311 4.533 17.594-0.593 4.427-2.272 6.553-3.417 12.523-0.854 4.651 3.786 4.098 6.262 5.225 11.619 4.671 14.104 4.087 30.341 7.185 14.438 2.72 18.864 8.33 33.787 6.991 5.01-0.418 4.341-0.604 9.166-3.604 4.292-2.729 1.942-2.359 0.972-9.396-1.163-10.613 0.263-14.709-4.369-22.012-8.03-12.641-8.787-12.371-14.03-20.7-5.243-8.214-10.962-25.903-16.962-26.021-4.719-0.117-7.457 2.447-10.428 5.477-2.972 3.029-3.632 17.313-8.098 21.826z"/>
+ <path fill="#ffd02d" d="m62.998 286.638c-7.57 7.493-24.13 1.61-27.925 4.987-4.174 3.742 5.635 10.451 4.716 17.4-0.604 4.398-2.182 6.596-3.478 12.518-0.969 4.623 3.875 4.045 6.382 5.101 11.991 4.579 14.694 4.228 30.105 7.149 14.345 2.688 18.743 8.275 33.563 6.944 4.977-0.411 4.207-0.61 9.042-3.524 4.193-2.562 1.884-2.239 0.819-9.481-1.366-10.538 0.251-14.754-4.133-21.659-7.979-12.557-8.825-12.224-14.034-20.498-5.208-8.16-10.791-25.91-16.751-26.027-4.688-0.114-7.407 2.433-10.358 5.441-2.951 3.01-3.505 17.174-7.948 21.649z"/>
+ <path fill="#ffd030" d="m63.292 286.729c-7.753 7.658-24.454 1.775-28.094 5.063-4.142 3.756 5.815 10.594 4.899 17.209-0.616 4.367-2.09 6.638-3.537 12.51-1.084 4.596 3.964 3.992 6.502 4.977 12.362 4.488 15.283 4.369 29.869 7.115 14.252 2.656 18.621 8.22 33.34 6.898 4.943-0.406 4.073-0.621 8.917-3.447 4.095-2.395 1.828-2.119 0.667-9.565-1.568-10.465 0.239-14.8-3.894-21.307-7.929-12.474-8.866-12.078-14.04-20.298-5.173-8.105-10.619-25.916-16.54-26.031-4.656-0.115-7.357 2.415-10.289 5.404-2.932 2.988-3.38 17.036-7.8 21.472z"/>
+ <path fill="#ffd133" d="m63.587 286.82c-7.937 7.822-24.78 1.94-28.263 5.138-4.111 3.77 5.995 10.734 5.081 17.016-0.627 4.339-1.998 6.68-3.597 12.504-1.199 4.568 4.054 3.939 6.623 4.854 12.732 4.396 15.873 4.51 29.633 7.08 14.16 2.625 18.499 8.164 33.116 6.852 4.909-0.4 3.939-0.629 8.793-3.369 3.997-2.227 1.77-1.999 0.514-9.648-1.771-10.393 0.228-14.846-3.654-20.955-7.88-12.39-8.907-11.934-14.046-20.098-5.139-8.051-10.448-25.922-16.329-26.037-4.625-0.113-7.309 2.398-10.221 5.368s-3.254 16.897-7.65 21.295z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m88.782 218.681c-0.936 2.088-1.728 20.017 2.952 27 4.68 6.911 3.312 10.872-1.872 5.616-5.4-5.112-8.928-12.816-9-18.145 0-3.096 2.376-15.84 3.313-17.208 1.007-1.44 5.327 1.153 4.607 2.737z"/>
+ <path fill="#030303" d="m88.692 219.032c-0.903 2.34-1.656 19.698 3.01 26.668 4.665 6.901 3.186 10.49-1.84 5.356-5.23-4.997-8.607-12.47-8.741-17.787-0.043-3.114 2.236-15.419 3.133-16.791 0.961-1.394 5.126 0.989 4.438 2.554z"/>
+ <path fill="#070707" d="m88.602 219.379c-0.871 2.593-1.584 19.383 3.067 26.338 4.65 6.891 3.06 10.109-1.808 5.098-5.062-4.882-8.287-12.125-8.481-17.432-0.087-3.131 2.095-14.998 2.952-16.373 0.915-1.345 4.926 0.828 4.27 2.369z"/>
+ <path fill="#0b0b0b" d="m88.512 219.729c-0.839 2.844-1.513 19.066 3.124 26.006 4.638 6.881 2.935 9.729-1.774 4.84-4.893-4.768-7.967-11.779-8.223-17.076-0.129-3.149 1.955-14.576 2.772-15.955 0.868-1.299 4.724 0.665 4.101 2.185z"/>
+ <path fill="#0f0f0f" d="m88.422 220.079c-0.806 3.096-1.439 18.748 3.183 25.674 4.623 6.869 2.809 9.347-1.742 4.58-4.724-4.651-7.646-11.434-7.963-16.719-0.173-3.168 1.814-14.154 2.592-15.537 0.819-1.252 4.52 0.504 3.93 2.002z"/>
+ <path fill="#131313" d="m88.332 220.426c-0.773 3.349-1.368 18.433 3.24 25.345 4.608 6.858 2.682 8.964-1.71 4.319-4.554-4.535-7.326-11.088-7.704-16.361-0.216-3.186 1.674-13.734 2.412-15.12 0.774-1.206 4.32 0.343 3.762 1.817z"/>
+ <path fill="#161616" d="m88.242 220.777c-0.741 3.601-1.296 18.115 3.298 25.013 4.594 6.848 2.556 8.582-1.678 4.061-4.385-4.421-7.006-10.742-7.444-16.006-0.26-3.203 1.533-13.313 2.231-14.702 0.728-1.16 4.118 0.18 3.593 1.634z"/>
+ <path fill="#1a1a1a" d="m88.152 221.125c-0.709 3.853-1.224 17.799 3.355 24.682 4.579 6.837 2.43 8.201-1.646 3.802-4.216-4.306-6.686-10.397-7.186-15.649-0.303-3.221 1.394-12.892 2.052-14.285 0.682-1.112 3.918 0.018 3.425 1.45z"/>
+ <path fill="#1e1e1e" d="m88.062 221.475c-0.677 4.104-1.152 17.482 3.413 24.35 4.564 6.826 2.304 7.82-1.613 3.543-4.046-4.191-6.365-10.051-6.927-15.293-0.345-3.24 1.253-12.47 1.872-13.867 0.634-1.066 3.716-0.144 3.255 1.267z"/>
+ <path fill="#222" d="m87.972 221.825c-0.645 4.355-1.08 17.164 3.47 24.018 4.551 6.816 2.179 7.439-1.58 3.285-3.877-4.076-6.044-9.707-6.667-14.938-0.389-3.258 1.112-12.049 1.691-13.449 0.587-1.019 3.514-0.306 3.086 1.084z"/>
+ <path fill="#262626" d="m87.883 222.172c-0.612 4.609-1.009 16.849 3.527 23.688 4.536 6.804 2.052 7.056-1.548 3.024-3.708-3.961-5.724-9.36-6.408-14.58-0.432-3.276 0.973-11.629 1.513-13.032 0.54-0.971 3.311-0.467 2.916 0.9z"/>
+ <path fill="#2a2a2a" d="m87.792 222.523c-0.579 4.86-0.936 16.531 3.586 23.356 4.521 6.793 1.926 6.675-1.516 2.765-3.539-3.845-5.403-9.015-6.148-14.224-0.476-3.293 0.831-11.207 1.332-12.614 0.493-0.925 3.11-0.63 2.746 0.717z"/>
+ <path fill="#2d2d2d" d="m87.702 222.872c-0.547 5.112-0.864 16.215 3.644 23.025 4.507 6.783 1.8 6.293-1.483 2.506-3.369-3.73-5.083-8.669-5.89-13.867-0.519-3.312 0.691-10.785 1.152-12.197 0.446-0.878 2.908-0.792 2.577 0.533z"/>
+ <path fill="#313131" d="m87.612 223.221c-0.515 5.363-0.792 15.898 3.701 22.693 4.492 6.772 1.674 5.912-1.451 2.248-3.2-3.615-4.763-8.324-5.63-13.512-0.563-3.33 0.551-10.363 0.972-11.779 0.399-0.831 2.707-0.953 2.408 0.35z"/>
+ <path fill="#353535" d="m87.522 223.57c-0.482 5.616-0.72 15.581 3.758 22.363 4.479 6.761 1.549 5.53-1.418 1.987-3.031-3.5-4.442-7.978-5.371-13.154-0.604-3.348 0.41-9.943 0.792-11.361 0.352-0.785 2.506-1.115 2.239 0.165z"/>
+ <path fill="#393939" d="m87.432 223.918c-0.45 5.869-0.648 15.265 3.815 22.033 4.464 6.75 1.422 5.147-1.386 1.728-2.862-3.384-4.122-7.632-5.112-12.798-0.647-3.366 0.271-9.522 0.612-10.944 0.307-0.737 2.305-1.278 2.071-0.019z"/>
+ <path fill="#3d3d3d" d="m87.343 224.269c-0.418 6.12-0.576 14.946 3.873 21.7 4.45 6.74 1.296 4.767-1.354 1.469-2.692-3.27-3.802-7.286-4.853-12.441-0.691-3.383 0.129-9.101 0.432-10.527 0.26-0.691 2.103-1.44 1.902-0.201z"/>
+ <path fill="#414141" d="m87.252 224.618c-0.385 6.373-0.504 14.631 3.932 21.369 4.436 6.729 1.17 4.385-1.321 1.211-2.523-3.154-3.481-6.941-4.594-12.086-0.734-3.402-0.011-8.68 0.252-10.109 0.212-0.644 1.901-1.602 1.731-0.385z"/>
+ <path fill="#444" d="m87.162 224.967c-0.353 6.623-0.432 14.314 3.989 21.037 4.421 6.719 1.044 4.004-1.289 0.951-2.354-3.039-3.161-6.595-4.334-11.729-0.778-3.42-0.151-8.258 0.071-9.691 0.166-0.597 1.7-1.763 1.563-0.568z"/>
+ <path fill="#484848" d="m87.072 225.316c-0.32 6.876-0.36 13.997 4.047 20.707 4.406 6.707 0.918 3.622-1.257 0.692-2.186-2.924-2.841-6.25-4.075-11.373-0.82-3.438-0.292-7.838-0.108-9.273 0.119-0.551 1.498-1.926 1.393-0.753z"/>
+ <path fill="#4c4c4c" d="m86.982 225.665c-0.288 7.129-0.288 13.68 4.104 20.377 4.393 6.695 0.792 3.24-1.224 0.432s-2.52-5.904-3.816-11.016c-0.863-3.457-0.432-7.416-0.287-8.856 0.071-0.505 1.295-2.089 1.223-0.937z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m88.782 218.681c4.32-9.433 6.696-19.584 12.888-29.448 6.12-9.792 3.672-13.608-0.863-8.64-4.536 4.968-9.504 15.48-9.504 15.48s-5.832 9.216-7.128 19.872c-0.217 1.8 3.887 4.248 4.607 2.736z"/>
+ <path fill="#020202" d="m88.968 218.071c4.279-9.5 6.615-19.246 12.586-28.802 5.901-9.488 3.608-13.279-0.764-8.472-4.403 4.847-9.302 15.236-9.368 15.381 0 0-5.637 8.993-6.877 19.239-0.209 1.771 3.72 4.145 4.423 2.654z"/>
+ <path fill="#050505" d="m89.152 217.459c4.239-9.566 6.535-18.908 12.284-28.155 5.683-9.183 3.547-12.95-0.663-8.303-4.27 4.725-9.099 14.991-9.231 15.282 0 0-5.442 8.766-6.627 18.605-0.201 1.741 3.554 4.042 4.237 2.571z"/>
+ <path fill="#070707" d="m89.338 216.849c4.199-9.634 6.454-18.572 11.981-27.51 5.465-8.878 3.484-12.621-0.563-8.135-4.137 4.605-8.896 14.748-9.096 15.184 0 0-5.247 8.542-6.376 17.972-0.192 1.713 3.387 3.937 4.054 2.489z"/>
+ <path fill="#0a0a0a" d="m89.522 216.239c4.159-9.701 6.375-18.234 11.68-26.865 5.247-8.573 3.422-12.292-0.461-7.966-4.005 4.483-8.693 14.503-8.96 15.085 0 0-5.053 8.317-6.126 17.337-0.186 1.684 3.219 3.837 3.867 2.409z"/>
+ <path fill="#0c0c0c" d="m89.708 215.627c4.118-9.769 6.294-17.897 11.376-26.218 5.029-8.268 3.36-11.962-0.359-7.797-3.871 4.361-8.49 14.259-8.823 14.985 0 0-4.858 8.093-5.876 16.706-0.179 1.653 3.051 3.731 3.682 2.324z"/>
+ <path fill="#0f0f0f" d="m89.893 215.017c4.077-9.836 6.213-17.56 11.073-25.573 4.812-7.963 3.298-11.633-0.259-7.629-3.738 4.241-8.288 14.015-8.688 14.887 0 0-4.663 7.868-5.625 16.072-0.169 1.624 2.886 3.628 3.499 2.243z"/>
+ <path fill="#111" d="m90.078 214.407c4.037-9.904 6.133-17.224 10.772-24.928 4.593-7.658 3.234-11.304-0.159-7.46-3.605 4.119-8.085 13.771-8.551 14.788 0 0-4.47 7.645-5.375 15.439-0.162 1.594 2.718 3.524 3.313 2.161z"/>
+ <path fill="#141414" d="m90.263 213.795c3.997-9.971 6.052-16.885 10.47-24.281 4.374-7.353 3.172-10.975-0.059-7.291-3.472 3.998-7.882 13.526-8.415 14.689 0 0-4.273 7.418-5.124 14.805-0.154 1.565 2.551 3.421 3.128 2.078z"/>
+ <path fill="#161616" d="m90.449 213.184c3.956-10.037 5.972-16.548 10.167-23.635 4.156-7.048 3.11-10.645 0.043-7.123-3.34 3.877-7.68 13.283-8.279 14.591 0 0-4.08 7.194-4.874 14.172-0.147 1.535 2.383 3.317 2.943 1.995z"/>
+ <path fill="#191919" d="m90.634 212.573c3.916-10.105 5.892-16.209 9.865-22.989 3.938-6.743 3.047-10.316 0.144-6.954-3.207 3.755-7.477 13.038-8.143 14.491 0 0-3.886 6.969-4.624 13.54-0.139 1.506 2.217 3.213 2.758 1.912z"/>
+ <path fill="#1c1c1c" d="m90.819 211.963c3.875-10.174 5.811-15.874 9.563-22.344 3.721-6.438 2.984-9.987 0.244-6.785-3.073 3.634-7.274 12.793-8.007 14.392 0 0-3.69 6.745-4.373 12.905-0.131 1.477 2.049 3.112 2.573 1.832z"/>
+ <path fill="#1e1e1e" d="m91.004 211.352c3.836-10.24 5.73-15.536 9.262-21.698 3.501-6.133 2.922-9.658 0.344-6.617-2.94 3.513-7.071 12.55-7.87 14.293 0 0-3.496 6.521-4.123 12.272-0.124 1.447 1.881 3.009 2.387 1.75z"/>
+ <path fill="#212121" d="m91.189 210.741c3.795-10.307 5.649-15.198 8.958-21.052 3.284-5.828 2.859-9.328 0.445-6.448-2.808 3.392-6.868 12.305-7.734 14.195 0 0-3.301 6.295-3.872 11.639-0.115 1.418 1.715 2.904 2.203 1.666z"/>
+ <path fill="#232323" d="m91.375 210.129c3.754-10.373 5.569-14.86 8.655-20.405 3.066-5.523 2.797-8.999 0.547-6.279-2.675 3.27-6.666 12.061-7.599 14.097 0 0-3.106 6.07-3.622 11.004-0.107 1.388 1.548 2.801 2.019 1.583z"/>
+ <path fill="#262626" d="m91.559 209.519c3.714-10.44 5.489-14.523 8.354-19.76 2.847-5.218 2.735-8.67 0.647-6.111-2.542 3.149-6.463 11.817-7.462 13.997 0 0-2.912 5.848-3.372 10.373-0.099 1.357 1.381 2.697 1.833 1.501z"/>
+ <path fill="#282828" d="m91.745 208.909c3.674-10.509 5.408-14.187 8.051-19.115 2.629-4.913 2.672-8.341 0.748-5.942-2.409 3.028-6.261 11.573-7.326 13.898 0 0-2.717 5.621-3.121 9.738-0.092 1.33 1.213 2.595 1.648 1.421z"/>
+ <path fill="#2b2b2b" d="m91.929 208.297c3.634-10.575 5.328-13.848 7.75-18.468 2.41-4.608 2.609-8.011 0.848-5.773-2.275 2.906-6.058 11.328-7.189 13.799 0 0-2.522 5.397-2.871 9.106-0.084 1.299 1.046 2.491 1.462 1.336z"/>
+ <path fill="#2d2d2d" d="m92.115 207.687c3.593-10.643 5.247-13.512 7.447-17.823 2.191-4.303 2.547-7.682 0.949-5.605-2.144 2.786-5.855 11.085-7.055 13.701 0 0-2.327 5.172-2.62 8.473-0.076 1.269 0.881 2.386 1.279 1.254z"/>
+ <path fill="#303030" d="m92.301 207.077c3.552-10.71 5.167-13.175 7.145-17.178 1.974-3.998 2.484-7.353 1.05-5.436-2.011 2.664-5.652 10.84-6.918 13.602 0 0-2.133 4.947-2.37 7.839-0.07 1.24 0.712 2.283 1.093 1.173z"/>
+ <path fill="#333" d="m92.485 206.465c3.513-10.778 5.087-12.837 6.843-16.531s2.422-7.024 1.15-5.268c-1.877 2.543-5.449 10.596-6.781 13.502 0 0-1.938 4.724-2.12 7.207-0.061 1.211 0.545 2.18 0.908 1.09z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m273.03 225.592c2.088-5.903 1.872-20.951-3.456-30.671-1.872-3.528-3.672-7.632-4.752-7.848-1.152-0.216-3.24 2.088-3.024 2.448 0.288 0.576 10.009 14.256 7.992 32.832-0.144 1.513 2.736 4.608 3.24 3.239z"/>
+ <path fill="#030303" d="m272.936 224.831c2.025-5.719 1.753-20.379-3.344-29.663-1.815-3.407-3.535-7.374-4.595-7.59-1.122-0.214-3.125 2.022-2.925 2.367 0.258 0.562 9.605 13.778 7.729 31.753-0.129 1.487 2.647 4.456 3.135 3.133z"/>
+ <path fill="#070707" d="m272.841 224.068c1.967-5.532 1.637-19.808-3.228-28.654-1.762-3.286-3.401-7.115-4.44-7.332-1.091-0.211-3.009 1.956-2.824 2.287 0.227 0.548 9.201 13.299 7.466 30.672-0.118 1.463 2.555 4.305 3.026 3.027z"/>
+ <path fill="#0b0b0b" d="m272.747 223.305c1.904-5.348 1.518-19.235-3.115-27.645-1.706-3.165-3.265-6.856-4.282-7.073-1.062-0.21-2.896 1.889-2.727 2.206 0.197 0.534 8.799 12.821 7.203 29.592-0.103 1.44 2.466 4.153 2.921 2.92z"/>
+ <path fill="#0f0f0f" d="m272.652 222.542c1.843-5.162 1.398-18.662-3.001-26.635-1.65-3.044-3.13-6.598-4.127-6.815-1.03-0.207-2.779 1.823-2.626 2.126 0.167 0.52 8.396 12.341 6.94 28.511-0.09 1.416 2.376 4.001 2.814 2.813z"/>
+ <path fill="#131313" d="m272.558 221.779c1.78-4.976 1.279-18.09-2.889-25.626-1.595-2.923-2.994-6.34-3.97-6.557-1-0.205-2.664 1.756-2.527 2.045 0.137 0.506 7.993 11.861 6.679 27.432-0.078 1.392 2.285 3.849 2.707 2.706z"/>
+ <path fill="#161616" d="m272.463 221.016c1.721-4.79 1.163-17.518-2.773-24.617-1.539-2.802-2.858-6.081-3.814-6.299-0.969-0.203-2.548 1.691-2.427 1.965 0.106 0.492 7.59 11.383 6.415 26.352-0.065 1.369 2.194 3.697 2.599 2.599z"/>
+ <path fill="#1a1a1a" d="m272.369 220.254c1.659-4.605 1.044-16.946-2.66-23.609-1.483-2.681-2.723-5.822-3.658-6.04-0.938-0.201-2.434 1.624-2.326 1.884 0.074 0.478 7.185 10.904 6.15 25.271-0.051 1.344 2.106 3.546 2.494 2.494z"/>
+ <path fill="#1e1e1e" d="m272.274 219.491c1.598-4.42 0.926-16.373-2.546-22.6-1.43-2.56-2.587-5.564-3.501-5.782-0.908-0.198-2.319 1.558-2.229 1.804 0.044 0.464 6.782 10.425 5.889 24.19-0.037 1.321 2.016 3.396 2.387 2.388z"/>
+ <path fill="#222" d="m272.18 218.728c1.535-4.233 0.807-15.802-2.434-21.59-1.373-2.439-2.452-5.306-3.345-5.524-0.877-0.197-2.203 1.491-2.128 1.723 0.014 0.45 6.379 9.947 5.625 23.111-0.023 1.297 1.927 3.242 2.282 2.28z"/>
+ <path fill="#262626" d="m272.085 217.965c1.476-4.049 0.69-15.229-2.318-20.582-1.317-2.317-2.316-5.046-3.188-5.265-0.847-0.194-2.088 1.425-2.029 1.642-0.016 0.436 5.977 9.468 5.362 22.032-0.011 1.272 1.835 3.089 2.173 2.173z"/>
+ <path fill="#2a2a2a" d="m271.991 217.202c1.413-3.861 0.571-14.656-2.206-19.572-1.262-2.196-2.18-4.788-3.032-5.007-0.815-0.191-1.973 1.36-1.929 1.562-0.047 0.422 5.573 8.988 5.099 20.951 0.003 1.247 1.746 2.939 2.068 2.066z"/>
+ <path fill="#2d2d2d" d="m271.896 216.439c1.353-3.677 0.453-14.084-2.091-18.563-1.207-2.076-2.045-4.529-2.876-4.749-0.786-0.19-1.858 1.293-1.83 1.481-0.077 0.408 5.17 8.51 4.836 19.87 0.017 1.226 1.656 2.789 1.961 1.961z"/>
+ <path fill="#313131" d="m271.802 215.676c1.29-3.491 0.334-13.512-1.979-17.553-1.151-1.956-1.909-4.272-2.72-4.493-0.755-0.187-1.742 1.227-1.73 1.401-0.106 0.394 4.768 8.031 4.573 18.791 0.031 1.202 1.567 2.637 1.856 1.854z"/>
+ <path fill="#353535" d="m271.707 214.915c1.23-3.307 0.217-12.94-1.864-16.545-1.096-1.834-1.773-4.014-2.563-4.234-0.725-0.185-1.627 1.16-1.631 1.32-0.138 0.38 4.364 7.552 4.311 17.71 0.042 1.176 1.475 2.485 1.747 1.749z"/>
+ <path fill="#393939" d="m271.613 214.151c1.168-3.119 0.098-12.367-1.751-15.535-1.04-1.714-1.638-3.755-2.407-3.976-0.693-0.183-1.512 1.094-1.531 1.24-0.168 0.366 3.962 7.074 4.049 16.63 0.055 1.153 1.384 2.332 1.64 1.641z"/>
+ <path fill="#3d3d3d" d="m271.518 213.388c1.106-2.935-0.021-11.796-1.638-14.527-0.983-1.592-1.502-3.496-2.25-3.716-0.664-0.181-1.396 1.028-1.432 1.159-0.198 0.352 3.558 6.594 3.785 15.549 0.07 1.13 1.296 2.183 1.535 1.535z"/>
+ <path fill="#414141" d="m271.424 212.625c1.047-2.75-0.139-11.223-1.522-13.518-0.93-1.471-1.367-3.238-2.094-3.459-0.635-0.178-1.282 0.962-1.333 1.079-0.229 0.338 3.153 6.114 3.521 14.47 0.083 1.106 1.205 2.03 1.428 1.428z"/>
+ <path fill="#444" d="m271.329 211.862c0.985-2.563-0.256-10.65-1.409-12.508-0.874-1.35-1.23-2.979-1.938-3.2-0.604-0.177-1.166 0.895-1.233 0.998-0.259 0.324 2.751 5.636 3.259 13.39 0.096 1.082 1.115 1.876 1.321 1.32z"/>
+ <path fill="#484848" d="m271.235 211.099c0.923-2.377-0.375-10.077-1.296-11.499-0.818-1.229-1.097-2.72-1.781-2.942-0.573-0.174-1.052 0.829-1.134 0.918-0.289 0.309 2.348 5.156 2.996 12.309 0.11 1.058 1.025 1.726 1.215 1.214z"/>
+ <path fill="#4c4c4c" d="m271.14 210.336c0.861-2.192-0.493-9.506-1.183-10.49-0.763-1.107-0.96-2.463-1.625-2.684-0.542-0.172-0.936 0.762-1.034 0.836-0.319 0.297 1.945 4.68 2.733 11.229 0.124 1.035 0.936 1.576 1.109 1.109z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m264.822 187.073c-10.224-13.968-23.472-18.504-22.104-14.112 0 0 10.152 5.76 19.08 16.56 1.728 2.088 4.608-0.288 3.024-2.448z"/>
+ <path fill="#030303" d="m264.372 186.687c-9.924-13.495-22.894-17.912-21.539-13.7 0.018 0.012 9.901 5.614 18.609 16.071 1.678 2.016 4.467-0.285 2.93-2.371z"/>
+ <path fill="#070707" d="m263.922 186.3c-9.624-13.022-22.316-17.319-20.975-13.287 0.036 0.023 9.652 5.467 18.139 15.582 1.628 1.943 4.325-0.283 2.836-2.295z"/>
+ <path fill="#0b0b0b" d="m263.472 185.913c-9.324-12.549-21.739-16.726-20.41-12.874 0.053 0.034 9.4 5.32 17.668 15.093 1.578 1.871 4.183-0.28 2.742-2.219z"/>
+ <path fill="#0f0f0f" d="m263.022 185.527c-9.024-12.077-21.162-16.134-19.847-12.462 0.071 0.045 9.151 5.174 17.198 14.604 1.529 1.798 4.043-0.278 2.649-2.142z"/>
+ <path fill="#131313" d="m262.571 185.14c-8.723-11.603-20.583-15.541-19.28-12.049 0.088 0.056 8.901 5.027 16.728 14.114 1.477 1.726 3.899-0.275 2.552-2.065z"/>
+ <path fill="#161616" d="m262.121 184.753c-8.423-11.13-20.006-14.948-18.716-11.636 0.106 0.067 8.651 4.88 16.257 13.625 1.428 1.654 3.759-0.272 2.459-1.989z"/>
+ <path fill="#1a1a1a" d="m261.671 184.367c-8.124-10.658-19.428-14.356-18.15-11.224 0.124 0.078 8.399 4.734 15.785 13.136 1.378 1.581 3.617-0.27 2.365-1.912z"/>
+ <path fill="#1e1e1e" d="m261.221 183.98c-7.824-10.185-18.851-13.763-17.588-10.811 0.143 0.089 8.151 4.587 15.315 12.647 1.33 1.508 3.477-0.267 2.273-1.836z"/>
+ <path fill="#222" d="m260.771 183.593c-7.524-9.711-18.273-13.17-17.022-10.398 0.159 0.1 7.9 4.44 14.844 12.158 1.279 1.436 3.335-0.265 2.178-1.76z"/>
+ <path fill="#262626" d="m260.321 183.206c-7.224-9.238-17.695-12.578-16.458-9.985 0.177 0.111 7.65 4.293 14.374 11.668 1.229 1.364 3.193-0.262 2.084-1.683z"/>
+ <path fill="#2a2a2a" d="m259.871 182.82c-6.924-8.766-17.118-11.986-15.893-9.573 0.193 0.122 7.398 4.147 13.902 11.179 1.18 1.291 3.053-0.259 1.991-1.606z"/>
+ <path fill="#2d2d2d" d="m259.42 182.433c-6.623-8.293-16.539-11.393-15.328-9.16 0.214 0.133 7.15 4 13.434 10.69 1.128 1.219 2.909-0.257 1.894-1.53z"/>
+ <path fill="#313131" d="m258.97 182.046c-6.323-7.819-15.963-10.8-14.764-8.747 0.23 0.144 6.899 3.853 12.962 10.201 1.08 1.146 2.769-0.254 1.802-1.454z"/>
+ <path fill="#353535" d="m258.52 181.66c-6.023-7.347-15.384-10.208-14.199-8.335 0.248 0.155 6.649 3.707 12.492 9.712 1.028 1.073 2.627-0.252 1.707-1.377z"/>
+ <path fill="#393939" d="m258.07 181.273c-5.723-6.874-14.807-9.615-13.634-7.922 0.265 0.166 6.398 3.56 12.021 9.222 0.978 1.002 2.485-0.249 1.613-1.3z"/>
+ <path fill="#3d3d3d" d="m257.62 180.886c-5.423-6.401-14.229-9.021-13.07-7.509 0.283 0.177 6.149 3.413 11.552 8.733 0.927 0.929 2.343-0.246 1.518-1.224z"/>
+ <path fill="#414141" d="m257.17 180.5c-5.124-5.928-13.65-8.43-12.505-7.097 0.301 0.188 5.898 3.267 11.079 8.244 0.879 0.856 2.203-0.244 1.426-1.147z"/>
+ <path fill="#444" d="m256.719 180.113c-4.823-5.455-13.073-7.837-11.94-6.684 0.319 0.199 5.649 3.12 10.609 7.755 0.829 0.784 2.061-0.241 1.331-1.071z"/>
+ <path fill="#484848" d="m256.269 179.726c-4.523-4.982-12.495-7.244-11.375-6.271 0.336 0.21 5.397 2.973 10.138 7.266 0.779 0.711 1.92-0.239 1.237-0.995z"/>
+ <path fill="#4c4c4c" d="m255.819 179.339c-4.223-4.509-11.918-6.652-10.812-5.859 0.354 0.222 5.148 2.827 9.668 6.777 0.73 0.639 1.779-0.236 1.144-0.918z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m273.03 225.592c0.144 6.265-5.76 22.248-7.992 21.673-2.52-0.576 0.504-5.257 2.809-13.177 0.936-3.312 1.655-11.447 1.943-11.735 0.936-0.936 3.24 1.728 3.24 3.239z"/>
+ <path fill="#050505" d="m272.846 226.116c0.103 6.082-5.638 21.594-7.797 21.018-2.422-0.567 0.548-5.146 2.814-12.928 0.899-3.178 1.595-10.947 1.887-11.25 0.914-0.927 3.147 1.527 3.096 3.16z"/>
+ <path fill="#0a0a0a" d="m272.662 226.637c0.063 5.902-5.514 20.939-7.601 20.363-2.323-0.558 0.592-5.035 2.82-12.681 0.861-3.041 1.534-10.446 1.83-10.761 0.89-0.917 3.054 1.327 2.951 3.079z"/>
+ <path fill="#0f0f0f" d="m272.478 227.159c0.021 5.721-5.392 20.284-7.405 19.711-2.224-0.55 0.635-4.927 2.827-12.434 0.824-2.907 1.473-9.945 1.773-10.273 0.866-0.911 2.959 1.125 2.805 2.996z"/>
+ <path fill="#141414" d="m272.294 227.68c-0.02 5.539-5.268 19.63-7.21 19.057-2.125-0.541 0.68-4.816 2.835-12.186 0.786-2.771 1.412-9.445 1.717-9.786 0.84-0.901 2.863 0.924 2.658 2.915z"/>
+ <path fill="#191919" d="m272.11 228.202c-0.063 5.359-5.146 18.977-7.014 18.403-2.027-0.532 0.722-4.706 2.841-11.938 0.748-2.637 1.351-8.944 1.659-9.299 0.818-0.893 2.77 0.722 2.514 2.834z"/>
+ <path fill="#1e1e1e" d="m271.926 228.723c-0.103 5.179-5.021 18.322-6.818 17.75-1.928-0.523 0.766-4.596 2.848-11.691 0.711-2.5 1.29-8.443 1.603-8.811 0.792-0.885 2.674 0.522 2.367 2.752z"/>
+ <path fill="#232323" d="m271.742 229.245c-0.144 4.998-4.9 17.668-6.623 17.096-1.83-0.514 0.811-4.485 2.854-11.442 0.673-2.366 1.229-7.944 1.545-8.325 0.771-0.876 2.583 0.32 2.224 2.671z"/>
+ <path fill="#282828" d="m271.558 229.766c-0.186 4.816-4.777 17.013-6.428 16.443-1.731-0.506 0.854-4.377 2.86-11.196 0.636-2.231 1.168-7.443 1.488-7.837 0.749-0.866 2.49 0.119 2.08 2.59z"/>
+ <path fill="#2d2d2d" d="m271.374 230.288c-0.226 4.637-4.653 16.359-6.231 15.789-1.632-0.496 0.896-4.266 2.866-10.947 0.6-2.098 1.107-6.943 1.433-7.351 0.722-0.859 2.393-0.081 1.932 2.509z"/>
+ <path fill="#333" d="m271.19 230.809c-0.268 4.456-4.531 15.705-6.036 15.136-1.534-0.489 0.94-4.155 2.873-10.7 0.561-1.961 1.046-6.443 1.375-6.863 0.7-0.848 2.3-0.282 1.788 2.427z"/>
+ <path fill="#383838" d="m271.006 231.331c-0.308 4.275-4.407 15.051-5.841 14.482-1.435-0.48 0.984-4.046 2.88-10.453 0.524-1.826 0.985-5.941 1.318-6.375 0.676-0.84 2.206-0.483 1.643 2.346z"/>
+ <path fill="#3d3d3d" d="m270.822 231.853c-0.35 4.093-4.285 14.396-5.645 13.828-1.338-0.472 1.027-3.937 2.886-10.206 0.485-1.691 0.924-5.441 1.261-5.887 0.653-0.832 2.113-0.684 1.498 2.265z"/>
+ <path fill="#424242" d="m270.638 232.374c-0.392 3.914-4.162 13.742-5.45 13.176-1.238-0.463 1.072-3.826 2.893-9.959 0.449-1.555 0.863-4.94 1.204-5.399 0.629-0.824 2.019-0.886 1.353 2.182z"/>
+ <path fill="#474747" d="m270.454 232.896c-0.432 3.731-4.039 13.087-5.254 12.521-1.14-0.453 1.115-3.715 2.9-9.711 0.411-1.42 0.802-4.439 1.146-4.912 0.606-0.815 1.925-1.086 1.208 2.102z"/>
+ <path fill="#4c4c4c" d="m270.27 233.417c-0.474 3.553-3.916 12.434-5.06 11.869-1.041-0.445 1.159-3.606 2.907-9.463 0.373-1.287 0.741-3.941 1.089-4.427 0.583-0.806 1.832-1.287 1.064 2.021z"/>
+ <path fill="#515151" d="m270.086 233.939c-0.514 3.37-3.793 11.778-4.862 11.214-0.942-0.436 1.201-3.496 2.913-9.216 0.336-1.151 0.68-3.438 1.032-3.938 0.558-0.797 1.736-1.489 0.917 1.94z"/>
+ <path fill="#565656" d="m269.902 234.461c-0.555 3.188-3.671 11.123-4.667 10.56-0.844-0.429 1.246-3.386 2.919-8.968 0.298-1.016 0.619-2.939 0.976-3.451 0.535-0.788 1.643-1.689 0.772 1.859z"/>
+ <path fill="#5b5b5b" d="m269.718 234.982c-0.597 3.009-3.548 10.47-4.472 9.907-0.745-0.42 1.29-3.275 2.926-8.721 0.262-0.881 0.559-2.438 0.919-2.963 0.511-0.781 1.549-1.89 0.627 1.777z"/>
+ <path fill="#606060" d="m269.534 235.504c-0.638 2.828-3.425 9.814-4.276 9.252-0.646-0.409 1.333-3.166 2.933-8.473 0.224-0.746 0.497-1.938 0.862-2.476 0.487-0.769 1.454-2.09 0.481 1.697z"/>
+ <path fill="#666" d="m269.35 236.025c-0.68 2.647-3.303 9.161-4.081 8.599-0.548-0.4 1.377-3.056 2.938-8.225 0.187-0.611 0.437-1.438 0.806-1.988 0.464-0.763 1.361-2.293 0.337 1.614z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m251.07 187.865c-1.537 1.622-2.903 9.991 0.938 12.893 3.844 2.818 10.59-2.391 10.59-5.379-0.086-6.746-9.991-9.222-11.528-7.514z"/>
+ <path fill="#010101" d="m251.207 188.006c-1.559 1.611-2.876 9.823 0.857 12.667 3.731 2.764 10.349-2.273 10.384-5.279-0.047-6.576-9.681-9.083-11.241-7.388z"/>
+ <path fill="#030303" d="m251.344 188.146c-1.582 1.601-2.85 9.653 0.774 12.438 3.62 2.709 10.109-2.154 10.178-5.177-0.007-6.404-9.37-8.943-10.952-7.261z"/>
+ <path fill="#050505" d="m251.481 188.287c-1.604 1.589-2.823 9.484 0.691 12.211 3.511 2.653 9.869-2.037 9.975-5.078 0.031-6.232-9.061-8.802-10.666-7.133z"/>
+ <path fill="#070707" d="m251.617 188.427c-1.626 1.579-2.795 9.316 0.611 11.984 3.397 2.6 9.629-1.918 9.768-4.976 0.071-6.062-8.751-8.664-10.379-7.008z"/>
+ <path fill="#090909" d="m251.754 188.567c-1.648 1.568-2.768 9.146 0.529 11.758 3.287 2.543 9.389-1.802 9.563-4.875 0.109-5.892-8.441-8.525-10.092-6.883z"/>
+ <path fill="#0b0b0b" d="m251.891 188.708c-1.671 1.557-2.741 8.978 0.445 11.529 3.177 2.489 9.15-1.683 9.358-4.774 0.15-5.72-8.13-8.385-9.803-6.755z"/>
+ <path fill="#0d0d0d" d="m252.028 188.848c-1.694 1.546-2.715 8.809 0.364 11.302 3.064 2.435 8.908-1.565 9.152-4.673 0.189-5.549-7.82-8.245-9.516-6.629z"/>
+ <path fill="#0f0f0f" d="m252.165 188.989c-1.716 1.535-2.688 8.64 0.282 11.074 2.953 2.38 8.669-1.447 8.948-4.572 0.226-5.378-7.512-8.106-9.23-6.502z"/>
+ <path fill="#111" d="m252.301 189.129c-1.737 1.524-2.659 8.471 0.2 10.847 2.844 2.325 8.431-1.33 8.743-4.471 0.266-5.207-7.201-7.966-8.943-6.376z"/>
+ <path fill="#131313" d="m252.438 189.269c-1.76 1.514-2.633 8.304 0.118 10.619 2.73 2.271 8.189-1.212 8.538-4.369 0.305-5.036-6.892-7.827-8.656-6.25z"/>
+ <path fill="#151515" d="m252.575 189.41c-1.783 1.503-2.606 8.133 0.036 10.391 2.62 2.216 7.949-1.094 8.332-4.268 0.344-4.865-6.581-7.687-8.368-6.123z"/>
+ <path fill="#161616" d="m252.712 189.55c-1.805 1.492-2.58 7.965-0.046 10.164 2.508 2.162 7.709-0.975 8.127-4.167 0.383-4.694-6.272-7.548-8.081-5.997z"/>
+ <path fill="#181818" d="m252.849 189.691c-1.828 1.481-2.554 7.796-0.129 9.937 2.397 2.105 7.47-0.857 7.922-4.066 0.423-4.524-5.961-7.409-7.793-5.871z"/>
+ <path fill="#1a1a1a" d="m252.985 189.831c-1.85 1.47-2.525 7.626-0.21 9.708 2.286 2.053 7.229-0.74 7.717-3.964 0.461-4.352-5.652-7.269-7.507-5.744z"/>
+ <path fill="#1c1c1c" d="m253.122 189.971c-1.872 1.46-2.499 7.459-0.292 9.482 2.175 1.996 6.989-0.623 7.511-3.865 0.501-4.18-5.341-7.128-7.219-5.617z"/>
+ <path fill="#1e1e1e" d="m253.259 190.112c-1.895 1.448-2.472 7.289-0.375 9.254 2.064 1.942 6.75-0.504 7.308-3.763 0.539-4.01-5.033-6.99-6.933-5.491z"/>
+ <path fill="#202020" d="m253.396 190.252c-1.917 1.438-2.445 7.122-0.457 9.027 1.953 1.888 6.51-0.386 7.102-3.662 0.578-3.839-4.722-6.85-6.645-5.365z"/>
+ <path fill="#222" d="m253.533 190.393c-1.939 1.426-2.418 6.951-0.539 8.799 1.841 1.832 6.271-0.268 6.896-3.561 0.618-3.668-4.412-6.711-6.357-5.238z"/>
+ <path fill="#242424" d="m253.669 190.533c-1.961 1.416-2.391 6.783-0.621 8.572 1.731 1.776 6.03-0.149 6.692-3.46 0.657-3.497-4.102-6.571-6.071-5.112z"/>
+ <path fill="#262626" d="m253.806 190.673c-1.984 1.405-2.364 6.615-0.703 8.344 1.619 1.724 5.79-0.032 6.485-3.358 0.697-3.326-3.791-6.432-5.782-4.986z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m250.71 256.698c1.513 1.512 2.809-2.232 4.32-3.457 1.512-1.224 3.96-3.888 8.856-3.888s4.535-0.144 4.319-2.017c-0.144-1.799-1.584-1.655-5.903-1.008-4.32 0.576-7.2 2.809-8.929 4.824-1.654 1.945-3.527 4.681-2.663 5.546z"/>
+ <path fill="#050505" d="m251.043 256.331c1.459 1.449 2.703-2.121 4.205-3.308 1.501-1.187 3.931-3.731 8.64-3.731 4.71-0.002 4.415-0.129 4.209-1.94-0.139-1.743-1.543-1.593-5.749-0.979-4.207 0.543-7.029 2.703-8.712 4.648-1.616 1.877-3.438 4.474-2.593 5.31z"/>
+ <path fill="#0a0a0a" d="m251.376 255.961c1.406 1.389 2.6-2.008 4.089-3.156 1.491-1.148 3.901-3.576 8.425-3.577 4.521-0.001 4.293-0.11 4.096-1.862-0.132-1.688-1.501-1.531-5.594-0.951-4.093 0.51-6.857 2.596-8.495 4.471-1.575 1.812-3.348 4.271-2.521 5.075z"/>
+ <path fill="#0f0f0f" d="m251.709 255.594c1.354 1.326 2.494-1.895 3.975-3.008 1.479-1.111 3.871-3.42 8.207-3.422s4.171-0.094 3.984-1.785c-0.126-1.631-1.46-1.467-5.438-0.924-3.979 0.479-6.687 2.492-8.28 4.297-1.533 1.747-3.257 4.066-2.448 4.842z"/>
+ <path fill="#141414" d="m252.042 255.226c1.302 1.265 2.39-1.783 3.858-2.856 1.47-1.076 3.842-3.266 7.991-3.268s4.05-0.077 3.873-1.709c-0.119-1.575-1.419-1.404-5.284-0.895-3.865 0.444-6.515 2.385-8.063 4.121-1.49 1.678-3.165 3.861-2.375 4.607z"/>
+ <path fill="#191919" d="m252.374 254.859c1.249 1.202 2.285-1.671 3.744-2.708 1.458-1.037 3.813-3.109 7.774-3.111 3.963-0.004 3.929-0.061 3.761-1.633-0.113-1.519-1.377-1.341-5.128-0.867-3.751 0.414-6.344 2.279-7.847 3.945-1.449 1.613-3.075 3.656-2.304 4.374z"/>
+ <path fill="#1e1e1e" d="m252.707 254.491c1.196 1.141 2.182-1.559 3.628-2.558 1.448-1 3.783-2.954 7.56-2.957 3.775-0.003 3.806-0.043 3.648-1.556-0.106-1.461-1.336-1.277-4.974-0.838-3.637 0.379-6.172 2.174-7.63 3.77-1.408 1.546-2.984 3.451-2.232 4.139z"/>
+ <path fill="#232323" d="m253.04 254.124c1.144 1.078 2.076-1.447 3.514-2.41 1.437-0.961 3.753-2.797 7.342-2.799 3.589-0.004 3.685-0.027 3.537-1.48-0.101-1.405-1.294-1.215-4.818-0.811-3.524 0.349-6.001 2.068-7.415 3.594-1.367 1.48-2.894 3.245-2.16 3.906z"/>
+ <path fill="#282828" d="m253.373 253.754c1.09 1.018 1.972-1.334 3.398-2.258 1.426-0.926 3.723-2.642 7.125-2.646 3.402-0.005 3.563-0.011 3.426-1.403-0.095-1.349-1.253-1.15-4.664-0.781-3.409 0.314-5.829 1.961-7.198 3.418-1.325 1.415-2.803 3.041-2.087 3.67z"/>
+ <path fill="#2d2d2d" d="m253.706 253.388c1.038 0.954 1.866-1.222 3.282-2.11 1.416-0.887 3.694-2.486 6.909-2.49 3.217-0.004 3.441 0.008 3.313-1.326-0.088-1.293-1.212-1.088-4.508-0.754-3.296 0.283-5.658 1.857-6.981 3.244-1.284 1.345-2.712 2.836-2.015 3.436z"/>
+ <path fill="#333" d="m254.039 253.02c0.985 0.893 1.762-1.109 3.167-1.96s3.664-2.33 6.693-2.335c3.029-0.006 3.32 0.023 3.202-1.249-0.082-1.237-1.171-1.024-4.354-0.726-3.182 0.25-5.485 1.75-6.765 3.066-1.243 1.282-2.622 2.634-1.943 3.204z"/>
+ <path fill="#383838" d="m254.372 252.652c0.933 0.831 1.657-0.998 3.051-1.81 1.396-0.813 3.636-2.174 6.478-2.18 2.843-0.006 3.199 0.039 3.09-1.172-0.076-1.181-1.129-0.963-4.198-0.697-3.068 0.217-5.314 1.644-6.55 2.891-1.202 1.214-2.531 2.427-1.871 2.968z"/>
+ <path fill="#3d3d3d" d="m254.704 252.284c0.88 0.771 1.553-0.885 2.938-1.66 1.383-0.775 3.604-2.019 6.26-2.024 2.656-0.007 3.078 0.058 2.979-1.095-0.069-1.125-1.088-0.899-4.044-0.67-2.954 0.185-5.144 1.539-6.333 2.715-1.16 1.148-2.441 2.222-1.8 2.734z"/>
+ <path fill="#424242" d="m255.037 251.917c0.827 0.707 1.448-0.773 2.821-1.51 1.373-0.738 3.576-1.863 6.044-1.871 2.47-0.007 2.956 0.074 2.867-1.018-0.063-1.068-1.046-0.836-3.889-0.641-2.841 0.151-4.973 1.433-6.116 2.539-1.119 1.083-2.35 2.018-1.727 2.501z"/>
+ <path fill="#474747" d="m255.37 251.549c0.774 0.645 1.344-0.661 2.706-1.362 1.362-0.7 3.545-1.706 5.828-1.713 2.283-0.009 2.834 0.09 2.754-0.942-0.057-1.012-1.005-0.773-3.733-0.613-2.727 0.119-4.801 1.328-5.899 2.365-1.078 1.013-2.26 1.81-1.656 2.265z"/>
+ <path fill="#4c4c4c" d="m255.703 251.181c0.721 0.584 1.239-0.55 2.59-1.212 1.353-0.663 3.517-1.551 5.612-1.559 2.096-0.009 2.713 0.107 2.643-0.865-0.051-0.955-0.964-0.709-3.577-0.584-2.613 0.086-4.631 1.222-5.686 2.188-1.035 0.949-2.168 1.607-1.582 2.032z"/>
+ <path fill="#515151" d="m256.036 250.813c0.669 0.521 1.134-0.436 2.476-1.063 1.341-0.625 3.485-1.395 5.395-1.402 1.91-0.01 2.591 0.124 2.531-0.789-0.044-0.898-0.922-0.646-3.423-0.557-2.499 0.055-4.458 1.117-5.469 2.014-0.994 0.882-2.077 1.402-1.51 1.797z"/>
+ <path fill="#565656" d="m256.369 250.446c0.616 0.459 1.029-0.324 2.36-0.912 1.33-0.589 3.456-1.24 5.178-1.248 1.723-0.01 2.47 0.141 2.42-0.713-0.039-0.842-0.881-0.582-3.268-0.527-2.387 0.021-4.287 1.01-5.252 1.836-0.953 0.816-1.987 1.199-1.438 1.564z"/>
+ <path fill="#5b5b5b" d="m256.701 250.079c0.564 0.397 0.926-0.213 2.245-0.764s3.427-1.084 4.963-1.093c1.536-0.011 2.348 0.157 2.307-0.636-0.031-0.785-0.839-0.52-3.112-0.5-2.271-0.01-4.116 0.906-5.035 1.662-0.913 0.751-1.898 0.993-1.368 1.331z"/>
+ <path fill="#606060" d="m257.034 249.709c0.511 0.336 0.821-0.1 2.13-0.612 1.309-0.515 3.397-0.929 4.746-0.938 1.351-0.01 2.227 0.176 2.196-0.558-0.026-0.729-0.799-0.457-2.958-0.472-2.158-0.043-3.945 0.799-4.82 1.486-0.87 0.682-1.805 0.788-1.294 1.094z"/>
+ <path fill="#666" d="m257.367 249.342c0.458 0.273 0.716 0.012 2.014-0.465 1.299-0.476 3.368-0.771 4.53-0.781 1.163-0.012 2.105 0.191 2.084-0.482-0.02-0.673-0.757-0.393-2.803-0.443-2.044-0.076-3.773 0.693-4.604 1.311-0.828 0.616-1.714 0.582-1.221 0.86z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m270.222 247.265c0 2.304 4.68 3.096 9.144 3.743 4.392 0.648 7.92 1.513 8.136 6.121 0.216 4.535-0.936 7.775 1.08 7.416 4.32-0.793 5.904-5.473 5.832-7.633 0-2.16-3.168-6.047-8.855-8.207-4.177-1.584-7.2-2.305-10.872-2.449-4.897-0.214-4.465 1.009-4.465 1.009z"/>
+ <path fill="#030303" d="m270.348 247.304c0.012 2.239 4.643 2.97 9.049 3.639 4.352 0.675 7.75 1.511 8.11 6.002 0.345 4.415-0.854 7.515 1.136 7.188 4.145-0.739 5.688-5.2 5.607-7.332-0.015-2.151-3.118-5.91-8.733-8.038-4.129-1.563-7.11-2.298-10.74-2.452-4.754-0.217-4.438 0.952-4.429 0.993z"/>
+ <path fill="#070707" d="m270.474 247.342c0.023 2.174 4.605 2.845 8.953 3.533 4.312 0.701 7.58 1.508 8.087 5.885 0.471 4.295-0.771 7.252 1.189 6.963 3.97-0.689 5.472-4.93 5.384-7.033-0.028-2.145-3.068-5.773-8.61-7.87-4.082-1.543-7.022-2.291-10.609-2.456-4.612-0.218-4.412 0.896-4.394 0.978z"/>
+ <path fill="#0b0b0b" d="m270.6 247.379c0.035 2.109 4.568 2.721 8.857 3.431 4.271 0.728 7.411 1.506 8.063 5.767 0.599 4.174-0.689 6.988 1.245 6.735 3.795-0.638 5.257-4.66 5.159-6.733-0.044-2.137-3.019-5.636-8.488-7.701-4.035-1.522-6.933-2.285-10.478-2.459-4.469-0.219-4.384 0.837-4.358 0.96z"/>
+ <path fill="#0f0f0f" d="m270.726 247.418c0.047 2.043 4.531 2.595 8.762 3.324 4.232 0.754 7.242 1.504 8.039 5.649 0.725 4.052-0.608 6.728 1.299 6.509 3.621-0.586 5.041-4.389 4.937-6.436-0.06-2.127-2.971-5.496-8.367-7.53-3.988-1.502-6.842-2.278-10.346-2.464-4.328-0.22-4.359 0.784-4.324 0.948z"/>
+ <path fill="#131313" d="m270.852 247.458c0.059 1.978 4.495 2.469 8.667 3.219 4.19 0.781 7.071 1.502 8.014 5.531 0.854 3.932-0.526 6.465 1.354 6.283 3.445-0.535 4.824-4.119 4.712-6.137-0.074-2.119-2.92-5.359-8.245-7.361-3.941-1.482-6.753-2.271-10.213-2.469-4.186-0.221-4.333 0.726-4.289 0.934z"/>
+ <path fill="#161616" d="m270.978 247.495c0.07 1.914 4.458 2.344 8.57 3.115 4.151 0.807 6.903 1.5 7.99 5.413 0.98 3.812-0.443 6.202 1.409 6.056 3.271-0.482 4.609-3.848 4.488-5.836-0.088-2.111-2.871-5.222-8.123-7.193-3.894-1.461-6.663-2.264-10.081-2.471-4.043-0.223-4.306 0.67-4.253 0.916z"/>
+ <path fill="#1a1a1a" d="m271.104 247.534c0.082 1.848 4.422 2.219 8.476 3.01 4.111 0.832 6.734 1.498 7.965 5.295 1.108 3.69-0.36 5.94 1.464 5.83 3.097-0.433 4.394-3.578 4.265-5.537-0.104-2.104-2.821-5.084-8-7.023-3.848-1.441-6.575-2.26-9.949-2.477-3.905-0.223-4.283 0.613-4.221 0.902z"/>
+ <path fill="#1e1e1e" d="m271.23 247.573c0.094 1.781 4.385 2.092 8.381 2.904 4.07 0.859 6.563 1.495 7.939 5.178 1.236 3.568-0.278 5.678 1.52 5.602 2.921-0.381 4.177-3.305 4.04-5.237-0.118-2.097-2.771-4.946-7.878-6.854-3.8-1.42-6.485-2.252-9.817-2.479-3.762-0.226-4.256 0.556-4.185 0.886z"/>
+ <path fill="#222" d="m271.356 247.61c0.105 1.717 4.348 1.969 8.285 2.801 4.029 0.885 6.395 1.493 7.916 5.059 1.362 3.449-0.197 5.416 1.573 5.377 2.746-0.329 3.962-3.036 3.816-4.939-0.133-2.087-2.722-4.808-7.756-6.684-3.753-1.4-6.396-2.247-9.686-2.484-3.618-0.227-4.227 0.499-4.148 0.87z"/>
+ <path fill="#262626" d="m271.482 247.648c0.118 1.651 4.311 1.843 8.189 2.694 3.99 0.914 6.226 1.492 7.892 4.943 1.491 3.328-0.115 5.152 1.629 5.149 2.571-0.278 3.746-2.765 3.592-4.64-0.146-2.08-2.672-4.672-7.634-6.516-3.705-1.38-6.306-2.24-9.553-2.488-3.478-0.225-4.203 0.446-4.115 0.858z"/>
+ <path fill="#2a2a2a" d="m271.608 247.687c0.129 1.587 4.273 1.716 8.094 2.59 3.95 0.938 6.056 1.489 7.867 4.825 1.618 3.206-0.033 4.891 1.684 4.922 2.396-0.227 3.53-2.494 3.368-4.34-0.162-2.072-2.623-4.534-7.512-6.348-3.658-1.358-6.216-2.232-9.421-2.492-3.336-0.226-4.177 0.39-4.08 0.843z"/>
+ <path fill="#2d2d2d" d="m271.734 247.725c0.141 1.521 4.237 1.591 7.999 2.484 3.909 0.967 5.886 1.488 7.842 4.707 1.746 3.086 0.05 4.629 1.739 4.697 2.221-0.176 3.313-2.225 3.144-4.041-0.177-2.064-2.572-4.396-7.389-6.178-3.612-1.339-6.128-2.227-9.29-2.497-3.194-0.227-4.151 0.334-4.045 0.828z"/>
+ <path fill="#313131" d="m271.86 247.763c0.153 1.456 4.2 1.466 7.903 2.381 3.869 0.991 5.717 1.485 7.817 4.589 1.873 2.965 0.132 4.365 1.794 4.469 2.046-0.123 3.099-1.953 2.92-3.742-0.191-2.055-2.523-4.258-7.267-6.008-3.565-1.318-6.038-2.22-9.158-2.5-3.051-0.229-4.124 0.276-4.009 0.811z"/>
+ <path fill="#353535" d="m271.986 247.801c0.165 1.392 4.163 1.341 7.808 2.275 3.829 1.018 5.547 1.483 7.794 4.473 2 2.843 0.213 4.103 1.848 4.242 1.873-0.074 2.883-1.683 2.696-3.443-0.206-2.047-2.474-4.12-7.145-5.838-3.517-1.299-5.948-2.215-9.026-2.506-2.91-0.229-4.099 0.221-3.975 0.797z"/>
+ <path fill="#393939" d="m272.112 247.84c0.176 1.326 4.126 1.215 7.712 2.17 3.789 1.045 5.378 1.482 7.771 4.354 2.127 2.723 0.295 3.842 1.901 4.016 1.698-0.021 2.667-1.412 2.474-3.144-0.222-2.038-2.426-3.981-7.023-5.669-3.47-1.277-5.859-2.208-8.894-2.509-2.769-0.231-4.074 0.164-3.941 0.782z"/>
+ <path fill="#3d3d3d" d="m272.238 247.877c0.188 1.262 4.089 1.09 7.617 2.066 3.749 1.071 5.208 1.479 7.745 4.236 2.255 2.602 0.377 3.578 1.957 3.789 1.522 0.029 2.451-1.141 2.249-2.844-0.236-2.033-2.375-3.846-6.901-5.5-3.423-1.258-5.769-2.203-8.762-2.514-2.626-0.231-4.046 0.109-3.905 0.767z"/>
+ <path fill="#414141" d="m272.364 247.917c0.2 1.195 4.052 0.965 7.522 1.961 3.708 1.098 5.037 1.477 7.72 4.119 2.383 2.479 0.46 3.315 2.012 3.562 1.348 0.081 2.236-0.87 2.025-2.545-0.251-2.022-2.325-3.707-6.778-5.331-3.377-1.237-5.681-2.195-8.631-2.518-2.485-0.233-4.02 0.05-3.87 0.752z"/>
+ <path fill="#444" d="m272.49 247.956c0.212 1.129 4.015 0.838 7.426 1.855 3.668 1.124 4.869 1.475 7.696 4 2.51 2.359 0.542 3.055 2.067 3.336 1.173 0.133 2.02-0.6 1.801-2.246-0.266-2.016-2.276-3.568-6.656-5.16-3.329-1.218-5.591-2.189-8.499-2.521-2.343-0.235-3.994-0.007-3.835 0.736z"/>
+ <path fill="#484848" d="m272.616 247.993c0.223 1.065 3.979 0.715 7.331 1.752 3.628 1.15 4.699 1.473 7.671 3.883 2.638 2.238 0.624 2.791 2.122 3.108 0.998 0.185 1.804-0.329 1.577-1.946-0.28-2.008-2.227-3.432-6.534-4.992-3.282-1.196-5.501-2.182-8.367-2.525-2.201-0.235-3.968-0.064-3.8 0.72z"/>
+ <path fill="#4c4c4c" d="m272.742 248.032c0.235 1 3.941 0.588 7.235 1.645 3.588 1.178 4.529 1.472 7.646 3.766 2.766 2.118 0.706 2.529 2.177 2.883 0.823 0.235 1.589-0.059 1.354-1.648-0.295-1.998-2.177-3.293-6.412-4.822-3.235-1.176-5.412-2.176-8.235-2.529-2.059-0.239-3.942-0.119-3.765 0.705z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#4c4c4c" d="m287.565 252.854c1.646 1 1.353 2.059 2.412 2.766 0.528 0.352 1.412 0.352 0.882-1-0.706-1.588-1.294-2.472-4.941-3.943-2.353-0.941-1.882 0.059 1.647 2.177z"/>
+ <path fill="#505050" d="m287.609 252.868c1.605 0.975 1.32 2.008 2.353 2.696 0.517 0.343 1.377 0.343 0.86-0.976-0.689-1.549-1.262-2.41-4.82-3.846-2.295-0.917-1.836 0.059 1.607 2.126z"/>
+ <path fill="#545454" d="m287.652 252.879c1.567 0.951 1.287 1.957 2.294 2.629 0.503 0.334 1.343 0.334 0.839-0.951-0.671-1.51-1.23-2.35-4.699-3.749-2.238-0.893-1.79 0.058 1.566 2.071z"/>
+ <path fill="#575757" d="m287.696 252.891c1.526 0.926 1.254 1.908 2.235 2.563 0.489 0.325 1.308 0.325 0.816-0.928-0.653-1.471-1.199-2.289-4.578-3.652-2.179-0.872-1.743 0.055 1.527 2.017z"/>
+ <path fill="#5b5b5b" d="m287.74 252.903c1.485 0.902 1.22 1.857 2.175 2.494 0.479 0.318 1.274 0.318 0.796-0.902-0.637-1.432-1.167-2.229-4.457-3.556-2.122-0.849-1.697 0.054 1.486 1.964z"/>
+ <path fill="#5f5f5f" d="m287.783 252.915c1.446 0.879 1.188 1.808 2.117 2.426 0.464 0.31 1.239 0.31 0.773-0.877-0.619-1.394-1.136-2.168-4.336-3.459-2.064-0.826-1.65 0.052 1.446 1.91z"/>
+ <path fill="#636363" d="m287.827 252.926c1.405 0.854 1.154 1.758 2.057 2.359 0.452 0.301 1.205 0.301 0.754-0.853-0.603-1.354-1.104-2.108-4.216-3.363-2.007-0.801-1.605 0.053 1.405 1.857z"/>
+ <path fill="#676767" d="m287.871 252.94c1.364 0.828 1.121 1.705 1.998 2.29 0.438 0.292 1.17 0.292 0.731-0.828-0.585-1.315-1.072-2.047-4.095-3.267-1.948-0.779-1.558 0.05 1.366 1.805z"/>
+ <path fill="#6b6b6b" d="m287.914 252.952c1.325 0.805 1.088 1.655 1.94 2.223 0.425 0.283 1.135 0.283 0.709-0.803-0.568-1.277-1.041-1.988-3.974-3.17-1.891-0.757-1.512 0.047 1.325 1.75z"/>
+ <path fill="#6e6e6e" d="m287.958 252.963c1.284 0.779 1.056 1.605 1.88 2.156 0.413 0.274 1.102 0.274 0.688-0.779-0.551-1.238-1.009-1.926-3.853-3.073-1.833-0.733-1.466 0.046 1.285 1.696z"/>
+ <path fill="#727272" d="m288.002 252.976c1.243 0.755 1.021 1.554 1.821 2.087 0.399 0.266 1.066 0.266 0.666-0.755-0.533-1.199-0.977-1.865-3.731-2.976-1.776-0.71-1.421 0.045 1.244 1.644z"/>
+ <path fill="#767676" d="m288.045 252.989c1.203 0.73 0.989 1.504 1.763 2.02 0.387 0.257 1.031 0.257 0.645-0.731-0.516-1.159-0.946-1.805-3.61-2.879-1.72-0.688-1.376 0.042 1.202 1.59z"/>
+ <path fill="#7a7a7a" d="m288.089 253c1.163 0.705 0.955 1.453 1.703 1.951 0.373 0.25 0.997 0.25 0.623-0.705-0.499-1.121-0.914-1.744-3.489-2.783-1.661-0.664-1.329 0.041 1.163 1.537z"/>
+ <path fill="#7e7e7e" d="m288.133 253.012c1.122 0.682 0.923 1.404 1.644 1.885 0.361 0.24 0.962 0.24 0.602-0.682-0.481-1.082-0.882-1.684-3.367-2.687-1.605-0.64-1.285 0.041 1.121 1.484z"/>
+ <path fill="#828282" d="m288.176 253.025c1.082 0.657 0.89 1.353 1.586 1.815 0.348 0.232 0.927 0.232 0.578-0.656-0.463-1.043-0.85-1.623-3.245-2.59-1.547-0.618-1.237 0.039 1.081 1.431z"/>
+ <path fill="#858585" d="m288.22 253.038c1.042 0.631 0.855 1.301 1.524 1.748 0.335 0.223 0.894 0.223 0.559-0.633-0.446-1.005-0.818-1.563-3.125-2.492-1.488-0.596-1.19 0.037 1.042 1.377z"/>
+ <path fill="#898989" d="m288.264 253.049c1.001 0.607 0.821 1.252 1.466 1.681 0.322 0.214 0.857 0.214 0.536-0.608-0.43-0.965-0.786-1.502-3.004-2.396-1.43-0.573-1.144 0.034 1.002 1.323z"/>
+ <path fill="#8d8d8d" d="m288.307 253.061c0.961 0.584 0.79 1.201 1.407 1.613 0.309 0.205 0.823 0.205 0.515-0.584-0.412-0.926-0.755-1.441-2.883-2.299-1.373-0.548-1.098 0.034 0.961 1.27z"/>
+ <path fill="#919191" d="m288.351 253.073c0.921 0.559 0.756 1.151 1.348 1.547 0.296 0.196 0.789 0.196 0.493-0.56-0.395-0.888-0.723-1.381-2.762-2.204-1.315-0.525-1.052 0.033 0.921 1.217z"/>
+ <path fill="#959595" d="m288.395 253.084c0.88 0.535 0.723 1.102 1.289 1.479 0.282 0.189 0.754 0.189 0.471-0.534-0.377-0.849-0.691-1.321-2.641-2.106-1.257-0.505-1.006 0.031 0.881 1.161z"/>
+ <path fill="#999" d="m288.438 253.097c0.84 0.51 0.689 1.05 1.229 1.409 0.271 0.181 0.721 0.181 0.45-0.51-0.36-0.81-0.66-1.26-2.52-2.01-1.199-0.48-0.959 0.031 0.841 1.111z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path d="m222.275 107.427c-0.738 0.902 0.574 8.365 5.412 13.285 4.839 4.838 7.791 4.838 9.759 2.706 3.771-4.018 0.738-7.791-1.558-10.415-2.297-2.624-5.248-1.722-7.955-4.346-2.706-2.624-4.592-2.46-5.658-1.23z"/>
+ <path fill="#050505" d="m222.345 107.494c-0.732 0.895 0.569 8.3 5.369 13.182 4.803 4.801 7.731 4.801 9.685 2.685 3.742-3.987 0.731-7.73-1.546-10.334-2.278-2.604-5.208-1.709-7.894-4.312-2.684-2.604-4.556-2.441-5.614-1.221z"/>
+ <path fill="#0a0a0a" d="m222.416 107.561c-0.727 0.888 0.565 8.235 5.328 13.079 4.763 4.763 7.67 4.763 9.607 2.664 3.713-3.956 0.727-7.67-1.534-10.253-2.26-2.584-5.166-1.696-7.831-4.279-2.664-2.583-4.521-2.422-5.57-1.211z"/>
+ <path fill="#0f0f0f" d="m222.486 107.628c-0.721 0.881 0.561 8.17 5.286 12.976 4.726 4.725 7.608 4.725 9.532 2.642 3.684-3.924 0.72-7.609-1.522-10.172-2.243-2.563-5.126-1.682-7.77-4.244-2.643-2.563-4.485-2.403-5.526-1.202z"/>
+ <path fill="#141414" d="m222.556 107.695c-0.716 0.874 0.557 8.105 5.243 12.872 4.689 4.688 7.55 4.688 9.456 2.622 3.655-3.893 0.716-7.549-1.51-10.091-2.224-2.543-5.085-1.669-7.707-4.211-2.621-2.543-4.449-2.384-5.482-1.192z"/>
+ <path fill="#191919" d="m222.627 107.762c-0.71 0.867 0.552 8.04 5.202 12.769 4.65 4.65 7.488 4.65 9.379 2.601 3.626-3.862 0.71-7.489-1.497-10.011s-5.044-1.655-7.646-4.177-4.414-2.364-5.438-1.182z"/>
+ <path fill="#1e1e1e" d="m222.697 107.829c-0.704 0.86 0.547 7.975 5.16 12.666 4.613 4.612 7.428 4.612 9.304 2.579 3.596-3.83 0.703-7.427-1.486-9.929-2.188-2.502-5.003-1.642-7.584-4.143-2.579-2.502-4.378-2.346-5.394-1.173z"/>
+ <path fill="#232323" d="m222.767 107.896c-0.697 0.853 0.543 7.91 5.117 12.562 4.576 4.575 7.367 4.575 9.229 2.559 3.567-3.8 0.698-7.367-1.473-9.848-2.171-2.482-4.963-1.629-7.522-4.11s-4.343-2.326-5.351-1.163z"/>
+ <path fill="#282828" d="m222.838 107.963c-0.691 0.846 0.538 7.845 5.076 12.459 4.537 4.537 7.307 4.537 9.152 2.538 3.537-3.769 0.691-7.307-1.461-9.768-2.154-2.461-4.922-1.615-7.461-4.076-2.538-2.461-4.307-2.307-5.306-1.153z"/>
+ <path fill="#2d2d2d" d="m222.908 108.03c-0.686 0.839 0.534 7.78 5.034 12.355 4.5 4.499 7.246 4.499 9.076 2.516 3.509-3.737 0.686-7.246-1.449-9.686-2.135-2.441-4.881-1.602-7.399-4.042-2.516-2.44-4.271-2.287-5.262-1.143z"/>
+ <path fill="#333" d="m222.978 108.096c-0.681 0.832 0.529 7.715 4.992 12.253 4.463 4.462 7.186 4.462 9.001 2.496 3.479-3.706 0.68-7.186-1.438-9.605-2.118-2.42-4.841-1.588-7.337-4.008s-4.235-2.27-5.218-1.136z"/>
+ <path fill="#383838" d="m223.048 108.163c-0.674 0.825 0.526 7.65 4.95 12.15 4.425 4.425 7.125 4.425 8.925 2.475 3.45-3.675 0.676-7.125-1.425-9.525-2.099-2.4-4.8-1.575-7.274-3.975-2.475-2.399-4.201-2.25-5.176-1.125z"/>
+ <path fill="#3d3d3d" d="m223.119 108.23c-0.669 0.818 0.521 7.585 4.908 12.047 4.387 4.387 7.063 4.387 8.849 2.453 3.42-3.643 0.669-7.064-1.413-9.443-2.082-2.38-4.759-1.562-7.214-3.941-2.453-2.38-4.164-2.231-5.13-1.116z"/>
+ <path fill="#424242" d="m223.189 108.297c-0.663 0.811 0.516 7.52 4.866 11.944 4.35 4.349 7.004 4.349 8.772 2.432 3.392-3.612 0.663-7.004-1.4-9.363-2.064-2.359-4.719-1.548-7.151-3.907-2.433-2.359-4.129-2.212-5.087-1.106z"/>
+ <path fill="#474747" d="m223.259 108.364c-0.656 0.804 0.513 7.455 4.824 11.84 4.313 4.312 6.944 4.312 8.697 2.412 3.362-3.582 0.658-6.944-1.388-9.282-2.046-2.339-4.679-1.535-7.09-3.874-2.411-2.338-4.093-2.192-5.043-1.096z"/>
+ <path fill="#4c4c4c" d="m223.33 108.431c-0.651 0.797 0.507 7.39 4.782 11.737 4.274 4.274 6.882 4.274 8.621 2.39 3.332-3.55 0.651-6.883-1.377-9.201s-4.636-1.521-7.028-3.839c-2.39-2.318-4.057-2.174-4.998-1.087z"/>
+ <path fill="#515151" d="m223.4 108.498c-0.646 0.79 0.503 7.325 4.74 11.634 4.236 4.236 6.821 4.236 8.545 2.369 3.304-3.519 0.646-6.822-1.364-9.12s-4.596-1.508-6.966-3.806c-2.369-2.298-4.022-2.154-4.955-1.077z"/>
+ <path fill="#565656" d="m223.47 108.565c-0.641 0.783 0.499 7.26 4.697 11.53 4.199 4.199 6.763 4.199 8.471 2.349 3.273-3.488 0.64-6.762-1.353-9.039-1.993-2.278-4.556-1.495-6.905-3.773-2.347-2.277-3.985-2.135-4.91-1.067z"/>
+ <path fill="#5b5b5b" d="m223.541 108.632c-0.635 0.776 0.493 7.195 4.656 11.427 4.161 4.161 6.701 4.161 8.393 2.327 3.245-3.456 0.636-6.701-1.34-8.958-1.975-2.257-4.514-1.48-6.843-3.738-2.327-2.257-3.95-2.116-4.866-1.058z"/>
+ <path fill="#606060" d="m223.611 108.699c-0.629 0.769 0.489 7.13 4.614 11.324 4.124 4.123 6.64 4.123 8.317 2.306 3.215-3.425 0.628-6.641-1.328-8.877-1.957-2.237-4.474-1.468-6.78-3.705-2.306-2.236-3.915-2.097-4.823-1.048z"/>
+ <path fill="#666" d="m223.681 108.765c-0.623 0.762 0.484 7.065 4.571 11.221 4.086 4.086 6.58 4.086 8.242 2.285 3.187-3.394 0.623-6.58-1.315-8.796-1.939-2.217-4.434-1.455-6.72-3.671-2.284-2.216-3.878-2.078-4.778-1.039z"/>
+ </g>
+ <g transform="translate(-12.4048,10.0005)">
+ <path fill="#fc0" d="m137.79 109.277c1.978 1.366 2.031 1.607 4.948 3.514 4.64 3.768 12.885 4.616 16.922 4.75 9.233 1.467 25.738-7.161 32.273-11.111 3.291-2.463 9.38-7.551 11.659-7.637 1.405 1.485-0.66 1.792-3.587 3.775-3.906 2.779-7.25 5.156-13.172 8.515-6.338 3.316-16.078 8.794-28.548 8.054-6.542-0.959-6.566-1.024-10.606-3.086-2.4-1.732-7.901-4.608-9.889-6.774z"/>
+ <linearGradient id="al" x1="129.342" gradientUnits="userSpaceOnUse" x2="195.598" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.305" y2="259.305">
+ <stop stop-color="#FAC700" offset="0"/>
+ <stop stop-color="#F7C400" offset=".415"/>
+ <stop stop-color="#F7C400" offset="1"/>
+ </linearGradient>
+ <path fill="url(#al)" d="m137.742 109.259c1.926 1.274 2.165 1.643 5.083 3.554 4.616 3.734 12.716 4.616 16.796 4.763 9.365 1.452 26.05-7.294 32.356-11.159 3.357-2.506 9.344-7.498 11.595-7.604 1.365 1.472-0.728 1.768-3.688 3.814-3.889 2.753-7.119 5.065-12.972 8.383-6.29 3.291-16.078 8.795-28.536 8.104-6.561-0.945-6.851-1.07-10.758-3.079-2.468-1.755-7.876-4.587-9.876-6.776z"/>
+ <linearGradient id="am" x1="129.293" gradientUnits="userSpaceOnUse" x2="195.554" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.311" y2="259.311">
+ <stop stop-color="#F6C200" offset="0"/>
+ <stop stop-color="#EFBC00" offset=".415"/>
+ <stop stop-color="#EFBC00" offset="1"/>
+ </linearGradient>
+ <path fill="url(#am)" d="m137.693 109.24c1.876 1.183 2.3 1.68 5.218 3.595 4.593 3.7 12.548 4.616 16.67 4.776 9.498 1.437 26.364-7.428 32.44-11.207 3.425-2.55 9.308-7.444 11.528-7.57 1.326 1.457-0.795 1.743-3.788 3.854-3.87 2.725-6.99 4.973-12.771 8.25-6.243 3.266-16.078 8.796-28.525 8.154-6.579-0.931-7.134-1.117-10.908-3.073-2.536-1.779-7.852-4.567-9.864-6.779z"/>
+ <linearGradient id="an" x1="129.245" gradientUnits="userSpaceOnUse" x2="195.51" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.317" y2="259.317">
+ <stop stop-color="#F1BD00" offset="0"/>
+ <stop stop-color="#E8B500" offset=".415"/>
+ <stop stop-color="#E8B500" offset="1"/>
+ </linearGradient>
+ <path fill="url(#an)" d="m137.645 109.222c1.825 1.091 2.434 1.715 5.352 3.635 4.569 3.665 12.38 4.615 16.544 4.789 9.631 1.422 26.677-7.562 32.524-11.255 3.491-2.594 9.271-7.392 11.463-7.538 1.287 1.442-0.861 1.718-3.889 3.893-3.853 2.699-6.86 4.882-12.57 8.119-6.195 3.241-16.078 8.797-28.513 8.203-6.6-0.916-7.418-1.163-11.061-3.066-2.603-1.801-7.826-4.546-9.85-6.78z"/>
+ <linearGradient id="ao" x1="129.196" gradientUnits="userSpaceOnUse" x2="195.465" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.322" y2="259.322">
+ <stop stop-color="#EDB800" offset="0"/>
+ <stop stop-color="#E0AD00" offset=".415"/>
+ <stop stop-color="#E0AD00" offset="1"/>
+ </linearGradient>
+ <path fill="url(#ao)" d="m137.596 109.203c1.774 1 2.568 1.752 5.487 3.676 4.545 3.631 12.211 4.615 16.418 4.801 9.764 1.408 26.989-7.695 32.608-11.302 3.557-2.637 9.236-7.338 11.396-7.505 1.247 1.427-0.928 1.693-3.99 3.932-3.833 2.672-6.729 4.791-12.369 7.986-6.148 3.217-16.078 8.799-28.501 8.254-6.619-0.902-7.702-1.21-11.21-3.059-2.672-1.825-7.803-4.525-9.839-6.783z"/>
+ <linearGradient id="ap" x1="129.148" gradientUnits="userSpaceOnUse" x2="195.422" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.327" y2="259.327">
+ <stop stop-color="#E9B300" offset="0"/>
+ <stop stop-color="#D8A500" offset=".415"/>
+ <stop stop-color="#D8A500" offset="1"/>
+ </linearGradient>
+ <path fill="url(#ap)" d="m137.548 109.184c1.724 0.909 2.703 1.788 5.622 3.717 4.522 3.597 12.043 4.615 16.292 4.814 9.896 1.393 27.303-7.829 32.692-11.35 3.624-2.681 9.2-7.286 11.331-7.472 1.208 1.412-0.995 1.668-4.092 3.972-3.814 2.644-6.6 4.698-12.168 7.853-6.101 3.192-16.077 8.8-28.489 8.303-6.638-0.887-7.986-1.256-11.361-3.052-2.741-1.848-7.779-4.504-9.827-6.785z"/>
+ <linearGradient id="aq" x1="129.099" gradientUnits="userSpaceOnUse" x2="195.379" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.332" y2="259.332">
+ <stop stop-color="#E4AE00" offset="0"/>
+ <stop stop-color="#D19E00" offset=".415"/>
+ <stop stop-color="#D19E00" offset="1"/>
+ </linearGradient>
+ <path fill="url(#aq)" d="m137.499 109.166c1.673 0.817 2.838 1.824 5.757 3.757 4.499 3.562 11.875 4.614 16.166 4.827 10.029 1.378 27.615-7.963 32.776-11.398 3.691-2.725 9.164-7.232 11.265-7.439 1.169 1.397-1.061 1.644-4.191 4.01-3.796 2.618-6.469 4.608-11.968 7.722-6.053 3.167-16.077 8.801-28.478 8.353-6.657-0.873-8.27-1.303-11.512-3.046-2.809-1.87-7.755-4.483-9.815-6.786z"/>
+ <linearGradient id="ar" x1="129.051" gradientUnits="userSpaceOnUse" x2="195.338" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.336" y2="259.336">
+ <stop stop-color="#E0A900" offset="0"/>
+ <stop stop-color="#C99600" offset=".415"/>
+ <stop stop-color="#C99600" offset="1"/>
+ </linearGradient>
+ <path fill="url(#ar)" d="m137.451 109.147c1.622 0.726 2.972 1.86 5.892 3.798 4.475 3.528 11.705 4.614 16.04 4.84 10.161 1.362 27.929-8.097 32.859-11.447 3.757-2.767 9.128-7.178 11.2-7.405 1.13 1.382-1.128 1.619-4.294 4.049-3.777 2.592-6.339 4.517-11.767 7.589-6.005 3.143-16.077 8.803-28.466 8.404-6.676-0.859-8.553-1.35-11.663-3.039-2.876-1.894-7.729-4.462-9.801-6.789z"/>
+ <linearGradient id="w" x1="129.003" gradientUnits="userSpaceOnUse" x2="195.296" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.34" y2="259.34">
+ <stop stop-color="#DCA400" offset="0"/>
+ <stop stop-color="#C18E00" offset=".415"/>
+ <stop stop-color="#C18E00" offset="1"/>
+ </linearGradient>
+ <path fill="url(#w)" d="m137.403 109.129c1.571 0.634 3.105 1.896 6.026 3.838 4.45 3.494 11.536 4.614 15.913 4.852 10.295 1.348 28.241-8.23 32.943-11.494 3.824-2.811 9.092-7.125 11.134-7.373 1.092 1.367-1.194 1.594-4.394 4.088-3.759 2.565-6.209 4.425-11.566 7.457-5.957 3.118-16.077 8.804-28.454 8.453-6.694-0.844-8.837-1.396-11.813-3.032-2.945-1.916-7.706-4.44-9.789-6.789z"/>
+ <linearGradient id="x" x1="128.954" gradientUnits="userSpaceOnUse" x2="195.255" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.343" y2="259.343">
+ <stop stop-color="#D79F00" offset="0"/>
+ <stop stop-color="#BA8700" offset=".415"/>
+ <stop stop-color="#BA8700" offset="1"/>
+ </linearGradient>
+ <path fill="url(#x)" d="m137.354 109.11c1.521 0.543 3.241 1.932 6.161 3.879 4.428 3.459 11.368 4.613 15.788 4.865 10.427 1.333 28.554-8.364 33.026-11.542 3.892-2.855 9.057-7.073 11.068-7.339 1.052 1.353-1.261 1.569-4.495 4.127-3.74 2.538-6.078 4.334-11.365 7.325-5.91 3.093-16.077 8.805-28.441 8.503-6.716-0.83-9.121-1.443-11.966-3.026-3.012-1.939-7.68-4.42-9.776-6.792z"/>
+ <linearGradient id="y" x1="128.906" gradientUnits="userSpaceOnUse" x2="195.216" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.348" y2="259.348">
+ <stop stop-color="#D39B00" offset="0"/>
+ <stop stop-color="#B27F00" offset=".415"/>
+ <stop stop-color="#B27F00" offset="1"/>
+ </linearGradient>
+ <path fill="url(#y)" d="m137.306 109.091c1.47 0.451 3.375 1.969 6.296 3.919 4.403 3.426 11.2 4.614 15.662 4.879 10.559 1.318 28.865-8.498 33.109-11.59 3.958-2.899 9.021-7.02 11.003-7.306 1.013 1.337-1.328 1.544-4.596 4.167-3.722 2.511-5.949 4.242-11.165 7.192-5.862 3.068-16.077 8.807-28.43 8.553-6.734-0.816-9.405-1.489-12.116-3.019-3.08-1.963-7.656-4.4-9.763-6.795z"/>
+ <linearGradient id="z" x1="128.857" gradientUnits="userSpaceOnUse" x2="195.176" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.35" y2="259.35">
+ <stop stop-color="#CF9600" offset="0"/>
+ <stop stop-color="#a70" offset=".415"/>
+ <stop stop-color="#a70" offset="1"/>
+ </linearGradient>
+ <path fill="url(#z)" d="m137.257 109.073c1.421 0.359 3.511 2.005 6.432 3.959 4.38 3.392 11.032 4.614 15.536 4.892 10.691 1.303 29.179-8.631 33.193-11.638 4.024-2.942 8.984-6.967 10.938-7.274 0.973 1.323-1.396 1.521-4.697 4.206-3.703 2.484-5.818 4.151-10.964 7.06-5.814 3.043-16.077 8.808-28.418 8.603-6.753-0.802-9.689-1.535-12.268-3.012-3.149-1.986-7.632-4.378-9.752-6.796z"/>
+ <linearGradient id="aa" x1="128.809" gradientUnits="userSpaceOnUse" x2="195.137" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.354" y2="259.354">
+ <stop stop-color="#CA9100" offset="0"/>
+ <stop stop-color="#A37000" offset=".415"/>
+ <stop stop-color="#A37000" offset="1"/>
+ </linearGradient>
+ <path fill="url(#aa)" d="m137.209 109.054c1.368 0.268 3.645 2.041 6.565 4 4.356 3.357 10.864 4.613 15.41 4.904 10.824 1.289 29.493-8.764 33.277-11.685 4.092-2.986 8.948-6.914 10.871-7.241 0.935 1.308-1.461 1.496-4.797 4.245-3.685 2.457-5.688 4.06-10.763 6.928-5.768 3.018-16.077 8.809-28.407 8.653-6.771-0.788-9.972-1.582-12.418-3.006-3.216-2.008-7.607-4.357-9.738-6.798z"/>
+ <linearGradient id="ab" x1="128.76" gradientUnits="userSpaceOnUse" x2="195.099" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.356" y2="259.356">
+ <stop stop-color="#C68C00" offset="0"/>
+ <stop stop-color="#9B6800" offset=".415"/>
+ <stop stop-color="#9B6800" offset="1"/>
+ </linearGradient>
+ <path fill="url(#ab)" d="m137.16 109.036c1.318 0.176 3.779 2.077 6.701 4.04 4.333 3.323 10.695 4.613 15.284 4.917 10.957 1.274 29.805-8.898 33.36-11.733 4.158-3.03 8.912-6.86 10.807-7.208 0.894 1.292-1.528 1.471-4.899 4.284-3.666 2.43-5.558 3.968-10.562 6.796-5.72 2.993-16.077 8.81-28.396 8.702-6.791-0.773-10.256-1.628-12.568-2.999-3.285-2.031-7.583-4.336-9.727-6.799z"/>
+ <linearGradient id="ac" x1="128.712" gradientUnits="userSpaceOnUse" x2="195.062" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.358" y2="259.358">
+ <stop stop-color="#C28700" offset="0"/>
+ <stop stop-color="#936000" offset=".415"/>
+ <stop stop-color="#936000" offset="1"/>
+ </linearGradient>
+ <path fill="url(#ac)" d="m137.112 109.017c1.267 0.085 3.912 2.113 6.835 4.081 4.31 3.289 10.527 4.613 15.158 4.93 11.09 1.258 30.118-9.032 33.445-11.782 4.225-3.072 8.877-6.807 10.739-7.174 0.855 1.278-1.595 1.446-5 4.323-3.647 2.404-5.427 3.877-10.36 6.663-5.673 2.969-16.077 8.812-28.384 8.753-6.811-0.759-10.54-1.675-12.719-2.992-3.353-2.055-7.559-4.315-9.714-6.802z"/>
+ <linearGradient id="ad" x1="128.663" gradientUnits="userSpaceOnUse" x2="195.025" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.36" y2="259.36">
+ <stop stop-color="#BD8200" offset="0"/>
+ <stop stop-color="#8C5900" offset=".415"/>
+ <stop stop-color="#8C5900" offset="1"/>
+ </linearGradient>
+ <path fill="url(#ad)" d="m137.063 108.998c1.217-0.006 4.047 2.15 6.97 4.122 4.286 3.254 10.359 4.612 15.032 4.943 11.223 1.243 30.431-9.166 33.53-11.83 4.289-3.116 8.84-6.753 10.673-7.141 0.815 1.263-1.661 1.421-5.101 4.362-3.63 2.377-5.298 3.785-10.161 6.531-5.624 2.944-16.075 8.813-28.37 8.802-6.83-0.744-10.824-1.721-12.87-2.985-3.422-2.077-7.535-4.294-9.703-6.804z"/>
+ <linearGradient id="ae" x1="128.615" gradientUnits="userSpaceOnUse" x2="194.989" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.362" y2="259.362">
+ <stop stop-color="#B97D00" offset="0"/>
+ <stop stop-color="#845100" offset=".415"/>
+ <stop stop-color="#845100" offset="1"/>
+ </linearGradient>
+ <path fill="url(#ae)" d="m137.015 108.98c1.166-0.098 4.181 2.185 7.104 4.162 4.262 3.22 10.19 4.612 14.906 4.955 11.354 1.229 30.743-9.299 33.613-11.877 4.356-3.16 8.804-6.7 10.607-7.108 0.776 1.248-1.728 1.397-5.202 4.401-3.61 2.35-5.167 3.694-9.96 6.399-5.576 2.919-16.076 8.814-28.358 8.852-6.85-0.73-11.108-1.768-13.021-2.979-3.489-2.1-7.51-4.273-9.689-6.805z"/>
+ <linearGradient id="af" x1="128.567" gradientUnits="userSpaceOnUse" x2="194.954" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.364" y2="259.364">
+ <stop stop-color="#B57800" offset="0"/>
+ <stop stop-color="#7C4900" offset=".415"/>
+ <stop stop-color="#7C4900" offset="1"/>
+ </linearGradient>
+ <path fill="url(#af)" d="m136.967 108.961c1.115-0.189 4.315 2.222 7.239 4.203 4.239 3.186 10.021 4.612 14.78 4.968 11.488 1.214 31.057-9.433 33.697-11.925 4.424-3.203 8.768-6.647 10.542-7.075 0.736 1.233-1.795 1.372-5.303 4.44-3.593 2.323-5.038 3.603-9.759 6.266-5.529 2.895-16.077 8.816-28.348 8.903-6.868-0.716-11.392-1.815-13.172-2.972-3.557-2.124-7.485-4.252-9.676-6.808z"/>
+ <linearGradient id="ah" x1="128.518" gradientUnits="userSpaceOnUse" x2="194.918" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.366" y2="259.366">
+ <stop stop-color="#B07300" offset="0"/>
+ <stop stop-color="#754200" offset=".415"/>
+ <stop stop-color="#754200" offset="1"/>
+ </linearGradient>
+ <path fill="url(#ah)" d="m136.918 108.943c1.064-0.281 4.45 2.257 7.374 4.243 4.216 3.151 9.854 4.611 14.654 4.981 11.621 1.199 31.37-9.567 33.781-11.973 4.49-3.247 8.731-6.594 10.476-7.042 0.698 1.218-1.861 1.347-5.403 4.479-3.573 2.296-4.906 3.511-9.558 6.134-5.48 2.87-16.076 8.817-28.336 8.952-6.887-0.701-11.675-1.861-13.323-2.965-3.626-2.146-7.462-4.231-9.665-6.809z"/>
+ <linearGradient id="ai" x1="128.47" gradientUnits="userSpaceOnUse" x2="194.886" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.367" y2="259.367">
+ <stop stop-color="#AC6E00" offset="0"/>
+ <stop stop-color="#6D3A00" offset=".415"/>
+ <stop stop-color="#6D3A00" offset="1"/>
+ </linearGradient>
+ <path fill="url(#ai)" d="m136.87 108.924c1.013-0.372 4.584 2.294 7.509 4.284 4.191 3.117 9.685 4.611 14.528 4.994 11.753 1.184 31.682-9.701 33.864-12.021 4.557-3.291 8.695-6.542 10.411-7.009 0.657 1.203-1.929 1.322-5.504 4.518-3.557 2.269-4.777 3.42-9.358 6.002-5.434 2.845-16.076 8.818-28.324 9.002-6.907-0.687-11.959-1.908-13.474-2.959-3.694-2.169-7.437-4.21-9.652-6.811z"/>
+ <linearGradient id="aj" x1="128.421" gradientUnits="userSpaceOnUse" x2="194.85" gradientTransform="matrix(1,0,0,-1,8.3999,368.3)" y1="259.369" y2="259.369">
+ <stop stop-color="#A86A00" offset="0"/>
+ <stop stop-color="#663200" offset=".415"/>
+ <stop stop-color="#663200" offset="1"/>
+ </linearGradient>
+ <path fill="url(#aj)" d="m136.821 108.905c0.963-0.464 4.719 2.33 7.644 4.324 4.168 3.083 9.517 4.611 14.402 5.007 11.886 1.169 31.995-9.834 33.948-12.069 4.624-3.334 8.66-6.487 10.345-6.976 0.619 1.188-1.995 1.298-5.604 4.558-3.537 2.242-4.647 3.328-9.157 5.869-5.386 2.82-16.076 8.82-28.313 9.052-6.926-0.673-12.243-1.954-13.625-2.952-3.762-2.192-7.413-4.189-9.64-6.813z"/>
+ </g>
+ </g>
+</svg>
diff --git a/tests/phpunit/data/resourceloader/add.gif b/tests/phpunit/data/resourceloader/add.gif
new file mode 100644
index 00000000..5f454ca1
--- /dev/null
+++ b/tests/phpunit/data/resourceloader/add.gif
Binary files differ
diff --git a/tests/phpunit/data/resourceloader/bold-a.svg b/tests/phpunit/data/resourceloader/bold-a.svg
new file mode 100644
index 00000000..4b828779
--- /dev/null
+++ b/tests/phpunit/data/resourceloader/bold-a.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-a">
+ <path d="M16 18h3l-5-12h-3l-5 12h3l1.25-3h4.5l1.25 3zm-4.917-5l1.417-3.4 1.417 3.4h-2.834z"/>
+ </g>
+</svg>
diff --git a/tests/phpunit/data/resourceloader/bold-b.svg b/tests/phpunit/data/resourceloader/bold-b.svg
new file mode 100644
index 00000000..4f648203
--- /dev/null
+++ b/tests/phpunit/data/resourceloader/bold-b.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-b">
+ <path id="b" d="M7 18h6c2 0 4-1 4-3 0-1.064.011-1.975-1.989-3 2-.975 1.989-1.935 1.989-3 0-2-2-3-4-3h-6v12zm7-8c0 1.001 0 1-2 1h-2v-3h2c2 0 2 0 2 1v1zm-2 6h-2v-3h2c2 0 2 0 2 1v1s0 1-2 1z"/>
+ </g>
+</svg>
diff --git a/tests/phpunit/data/resourceloader/bold-f.svg b/tests/phpunit/data/resourceloader/bold-f.svg
new file mode 100644
index 00000000..357d2e5d
--- /dev/null
+++ b/tests/phpunit/data/resourceloader/bold-f.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-f">
+ <path id="f" d="M16 8v-2h-8v12h3v-5h4v-2h-4v-3z"/>
+ </g>
+</svg>
diff --git a/tests/phpunit/data/resourceloader/help-ltr.svg b/tests/phpunit/data/resourceloader/help-ltr.svg
new file mode 100644
index 00000000..bb2545c5
--- /dev/null
+++ b/tests/phpunit/data/resourceloader/help-ltr.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="help">
+ <path id="circle" d="M12.001 2.085c-5.478 0-9.916 4.438-9.916 9.916 0 5.476 4.438 9.914 9.916 9.914 5.476 0 9.914-4.438 9.914-9.914 0-5.478-4.438-9.916-9.914-9.916zm.001 18c-4.465 0-8.084-3.619-8.084-8.083 0-4.465 3.619-8.084 8.084-8.084 4.464 0 8.083 3.619 8.083 8.084 0 4.464-3.619 8.083-8.083 8.083z"/>
+ <g id="question-mark">
+ <path id="top" d="M11.766 6.688c-2.5 0-3.219 2.188-3.219 2.188l1.411.854s.298-.791.901-1.229c.516-.375 1.625-.625 2.219.125.701.885-.17 1.587-1.078 2.719-.953 1.186-1 3.655-1 3.655h1.969s.135-2.318 1.041-3.381c.603-.707 1.443-1.338 1.443-2.494s-1.187-2.437-3.687-2.437z"/>
+ <path id="bottom" d="M11 16h2v2h-2z"/>
+ </g>
+ </g>
+</svg>
diff --git a/tests/phpunit/data/resourceloader/help-rtl.svg b/tests/phpunit/data/resourceloader/help-rtl.svg
new file mode 100644
index 00000000..255ae95b
--- /dev/null
+++ b/tests/phpunit/data/resourceloader/help-rtl.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="help">
+ <path id="circle" d="M12.001 2.085c-5.478 0-9.916 4.438-9.916 9.916 0 5.476 4.438 9.914 9.916 9.914 5.476 0 9.914-4.438 9.914-9.914 0-5.478-4.438-9.916-9.914-9.916zm.001 18c-4.465 0-8.084-3.619-8.084-8.083 0-4.465 3.619-8.084 8.084-8.084 4.464 0 8.083 3.619 8.083 8.084 0 4.464-3.619 8.083-8.083 8.083z"/>
+ <g id="question-mark" transform="translate(24, 0) scale(-1, 1)">
+ <path id="top" d="M11.766 6.688c-2.5 0-3.219 2.188-3.219 2.188l1.411.854s.298-.791.901-1.229c.516-.375 1.625-.625 2.219.125.701.885-.17 1.587-1.078 2.719-.953 1.186-1 3.655-1 3.655h1.969s.135-2.318 1.041-3.381c.603-.707 1.443-1.338 1.443-2.494s-1.187-2.437-3.687-2.437z"/>
+ <path id="bottom" d="M11 16h2v2h-2z"/>
+ </g>
+ </g>
+</svg>
diff --git a/tests/phpunit/data/resourceloader/next.svg b/tests/phpunit/data/resourceloader/next.svg
new file mode 100644
index 00000000..02b4e387
--- /dev/null
+++ b/tests/phpunit/data/resourceloader/next.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16.5 13.1l-8.9 8.9c-.8-.8-.8-2 0-2.8l6.1-6.1-6-6.1c-.8-.8-.8-2 0-2.8l8.8 8.9z" id="path108"/>
+</svg>
diff --git a/tests/phpunit/data/resourceloader/next_massage.svg b/tests/phpunit/data/resourceloader/next_massage.svg
new file mode 100644
index 00000000..bbd1a8d6
--- /dev/null
+++ b/tests/phpunit/data/resourceloader/next_massage.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M 16.5 13.1 l -8.9 8.9 c -0.8 -0.8 -0.8 -2 0 -2.8 l 6.1 -6.1 -6 -6.1 c -0.8 -0.8 -0.8 -2 0 -2.8 l 8.8 8.9 z" id="path108"/>
+</svg>
diff --git a/tests/phpunit/data/resourceloader/prev.svg b/tests/phpunit/data/resourceloader/prev.svg
new file mode 100644
index 00000000..f31ec095
--- /dev/null
+++ b/tests/phpunit/data/resourceloader/prev.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 13.1l8.9 8.9c.8-.8.8-2 0-2.8l-6.1-6.1 6-6.1c.8-.8.8-2 0-2.8l-8.8 8.9z"/>
+</svg>
diff --git a/tests/phpunit/data/resourceloader/remove.svg b/tests/phpunit/data/resourceloader/remove.svg
new file mode 100644
index 00000000..6ad79174
--- /dev/null
+++ b/tests/phpunit/data/resourceloader/remove.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="remove">
+ <path id="trash-can" d="M12 10h-1v6h1v-6zm-2 0h-1v6h1v-6zm4 0h-1v6h1v-6zm0-4v-1h-5v1h-3v3h1v7.966l1 1.031v-.074.077h6.984l.016-.018v.015l1-1.031v-7.966h1v-3h-3zm1 11h-7v-8h7v8zm1-9h-9v-1h9v1z"/>
+ </g>
+</svg>
diff --git a/tests/phpunit/data/resourceloader/remove_variantize.svg b/tests/phpunit/data/resourceloader/remove_variantize.svg
new file mode 100644
index 00000000..bcbe8712
--- /dev/null
+++ b/tests/phpunit/data/resourceloader/remove_variantize.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="red">
+ <g xmlns:default="http://www.w3.org/2000/svg" id="remove">
+ <path id="trash-can" d="M12 10h-1v6h1v-6zm-2 0h-1v6h1v-6zm4 0h-1v6h1v-6zm0-4v-1h-5v1h-3v3h1v7.966l1 1.031v-.074.077h6.984l.016-.018v.015l1-1.031v-7.966h1v-3h-3zm1 11h-7v-8h7v8zm1-9h-9v-1h9v1z"/>
+ </g>
+</g></svg>
diff --git a/tests/phpunit/data/templates/foobar.mustache b/tests/phpunit/data/templates/foobar.mustache
new file mode 100644
index 00000000..a0423896
--- /dev/null
+++ b/tests/phpunit/data/templates/foobar.mustache
@@ -0,0 +1 @@
+hello world!
diff --git a/tests/phpunit/data/templates/foobar_args.mustache b/tests/phpunit/data/templates/foobar_args.mustache
new file mode 100644
index 00000000..cfbe3d0f
--- /dev/null
+++ b/tests/phpunit/data/templates/foobar_args.mustache
@@ -0,0 +1 @@
+hello {{planet}}!
diff --git a/tests/phpunit/includes/BlockTest.php b/tests/phpunit/includes/BlockTest.php
index b248d24e..19741621 100644
--- a/tests/phpunit/includes/BlockTest.php
+++ b/tests/phpunit/includes/BlockTest.php
@@ -133,6 +133,7 @@ class BlockTest extends MediaWikiLangTestCase {
$username = 'BlockedUserToCreateAccountWith';
$u = User::newFromName( $username );
$u->setPassword( 'NotRandomPass' );
+ $u->setId( 14146 );
$u->addToDatabase();
unset( $u );
@@ -200,6 +201,12 @@ class BlockTest extends MediaWikiLangTestCase {
$oldBlock->delete();
}
+ // Local perspective (blockee on current wiki)...
+ $user = User::newFromName( 'UserOnForeignWiki' );
+ $user->addToDatabase();
+ // Set user ID to match the test value
+ $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',
@@ -221,11 +228,6 @@ class BlockTest extends MediaWikiLangTestCase {
$res = $block->insert( $this->db );
$this->assertTrue( (bool)$res['id'], 'Block succeeded' );
- // Local perspective (blockee on current wiki)...
- $user = User::newFromName( 'UserOnForeignWiki' );
- $user->addToDatabase();
- // Set user ID to match the test value
- $this->db->update( 'user', array( 'user_id' => 14146 ), array( 'user_id' => $user->getId() ) );
$user = null; // clear
$block = Block::newFromID( $res['id'] );
diff --git a/tests/phpunit/includes/EditPageTest.php b/tests/phpunit/includes/EditPageTest.php
index 702fce4c..15778e40 100644
--- a/tests/phpunit/includes/EditPageTest.php
+++ b/tests/phpunit/includes/EditPageTest.php
@@ -217,7 +217,8 @@ class EditPageTest extends MediaWikiLangTestCase {
EditPage::AS_SUCCESS_NEW_ARTICLE,
''
),
- array( 'expected registered MediaWiki: page whose default content is empty not being created if empty',
+ array( 'expected registered MediaWiki: page whose default content is empty'
+ . ' not being created if empty',
'MediaWiki:Ipb-default-expiry',
'UTSysop',
'',
@@ -246,7 +247,9 @@ class EditPageTest extends MediaWikiLangTestCase {
* @dataProvider provideCreatePages
* @covers EditPage
*/
- public function testCreatePage( $desc, $pageTitle, $user, $editText, $expectedCode, $expectedText, $ignoreBlank = false ) {
+ public function testCreatePage(
+ $desc, $pageTitle, $user, $editText, $expectedCode, $expectedText, $ignoreBlank = false
+ ) {
$edit = array( 'wpTextbox1' => $editText );
if ( $ignoreBlank ) {
$edit['wpIgnoreBlankArticle'] = 1;
diff --git a/tests/phpunit/includes/GitInfoTest.php b/tests/phpunit/includes/GitInfoTest.php
index e22f5050..c3539d0e 100644
--- a/tests/phpunit/includes/GitInfoTest.php
+++ b/tests/phpunit/includes/GitInfoTest.php
@@ -10,7 +10,7 @@ class GitInfoTest extends MediaWikiTestCase {
}
public function testValidJsonData() {
- $dir = $GLOBALS['IP'] . '/testValidJsonData';
+ $dir = $GLOBALS['IP'] . DIRECTORY_SEPARATOR . 'testValidJsonData';
$fixture = new GitInfo( $dir );
$this->assertTrue( $fixture->cacheIsComplete() );
diff --git a/tests/phpunit/includes/GlobalFunctions/GlobalTest.php b/tests/phpunit/includes/GlobalFunctions/GlobalTest.php
index 3acc48e2..1e30273e 100644
--- a/tests/phpunit/includes/GlobalFunctions/GlobalTest.php
+++ b/tests/phpunit/includes/GlobalFunctions/GlobalTest.php
@@ -7,7 +7,7 @@ class GlobalTest extends MediaWikiTestCase {
protected function setUp() {
parent::setUp();
- $readOnlyFile = tempnam( wfTempDir(), "mwtest_readonly" );
+ $readOnlyFile = $this->getNewTempFile();
unlink( $readOnlyFile );
$this->setMwGlobals( array(
@@ -22,16 +22,6 @@ class GlobalTest extends MediaWikiTestCase {
) );
}
- protected function tearDown() {
- global $wgReadOnlyFile;
-
- if ( file_exists( $wgReadOnlyFile ) ) {
- unlink( $wgReadOnlyFile );
- }
-
- parent::tearDown();
- }
-
/**
* @dataProvider provideForWfArrayDiff2
* @covers ::wfArrayDiff2
@@ -312,46 +302,42 @@ class GlobalTest extends MediaWikiTestCase {
* @covers ::wfDebugMem
*/
public function testDebugFunctionTest() {
+ $debugLogFile = $this->getNewTempFile();
- global $wgDebugLogFile, $wgDebugTimestamps;
-
- $old_log_file = $wgDebugLogFile;
- $wgDebugLogFile = tempnam( wfTempDir(), 'mw-' );
- # @todo FIXME: $wgDebugTimestamps should be tested
- $old_wgDebugTimestamps = $wgDebugTimestamps;
- $wgDebugTimestamps = false;
+ $this->setMwGlobals( array(
+ 'wgDebugLogFile' => $debugLogFile,
+ # @todo FIXME: $wgDebugTimestamps should be tested
+ 'wgDebugTimestamps' => false
+ ) );
wfDebug( "This is a normal string" );
- $this->assertEquals( "This is a normal string", file_get_contents( $wgDebugLogFile ) );
- unlink( $wgDebugLogFile );
+ $this->assertEquals( "This is a normal string\n", file_get_contents( $debugLogFile ) );
+ unlink( $debugLogFile );
wfDebug( "This is nöt an ASCII string" );
- $this->assertEquals( "This is nöt an ASCII string", file_get_contents( $wgDebugLogFile ) );
- unlink( $wgDebugLogFile );
+ $this->assertEquals( "This is nöt an ASCII string\n", file_get_contents( $debugLogFile ) );
+ unlink( $debugLogFile );
wfDebug( "\00305This has böth UTF and control chars\003" );
$this->assertEquals(
- " 05This has böth UTF and control chars ",
- file_get_contents( $wgDebugLogFile )
+ " 05This has böth UTF and control chars \n",
+ file_get_contents( $debugLogFile )
);
- unlink( $wgDebugLogFile );
+ unlink( $debugLogFile );
wfDebugMem();
$this->assertGreaterThan(
1000,
- preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) )
+ preg_replace( '/\D/', '', file_get_contents( $debugLogFile ) )
);
- unlink( $wgDebugLogFile );
+ unlink( $debugLogFile );
wfDebugMem( true );
$this->assertGreaterThan(
1000000,
- preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) )
+ preg_replace( '/\D/', '', file_get_contents( $debugLogFile ) )
);
- unlink( $wgDebugLogFile );
-
- $wgDebugLogFile = $old_log_file;
- $wgDebugTimestamps = $old_wgDebugTimestamps;
+ unlink( $debugLogFile );
}
/**
@@ -389,24 +375,6 @@ class GlobalTest extends MediaWikiTestCase {
}
/**
- * @covers ::swap
- */
- public function testSwapVarsTest() {
- $this->hideDeprecated( 'swap' );
-
- $var1 = 1;
- $var2 = 2;
-
- $this->assertEquals( $var1, 1, 'var1 is set originally' );
- $this->assertEquals( $var2, 2, 'var1 is set originally' );
-
- swap( $var1, $var2 );
-
- $this->assertEquals( $var1, 2, 'var1 is swapped' );
- $this->assertEquals( $var2, 1, 'var2 is swapped' );
- }
-
- /**
* @covers ::wfPercent
*/
public function testWfPercentTest() {
@@ -705,21 +673,21 @@ class GlobalTest extends MediaWikiTestCase {
}
/**
- * @dataProvider provideWfShellMaintenanceCmdList
- * @covers ::wfShellMaintenanceCmd
+ * @dataProvider provideWfShellWikiCmdList
+ * @covers ::wfShellWikiCmd
*/
- public function testWfShellMaintenanceCmd( $script, $parameters, $options,
+ public function testWfShellWikiCmd( $script, $parameters, $options,
$expected, $description
) {
if ( wfIsWindows() ) {
// Approximation that's good enough for our purposes just now
$expected = str_replace( "'", '"', $expected );
}
- $actual = wfShellMaintenanceCmd( $script, $parameters, $options );
+ $actual = wfShellWikiCmd( $script, $parameters, $options );
$this->assertEquals( $expected, $actual, $description );
}
- public static function provideWfShellMaintenanceCmdList() {
+ public static function provideWfShellWikiCmdList() {
global $wgPhpCli;
return array(
diff --git a/tests/phpunit/includes/GlobalFunctions/wfAppendQueryTest.php b/tests/phpunit/includes/GlobalFunctions/wfAppendQueryTest.php
new file mode 100644
index 00000000..54e1f896
--- /dev/null
+++ b/tests/phpunit/includes/GlobalFunctions/wfAppendQueryTest.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @group GlobalFunctions
+ * @covers ::wfAppendQuery
+ */
+class WfAppendQueryTest extends MediaWikiTestCase {
+ /**
+ * @dataProvider provideAppendQuery
+ */
+ public function testAppendQuery( $url, $query, $expected, $message = null ) {
+ $this->assertEquals( $expected, wfAppendQuery( $url, $query ), $message );
+ }
+
+ public static function provideAppendQuery() {
+ return array(
+ array(
+ 'http://www.example.org/index.php',
+ '',
+ 'http://www.example.org/index.php',
+ 'No query'
+ ),
+ array(
+ 'http://www.example.org/index.php',
+ array( 'foo' => 'bar' ),
+ 'http://www.example.org/index.php?foo=bar',
+ 'Set query array'
+ ),
+ array(
+ 'http://www.example.org/index.php?foz=baz',
+ 'foo=bar',
+ 'http://www.example.org/index.php?foz=baz&foo=bar',
+ 'Set query string'
+ ),
+ array(
+ 'http://www.example.org/index.php?foo=bar',
+ '',
+ 'http://www.example.org/index.php?foo=bar',
+ 'Empty string with query'
+ ),
+ array(
+ 'http://www.example.org/index.php?foo=bar',
+ array( 'baz' => 'quux' ),
+ 'http://www.example.org/index.php?foo=bar&baz=quux',
+ 'Add query array'
+ ),
+ array(
+ 'http://www.example.org/index.php?foo=bar',
+ 'baz=quux',
+ 'http://www.example.org/index.php?foo=bar&baz=quux',
+ 'Add query string'
+ ),
+ array(
+ 'http://www.example.org/index.php?foo=bar',
+ array( 'baz' => 'quux', 'foo' => 'baz' ),
+ 'http://www.example.org/index.php?foo=bar&baz=quux&foo=baz',
+ 'Modify query array'
+ ),
+ array(
+ 'http://www.example.org/index.php?foo=bar',
+ 'baz=quux&foo=baz',
+ 'http://www.example.org/index.php?foo=bar&baz=quux&foo=baz',
+ 'Modify query string'
+ )
+ );
+ }
+}
diff --git a/tests/phpunit/includes/GlobalFunctions/wfEscapeShellArgTest.php b/tests/phpunit/includes/GlobalFunctions/wfEscapeShellArgTest.php
new file mode 100644
index 00000000..cb334d2f
--- /dev/null
+++ b/tests/phpunit/includes/GlobalFunctions/wfEscapeShellArgTest.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @group GlobalFunctions
+ * @covers ::wfEscapeShellArg
+ */
+class wfEscapeShellArgTest extends MediaWikiTestCase {
+ public function testSingleInput() {
+ if ( wfIsWindows() ) {
+ $expected = '"blah"';
+ } else {
+ $expected = "'blah'";
+ }
+
+ $actual = wfEscapeShellArg( 'blah' );
+
+ $this->assertEquals( $expected, $actual );
+ }
+
+ public function testMultipleArgs() {
+ if ( wfIsWindows() ) {
+ $expected = '"foo" "bar" "baz"';
+ } else {
+ $expected = "'foo' 'bar' 'baz'";
+ }
+
+ $actual = wfEscapeShellArg( 'foo', 'bar', 'baz' );
+
+ $this->assertEquals( $expected, $actual );
+ }
+
+ public function testMultipleArgsAsArray() {
+ if ( wfIsWindows() ) {
+ $expected = '"foo" "bar" "baz"';
+ } else {
+ $expected = "'foo' 'bar' 'baz'";
+ }
+
+ $actual = wfEscapeShellArg( array( 'foo', 'bar', 'baz' ) );
+
+ $this->assertEquals( $expected, $actual );
+ }
+}
diff --git a/tests/phpunit/includes/GlobalFunctions/wfThumbIsStandardTest.php b/tests/phpunit/includes/GlobalFunctions/wfThumbIsStandardTest.php
new file mode 100644
index 00000000..448250a6
--- /dev/null
+++ b/tests/phpunit/includes/GlobalFunctions/wfThumbIsStandardTest.php
@@ -0,0 +1,104 @@
+<?php
+
+/**
+ * @group GlobalFunctions
+ * @covers ::wfThumbIsStandard
+ */
+class WfThumbIsStandardTest extends MediaWikiTestCase {
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->setMwGlobals( array(
+ 'wgThumbLimits' => array(
+ 100,
+ 401
+ ),
+ 'wgImageLimits' => array(
+ array( 300, 225 ),
+ array( 800, 600 ),
+ ),
+ 'wgMediaHandlers' => array(
+ 'unknown/unknown' => 'MockBitmapHandler',
+ ),
+ ) );
+ }
+
+ public static function provideThumbParams() {
+ return array(
+ // Thumb limits
+ array(
+ 'Standard thumb width',
+ true,
+ array( 'width' => 100 ),
+ ),
+ array(
+ 'Standard thumb width',
+ true,
+ array( 'width' => 401 ),
+ ),
+ // wfThumbIsStandard should match Linker::processResponsiveImages
+ // in its rounding behaviour.
+ array(
+ 'Standard thumb width (HiDPI 1.5x) - incorrect rounding',
+ false,
+ array( 'width' => 601 ),
+ ),
+ array(
+ 'Standard thumb width (HiDPI 1.5x)',
+ true,
+ array( 'width' => 602 ),
+ ),
+ array(
+ 'Standard thumb width (HiDPI 2x)',
+ true,
+ array( 'width' => 802 ),
+ ),
+ array(
+ 'Non-standard thumb width',
+ false,
+ array( 'width' => 300 ),
+ ),
+ // Image limits
+ // Note: Image limits are measured as pairs. Individual values
+ // may be non-standard based on the aspect ratio.
+ array(
+ 'Standard image width/height pair',
+ true,
+ array( 'width' => 250, 'height' => 225 ),
+ ),
+ array(
+ 'Standard image width/height pair',
+ true,
+ array( 'width' => 667, 'height' => 600 ),
+ ),
+ array(
+ 'Standard image width where image does not fit aspect ratio',
+ false,
+ array( 'width' => 300 ),
+ ),
+ array(
+ 'Implicit width from image width/height pair aspect ratio fit',
+ true,
+ // 2000x1800 fit inside 300x225 makes w=250
+ array( 'width' => 250 ),
+ ),
+ array(
+ 'Height-only is always non-standard',
+ false,
+ array( 'height' => 225 ),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider provideThumbParams
+ */
+ public function testIsStandard( $message, $expected, $params ) {
+ $this->assertSame(
+ $expected,
+ wfThumbIsStandard( new FakeDimensionFile( array( 2000, 1800 ) ), $params ),
+ $message
+ );
+ }
+}
diff --git a/tests/phpunit/includes/HtmlFormatterTest.php b/tests/phpunit/includes/HtmlFormatterTest.php
index 9dbfa452..1c3e8539 100644
--- a/tests/phpunit/includes/HtmlFormatterTest.php
+++ b/tests/phpunit/includes/HtmlFormatterTest.php
@@ -4,6 +4,20 @@
* @group HtmlFormatter
*/
class HtmlFormatterTest extends MediaWikiTestCase {
+
+ /**
+ * Use TidySupport to check whether we should use $wgTidyInternal.
+ *
+ * The Tidy extension in HHVM does not support error text return, so it is
+ * nominally usable, but does not pass tests which require error text from
+ * Tidy.
+ */
+ protected function setUp() {
+ parent::setUp();
+ $tidySupport = new TidySupport();
+ $this->setMwGlobals( 'wgTidyInternal', $tidySupport->isInternal() );
+ }
+
/**
* @dataProvider getHtmlData
*
diff --git a/tests/phpunit/includes/HtmlTest.php b/tests/phpunit/includes/HtmlTest.php
index a8829cd8..c5797c4f 100644
--- a/tests/phpunit/includes/HtmlTest.php
+++ b/tests/phpunit/includes/HtmlTest.php
@@ -637,7 +637,7 @@ class HtmlTest extends MediaWikiTestCase {
. 'Depending on compatibility mode IE might use "button", instead.',
);
- # <select> specifc handling
+ # <select> specific handling
$cases[] = array( '<select multiple></select>',
'select', array( 'size' => '4', 'multiple' => true ),
);
@@ -715,7 +715,7 @@ class HtmlTest extends MediaWikiTestCase {
'Input wrapper with type and value.'
);
$this->assertEquals(
- '<input name=testname class=mw-ui-input>',
+ '<input name=testname>',
Html::input( 'testname' ),
'Input wrapper with all default values.'
);
@@ -764,6 +764,30 @@ class HtmlTest extends MediaWikiTestCase {
'Label wrapper'
);
}
+
+ public static function provideSrcSetImages() {
+ return array(
+ array( array(), '', 'when there are no images, return empty string' ),
+ array(
+ array( '1x' => '1x.png', '1.5x' => '1_5x.png', '2x' => '2x.png' ),
+ '1x.png 1x, 1_5x.png 1.5x, 2x.png 2x',
+ 'pixel depth keys may include a trailing "x"'
+ ),
+ array(
+ array( '1' => '1x.png', '1.5' => '1_5x.png', '2' => '2x.png' ),
+ '1x.png 1x, 1_5x.png 1.5x, 2x.png 2x',
+ 'pixel depth keys may omit a trailing "x"'
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider provideSrcSetImages
+ * @covers Html::srcSet
+ */
+ public function testSrcSet( $images, $expected, $message ) {
+ $this->assertEquals( Html::srcSet( $images ), $expected, $message );
+ }
}
class HtmlTestValue {
diff --git a/tests/phpunit/includes/HttpTest.php b/tests/phpunit/includes/HttpTest.php
index 9b53381e..8a0dff78 100644
--- a/tests/phpunit/includes/HttpTest.php
+++ b/tests/phpunit/includes/HttpTest.php
@@ -1,6 +1,7 @@
<?php
+
/**
- * @group Broken
+ * @group Http
*/
class HttpTest extends MediaWikiTestCase {
/**
@@ -92,8 +93,10 @@ class HttpTest extends MediaWikiTestCase {
array( true, 'http://user:pass@host', 'Username and password provided' ),
# (\S+) - host part is made of anything not whitespaces
- array( false, 'http://!"èèè¿¿¿~~\'', 'hostname is made of any non whitespace' ),
- array( false, 'http://exam:ple.org/', 'hostname can not use colons!' ),
+ // commented these out in order to remove @group Broken
+ // @todo are these valid tests? if so, fix Http::isValidURI so it can handle them
+ //array( false, 'http://!"èèè¿¿¿~~\'', 'hostname is made of any non whitespace' ),
+ //array( false, 'http://exam:ple.org/', 'hostname can not use colons!' ),
# (:[0-9]+)? - port number
array( true, 'http://example.org:80/' ),
@@ -135,7 +138,7 @@ class HttpTest extends MediaWikiTestCase {
* HTTP redirects).
*/
public function testRelativeRedirections() {
- $h = MWHttpRequestTester::factory( 'http://oldsite/file.ext' );
+ $h = MWHttpRequestTester::factory( 'http://oldsite/file.ext', array(), __METHOD__ );
# Forge a Location header
$h->setRespHeaders( 'location', array(
@@ -171,6 +174,310 @@ class HttpTest extends MediaWikiTestCase {
$h->getFinalUrl( "Relative file path Location: should keep the latest host and scheme!" )
);
}
+
+ /**
+ * Constant values are from PHP 5.3.28 using cURL 7.24.0
+ * @see http://php.net/manual/en/curl.constants.php
+ *
+ * All constant values are present so that developers don’t need to remember
+ * to add them if added at a later date. The commented out constants were
+ * not found anywhere in the MediaWiki core code.
+ *
+ * Commented out constants that were not available in:
+ * HipHop VM 3.3.0 (rel)
+ * Compiler: heads/master-0-g08810d920dfff59e0774cf2d651f92f13a637175
+ * Repo schema: 3214fc2c684a4520485f715ee45f33f2182324b1
+ * Extension API: 20140829
+ *
+ * Commented out constants that were removed in PHP 5.6.0
+ *
+ * @covers CurlHttpRequest::execute
+ */
+ public function provideCurlConstants() {
+ return array(
+ array( 'CURLAUTH_ANY' ),
+ array( 'CURLAUTH_ANYSAFE' ),
+ array( 'CURLAUTH_BASIC' ),
+ array( 'CURLAUTH_DIGEST' ),
+ array( 'CURLAUTH_GSSNEGOTIATE' ),
+ array( 'CURLAUTH_NTLM' ),
+ // array( 'CURLCLOSEPOLICY_CALLBACK' ), // removed in PHP 5.6.0
+ // array( 'CURLCLOSEPOLICY_LEAST_RECENTLY_USED' ), // removed in PHP 5.6.0
+ // array( 'CURLCLOSEPOLICY_LEAST_TRAFFIC' ), // removed in PHP 5.6.0
+ // array( 'CURLCLOSEPOLICY_OLDEST' ), // removed in PHP 5.6.0
+ // array( 'CURLCLOSEPOLICY_SLOWEST' ), // removed in PHP 5.6.0
+ array( 'CURLE_ABORTED_BY_CALLBACK' ),
+ array( 'CURLE_BAD_CALLING_ORDER' ),
+ array( 'CURLE_BAD_CONTENT_ENCODING' ),
+ array( 'CURLE_BAD_FUNCTION_ARGUMENT' ),
+ array( 'CURLE_BAD_PASSWORD_ENTERED' ),
+ array( 'CURLE_COULDNT_CONNECT' ),
+ array( 'CURLE_COULDNT_RESOLVE_HOST' ),
+ array( 'CURLE_COULDNT_RESOLVE_PROXY' ),
+ array( 'CURLE_FAILED_INIT' ),
+ array( 'CURLE_FILESIZE_EXCEEDED' ),
+ array( 'CURLE_FILE_COULDNT_READ_FILE' ),
+ array( 'CURLE_FTP_ACCESS_DENIED' ),
+ array( 'CURLE_FTP_BAD_DOWNLOAD_RESUME' ),
+ array( 'CURLE_FTP_CANT_GET_HOST' ),
+ array( 'CURLE_FTP_CANT_RECONNECT' ),
+ array( 'CURLE_FTP_COULDNT_GET_SIZE' ),
+ array( 'CURLE_FTP_COULDNT_RETR_FILE' ),
+ array( 'CURLE_FTP_COULDNT_SET_ASCII' ),
+ array( 'CURLE_FTP_COULDNT_SET_BINARY' ),
+ array( 'CURLE_FTP_COULDNT_STOR_FILE' ),
+ array( 'CURLE_FTP_COULDNT_USE_REST' ),
+ array( 'CURLE_FTP_PORT_FAILED' ),
+ array( 'CURLE_FTP_QUOTE_ERROR' ),
+ array( 'CURLE_FTP_SSL_FAILED' ),
+ array( 'CURLE_FTP_USER_PASSWORD_INCORRECT' ),
+ array( 'CURLE_FTP_WEIRD_227_FORMAT' ),
+ array( 'CURLE_FTP_WEIRD_PASS_REPLY' ),
+ array( 'CURLE_FTP_WEIRD_PASV_REPLY' ),
+ array( 'CURLE_FTP_WEIRD_SERVER_REPLY' ),
+ array( 'CURLE_FTP_WEIRD_USER_REPLY' ),
+ array( 'CURLE_FTP_WRITE_ERROR' ),
+ array( 'CURLE_FUNCTION_NOT_FOUND' ),
+ array( 'CURLE_GOT_NOTHING' ),
+ array( 'CURLE_HTTP_NOT_FOUND' ),
+ array( 'CURLE_HTTP_PORT_FAILED' ),
+ array( 'CURLE_HTTP_POST_ERROR' ),
+ array( 'CURLE_HTTP_RANGE_ERROR' ),
+ array( 'CURLE_LDAP_CANNOT_BIND' ),
+ array( 'CURLE_LDAP_INVALID_URL' ),
+ array( 'CURLE_LDAP_SEARCH_FAILED' ),
+ array( 'CURLE_LIBRARY_NOT_FOUND' ),
+ array( 'CURLE_MALFORMAT_USER' ),
+ array( 'CURLE_OBSOLETE' ),
+ array( 'CURLE_OK' ),
+ array( 'CURLE_OPERATION_TIMEOUTED' ),
+ array( 'CURLE_OUT_OF_MEMORY' ),
+ array( 'CURLE_PARTIAL_FILE' ),
+ array( 'CURLE_READ_ERROR' ),
+ array( 'CURLE_RECV_ERROR' ),
+ array( 'CURLE_SEND_ERROR' ),
+ array( 'CURLE_SHARE_IN_USE' ),
+ // array( 'CURLE_SSH' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLE_SSL_CACERT' ),
+ array( 'CURLE_SSL_CERTPROBLEM' ),
+ array( 'CURLE_SSL_CIPHER' ),
+ array( 'CURLE_SSL_CONNECT_ERROR' ),
+ array( 'CURLE_SSL_ENGINE_NOTFOUND' ),
+ array( 'CURLE_SSL_ENGINE_SETFAILED' ),
+ array( 'CURLE_SSL_PEER_CERTIFICATE' ),
+ array( 'CURLE_TELNET_OPTION_SYNTAX' ),
+ array( 'CURLE_TOO_MANY_REDIRECTS' ),
+ array( 'CURLE_UNKNOWN_TELNET_OPTION' ),
+ array( 'CURLE_UNSUPPORTED_PROTOCOL' ),
+ array( 'CURLE_URL_MALFORMAT' ),
+ array( 'CURLE_URL_MALFORMAT_USER' ),
+ array( 'CURLE_WRITE_ERROR' ),
+ array( 'CURLFTPAUTH_DEFAULT' ),
+ array( 'CURLFTPAUTH_SSL' ),
+ array( 'CURLFTPAUTH_TLS' ),
+ // array( 'CURLFTPMETHOD_MULTICWD' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLFTPMETHOD_NOCWD' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLFTPMETHOD_SINGLECWD' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLFTPSSL_ALL' ),
+ array( 'CURLFTPSSL_CONTROL' ),
+ array( 'CURLFTPSSL_NONE' ),
+ array( 'CURLFTPSSL_TRY' ),
+ // array( 'CURLINFO_CERTINFO' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLINFO_CONNECT_TIME' ),
+ array( 'CURLINFO_CONTENT_LENGTH_DOWNLOAD' ),
+ array( 'CURLINFO_CONTENT_LENGTH_UPLOAD' ),
+ array( 'CURLINFO_CONTENT_TYPE' ),
+ array( 'CURLINFO_EFFECTIVE_URL' ),
+ array( 'CURLINFO_FILETIME' ),
+ array( 'CURLINFO_HEADER_OUT' ),
+ array( 'CURLINFO_HEADER_SIZE' ),
+ array( 'CURLINFO_HTTP_CODE' ),
+ array( 'CURLINFO_NAMELOOKUP_TIME' ),
+ array( 'CURLINFO_PRETRANSFER_TIME' ),
+ array( 'CURLINFO_PRIVATE' ),
+ array( 'CURLINFO_REDIRECT_COUNT' ),
+ array( 'CURLINFO_REDIRECT_TIME' ),
+ // array( 'CURLINFO_REDIRECT_URL' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLINFO_REQUEST_SIZE' ),
+ array( 'CURLINFO_SIZE_DOWNLOAD' ),
+ array( 'CURLINFO_SIZE_UPLOAD' ),
+ array( 'CURLINFO_SPEED_DOWNLOAD' ),
+ array( 'CURLINFO_SPEED_UPLOAD' ),
+ array( 'CURLINFO_SSL_VERIFYRESULT' ),
+ array( 'CURLINFO_STARTTRANSFER_TIME' ),
+ array( 'CURLINFO_TOTAL_TIME' ),
+ array( 'CURLMSG_DONE' ),
+ array( 'CURLM_BAD_EASY_HANDLE' ),
+ array( 'CURLM_BAD_HANDLE' ),
+ array( 'CURLM_CALL_MULTI_PERFORM' ),
+ array( 'CURLM_INTERNAL_ERROR' ),
+ array( 'CURLM_OK' ),
+ array( 'CURLM_OUT_OF_MEMORY' ),
+ array( 'CURLOPT_AUTOREFERER' ),
+ array( 'CURLOPT_BINARYTRANSFER' ),
+ array( 'CURLOPT_BUFFERSIZE' ),
+ array( 'CURLOPT_CAINFO' ),
+ array( 'CURLOPT_CAPATH' ),
+ // array( 'CURLOPT_CERTINFO' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLOPT_CLOSEPOLICY' ), // removed in PHP 5.6.0
+ array( 'CURLOPT_CONNECTTIMEOUT' ),
+ array( 'CURLOPT_CONNECTTIMEOUT_MS' ),
+ array( 'CURLOPT_COOKIE' ),
+ array( 'CURLOPT_COOKIEFILE' ),
+ array( 'CURLOPT_COOKIEJAR' ),
+ array( 'CURLOPT_COOKIESESSION' ),
+ array( 'CURLOPT_CRLF' ),
+ array( 'CURLOPT_CUSTOMREQUEST' ),
+ array( 'CURLOPT_DNS_CACHE_TIMEOUT' ),
+ array( 'CURLOPT_DNS_USE_GLOBAL_CACHE' ),
+ array( 'CURLOPT_EGDSOCKET' ),
+ array( 'CURLOPT_ENCODING' ),
+ array( 'CURLOPT_FAILONERROR' ),
+ array( 'CURLOPT_FILE' ),
+ array( 'CURLOPT_FILETIME' ),
+ array( 'CURLOPT_FOLLOWLOCATION' ),
+ array( 'CURLOPT_FORBID_REUSE' ),
+ array( 'CURLOPT_FRESH_CONNECT' ),
+ array( 'CURLOPT_FTPAPPEND' ),
+ array( 'CURLOPT_FTPLISTONLY' ),
+ array( 'CURLOPT_FTPPORT' ),
+ array( 'CURLOPT_FTPSSLAUTH' ),
+ array( 'CURLOPT_FTP_CREATE_MISSING_DIRS' ),
+ // array( 'CURLOPT_FTP_FILEMETHOD' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLOPT_FTP_SKIP_PASV_IP' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLOPT_FTP_SSL' ),
+ array( 'CURLOPT_FTP_USE_EPRT' ),
+ array( 'CURLOPT_FTP_USE_EPSV' ),
+ array( 'CURLOPT_HEADER' ),
+ array( 'CURLOPT_HEADERFUNCTION' ),
+ array( 'CURLOPT_HTTP200ALIASES' ),
+ array( 'CURLOPT_HTTPAUTH' ),
+ array( 'CURLOPT_HTTPGET' ),
+ array( 'CURLOPT_HTTPHEADER' ),
+ array( 'CURLOPT_HTTPPROXYTUNNEL' ),
+ array( 'CURLOPT_HTTP_VERSION' ),
+ array( 'CURLOPT_INFILE' ),
+ array( 'CURLOPT_INFILESIZE' ),
+ array( 'CURLOPT_INTERFACE' ),
+ array( 'CURLOPT_IPRESOLVE' ),
+ // array( 'CURLOPT_KEYPASSWD' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLOPT_KRB4LEVEL' ),
+ array( 'CURLOPT_LOW_SPEED_LIMIT' ),
+ array( 'CURLOPT_LOW_SPEED_TIME' ),
+ array( 'CURLOPT_MAXCONNECTS' ),
+ array( 'CURLOPT_MAXREDIRS' ),
+ // array( 'CURLOPT_MAX_RECV_SPEED_LARGE' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLOPT_MAX_SEND_SPEED_LARGE' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLOPT_NETRC' ),
+ array( 'CURLOPT_NOBODY' ),
+ array( 'CURLOPT_NOPROGRESS' ),
+ array( 'CURLOPT_NOSIGNAL' ),
+ array( 'CURLOPT_PORT' ),
+ array( 'CURLOPT_POST' ),
+ array( 'CURLOPT_POSTFIELDS' ),
+ array( 'CURLOPT_POSTQUOTE' ),
+ array( 'CURLOPT_POSTREDIR' ),
+ array( 'CURLOPT_PRIVATE' ),
+ array( 'CURLOPT_PROGRESSFUNCTION' ),
+ // array( 'CURLOPT_PROTOCOLS' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLOPT_PROXY' ),
+ array( 'CURLOPT_PROXYAUTH' ),
+ array( 'CURLOPT_PROXYPORT' ),
+ array( 'CURLOPT_PROXYTYPE' ),
+ array( 'CURLOPT_PROXYUSERPWD' ),
+ array( 'CURLOPT_PUT' ),
+ array( 'CURLOPT_QUOTE' ),
+ array( 'CURLOPT_RANDOM_FILE' ),
+ array( 'CURLOPT_RANGE' ),
+ array( 'CURLOPT_READDATA' ),
+ array( 'CURLOPT_READFUNCTION' ),
+ // array( 'CURLOPT_REDIR_PROTOCOLS' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLOPT_REFERER' ),
+ array( 'CURLOPT_RESUME_FROM' ),
+ array( 'CURLOPT_RETURNTRANSFER' ),
+ // array( 'CURLOPT_SSH_AUTH_TYPES' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLOPT_SSH_HOST_PUBLIC_KEY_MD5' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLOPT_SSH_PRIVATE_KEYFILE' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLOPT_SSH_PUBLIC_KEYFILE' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLOPT_SSLCERT' ),
+ array( 'CURLOPT_SSLCERTPASSWD' ),
+ array( 'CURLOPT_SSLCERTTYPE' ),
+ array( 'CURLOPT_SSLENGINE' ),
+ array( 'CURLOPT_SSLENGINE_DEFAULT' ),
+ array( 'CURLOPT_SSLKEY' ),
+ array( 'CURLOPT_SSLKEYPASSWD' ),
+ array( 'CURLOPT_SSLKEYTYPE' ),
+ array( 'CURLOPT_SSLVERSION' ),
+ array( 'CURLOPT_SSL_CIPHER_LIST' ),
+ array( 'CURLOPT_SSL_VERIFYHOST' ),
+ array( 'CURLOPT_SSL_VERIFYPEER' ),
+ array( 'CURLOPT_STDERR' ),
+ array( 'CURLOPT_TCP_NODELAY' ),
+ array( 'CURLOPT_TIMECONDITION' ),
+ array( 'CURLOPT_TIMEOUT' ),
+ array( 'CURLOPT_TIMEOUT_MS' ),
+ array( 'CURLOPT_TIMEVALUE' ),
+ array( 'CURLOPT_TRANSFERTEXT' ),
+ array( 'CURLOPT_UNRESTRICTED_AUTH' ),
+ array( 'CURLOPT_UPLOAD' ),
+ array( 'CURLOPT_URL' ),
+ array( 'CURLOPT_USERAGENT' ),
+ array( 'CURLOPT_USERPWD' ),
+ array( 'CURLOPT_VERBOSE' ),
+ array( 'CURLOPT_WRITEFUNCTION' ),
+ array( 'CURLOPT_WRITEHEADER' ),
+ // array( 'CURLPROTO_ALL' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_DICT' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_FILE' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_FTP' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_FTPS' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_HTTP' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_HTTPS' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_LDAP' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_LDAPS' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_SCP' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_SFTP' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_TELNET' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLPROTO_TFTP' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLPROXY_HTTP' ),
+ // array( 'CURLPROXY_SOCKS4' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLPROXY_SOCKS5' ),
+ // array( 'CURLSSH_AUTH_DEFAULT' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLSSH_AUTH_HOST' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLSSH_AUTH_KEYBOARD' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLSSH_AUTH_NONE' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLSSH_AUTH_PASSWORD' ), // not present in HHVM 3.3.0-dev
+ // array( 'CURLSSH_AUTH_PUBLICKEY' ), // not present in HHVM 3.3.0-dev
+ array( 'CURLVERSION_NOW' ),
+ array( 'CURL_HTTP_VERSION_1_0' ),
+ array( 'CURL_HTTP_VERSION_1_1' ),
+ array( 'CURL_HTTP_VERSION_NONE' ),
+ array( 'CURL_IPRESOLVE_V4' ),
+ array( 'CURL_IPRESOLVE_V6' ),
+ array( 'CURL_IPRESOLVE_WHATEVER' ),
+ array( 'CURL_NETRC_IGNORED' ),
+ array( 'CURL_NETRC_OPTIONAL' ),
+ array( 'CURL_NETRC_REQUIRED' ),
+ array( 'CURL_TIMECOND_IFMODSINCE' ),
+ array( 'CURL_TIMECOND_IFUNMODSINCE' ),
+ array( 'CURL_TIMECOND_LASTMOD' ),
+ array( 'CURL_VERSION_IPV6' ),
+ array( 'CURL_VERSION_KERBEROS4' ),
+ array( 'CURL_VERSION_LIBZ' ),
+ array( 'CURL_VERSION_SSL' ),
+ );
+ }
+
+ /**
+ * Added this test based on an issue experienced with HHVM 3.3.0-dev
+ * where it did not define a cURL constant.
+ *
+ * @bug 70570
+ * @dataProvider provideCurlConstants
+ */
+ public function testCurlConstants( $value ) {
+ $this->assertTrue( defined( $value ), $value . ' not defined' );
+ }
}
/**
@@ -179,7 +486,7 @@ class HttpTest extends MediaWikiTestCase {
class MWHttpRequestTester extends MWHttpRequest {
// function derived from the MWHttpRequest factory function but
// returns appropriate tester class here
- public static function factory( $url, $options = null ) {
+ public static function factory( $url, $options = null, $caller = __METHOD__ ) {
if ( !Http::$httpEngine ) {
Http::$httpEngine = function_exists( 'curl_init' ) ? 'curl' : 'php';
} elseif ( Http::$httpEngine == 'curl' && !function_exists( 'curl_init' ) ) {
@@ -189,7 +496,7 @@ class MWHttpRequestTester extends MWHttpRequest {
switch ( Http::$httpEngine ) {
case 'curl':
- return new CurlHttpRequestTester( $url, $options );
+ return new CurlHttpRequestTester( $url, $options, $caller );
case 'php':
if ( !wfIniGetBool( 'allow_url_fopen' ) ) {
throw new MWException( __METHOD__ .
@@ -197,7 +504,7 @@ class MWHttpRequestTester extends MWHttpRequest {
. 'If possible, curl should be used instead. See http://php.net/curl.' );
}
- return new PhpHttpRequestTester( $url, $options );
+ return new PhpHttpRequestTester( $url, $options, $caller );
default:
}
}
diff --git a/tests/phpunit/includes/ImportTest.php b/tests/phpunit/includes/ImportTest.php
index 2fce6bfb..ea753e81 100644
--- a/tests/phpunit/includes/ImportTest.php
+++ b/tests/phpunit/includes/ImportTest.php
@@ -28,13 +28,14 @@ class ImportTest extends MediaWikiLangTestCase {
$source = $this->getInputStreamSource( $xml );
$redirect = null;
- $callback = function ( $title, $origTitle, $revCount, $sRevCount, $pageInfo ) use ( &$redirect ) {
+ $callback = function ( Title $title, ForeignTitle $foreignTitle, $revCount,
+ $sRevCount, $pageInfo ) use ( &$redirect ) {
if ( array_key_exists( 'redirect', $pageInfo ) ) {
$redirect = $pageInfo['redirect'];
}
};
- $importer = new WikiImporter( $source );
+ $importer = new WikiImporter( $source, ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
$importer->setPageOutCallback( $callback );
$importer->doImport();
@@ -45,7 +46,7 @@ class ImportTest extends MediaWikiLangTestCase {
return array(
array(
<<< EOF
-<mediawiki>
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
<page>
<title>Test</title>
<ns>0</ns>
@@ -59,10 +60,10 @@ class ImportTest extends MediaWikiLangTestCase {
<id>10</id>
</contributor>
<comment>Admin moved page [[Test]] to [[Test22]]</comment>
- <text xml:space="preserve" bytes="20">#REDIRECT [[Test22]]</text>
- <sha1>tq456o9x3abm7r9ozi6km8yrbbc56o6</sha1>
<model>wikitext</model>
<format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="20">#REDIRECT [[Test22]]</text>
+ <sha1>tq456o9x3abm7r9ozi6km8yrbbc56o6</sha1>
</revision>
</page>
</mediawiki>
@@ -72,7 +73,7 @@ EOF
),
array(
<<< EOF
-<mediawiki>
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.9/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.9/ http://www.mediawiki.org/xml/export-0.9.xsd" version="0.9" xml:lang="en">
<page>
<title>Test</title>
<ns>0</ns>
@@ -98,4 +99,59 @@ EOF
);
}
+ /**
+ * @covers WikiImporter::handleSiteInfo
+ * @dataProvider getSiteInfoXML
+ * @param string $xml
+ * @param array|null $namespaces
+ */
+ public function testSiteInfoContainsNamespaces( $xml, $namespaces ) {
+ $source = $this->getInputStreamSource( $xml );
+
+ $importNamespaces = null;
+ $callback = function ( array $siteinfo, $innerImporter ) use ( &$importNamespaces ) {
+ $importNamespaces = $siteinfo['_namespaces'];
+ };
+
+ $importer = new WikiImporter( $source, ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
+ $importer->setSiteInfoCallback( $callback );
+ $importer->doImport();
+
+ $this->assertEquals( $importNamespaces, $namespaces );
+ }
+
+ public function getSiteInfoXML() {
+ return array(
+ array(
+ <<< EOF
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
+ <siteinfo>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="100" case="first-letter">Portal</namespace>
+ <namespace key="101" case="first-letter">Portal talk</namespace>
+ </namespaces>
+ </siteinfo>
+</mediawiki>
+EOF
+ ,
+ array(
+ '-2' => 'Media',
+ '-1' => 'Special',
+ '0' => '',
+ '1' => 'Talk',
+ '2' => 'User',
+ '3' => 'User talk',
+ '100' => 'Portal',
+ '101' => 'Portal talk',
+ )
+ ),
+ );
+ }
+
}
diff --git a/tests/phpunit/includes/LinkerTest.php b/tests/phpunit/includes/LinkerTest.php
index 7b84107e..823c9330 100644
--- a/tests/phpunit/includes/LinkerTest.php
+++ b/tests/phpunit/includes/LinkerTest.php
@@ -149,10 +149,14 @@ class LinkerTest extends MediaWikiLangTestCase {
"pre /* autocomment */ post",
),
array(
- '/* autocomment */ multiple? <a href="/wiki/Special:BlankPage#autocomment2" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment2: </span> </span>',
+ '<a href="/wiki/Special:BlankPage#autocomment" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment: </span> multiple? <a href="/wiki/Special:BlankPage#autocomment2" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment2: </span> </span></span>',
"/* autocomment */ multiple? /* autocomment2 */ ",
),
array(
+ '<a href="/wiki/Special:BlankPage#autocomment_containing_.2F.2A" title="Special:BlankPage">→</a>‎<span dir="auto"><span class="autocomment">autocomment containing /*: </span> T70361</span>',
+ "/* autocomment containing /* */ T70361"
+ ),
+ array(
'<a href="#autocomment">→</a>‎<span dir="auto"><span class="autocomment">autocomment</span></span>',
"/* autocomment */",
false, true
@@ -189,4 +193,54 @@ class LinkerTest extends MediaWikiLangTestCase {
),
);
}
+
+ /**
+ * @covers Linker::formatLinksInComment
+ * @dataProvider provideCasesForFormatLinksInComment
+ */
+ public function testFormatLinksInComment( $expected, $input, $wiki ) {
+
+ $conf = new SiteConfiguration();
+ $conf->settings = array(
+ 'wgServer' => array(
+ 'enwiki' => '//en.example.org'
+ ),
+ 'wgArticlePath' => array(
+ 'enwiki' => '/w/$1',
+ ),
+ );
+ $conf->suffixes = array( 'wiki' );
+ $this->setMwGlobals( array(
+ 'wgScript' => '/wiki/index.php',
+ 'wgArticlePath' => '/wiki/$1',
+ 'wgWellFormedXml' => true,
+ 'wgCapitalLinks' => true,
+ 'wgConf' => $conf,
+ ) );
+
+ $this->assertEquals(
+ $expected,
+ Linker::formatLinksInComment( $input, Title::newFromText( 'Special:BlankPage' ), false, $wiki )
+ );
+ }
+
+ public static function provideCasesForFormatLinksInComment() {
+ return array(
+ array(
+ 'foo bar <a href="/wiki/Special:BlankPage" title="Special:BlankPage">Special:BlankPage</a>',
+ 'foo bar [[Special:BlankPage]]',
+ null,
+ ),
+ array(
+ '<a class="external" rel="nofollow" href="//en.example.org/w/Foo%27bar">Foo\'bar</a>',
+ "[[Foo'bar]]",
+ 'enwiki',
+ ),
+ array(
+ 'foo bar <a class="external" rel="nofollow" href="//en.example.org/w/Special:BlankPage">Special:BlankPage</a>',
+ 'foo bar [[Special:BlankPage]]',
+ 'enwiki',
+ ),
+ );
+ }
}
diff --git a/tests/phpunit/includes/MWTimestampTest.php b/tests/phpunit/includes/MWTimestampTest.php
index dcb98563..36562545 100644
--- a/tests/phpunit/includes/MWTimestampTest.php
+++ b/tests/phpunit/includes/MWTimestampTest.php
@@ -8,6 +8,9 @@ class MWTimestampTest extends MediaWikiLangTestCase {
protected function setUp() {
parent::setUp();
+ // Avoid 'GetHumanTimestamp' hook and others
+ $this->setMwGlobals( 'wgHooks', array() );
+
RequestContext::getMain()->setLanguage( Language::factory( 'en' ) );
}
@@ -79,6 +82,17 @@ class MWTimestampTest extends MediaWikiLangTestCase {
}
/**
+ * Test an out of range timestamp
+ * @dataProvider provideOutOfRangeTimestamps
+ * @expectedException TimestampException
+ * @covers MWTimestamp
+ */
+ public function testOutOfRangeTimestamps( $format, $input ) {
+ $timestamp = new MWTimestamp( $input );
+ $timestamp->getTimestamp( $format );
+ }
+
+ /**
* Test requesting an invalid output format.
* @expectedException TimestampException
* @covers MWTimestamp::getTimestamp
@@ -111,6 +125,18 @@ class MWTimestampTest extends MediaWikiLangTestCase {
}
/**
+ * Returns a list of out of range timestamps in the format:
+ * array( type, timestamp_of_type )
+ */
+ public static function provideOutOfRangeTimestamps() {
+ return array(
+ // Various formats
+ array( TS_MW, '-62167219201' ), // -0001-12-31T23:59:59Z
+ array( TS_MW, '253402300800' ), // 10000-01-01T00:00:00Z
+ );
+ }
+
+ /**
* @dataProvider provideHumanTimestampTests
* @covers MWTimestamp::getHumanTimestamp
*/
diff --git a/tests/phpunit/includes/MediaWikiVersionFetcherTest.php b/tests/phpunit/includes/MediaWikiVersionFetcherTest.php
index e548f817..fa59ef29 100644
--- a/tests/phpunit/includes/MediaWikiVersionFetcherTest.php
+++ b/tests/phpunit/includes/MediaWikiVersionFetcherTest.php
@@ -8,7 +8,6 @@
*
* @group ComposerHooks
*
- * @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
class MediaWikiVersionFetcherTest extends PHPUnit_Framework_TestCase {
diff --git a/tests/phpunit/includes/MessageTest.php b/tests/phpunit/includes/MessageTest.php
index f3d2a84a..99ec2e42 100644
--- a/tests/phpunit/includes/MessageTest.php
+++ b/tests/phpunit/includes/MessageTest.php
@@ -16,22 +16,11 @@ class MessageTest extends MediaWikiLangTestCase {
* @dataProvider provideConstructor
*/
public function testConstructor( $expectedLang, $key, $params, $language ) {
- $reflection = new ReflectionClass( 'Message' );
-
- $keyProperty = $reflection->getProperty( 'key' );
- $keyProperty->setAccessible( true );
-
- $paramsProperty = $reflection->getProperty( 'parameters' );
- $paramsProperty->setAccessible( true );
-
- $langProperty = $reflection->getProperty( 'language' );
- $langProperty->setAccessible( true );
-
$message = new Message( $key, $params, $language );
- $this->assertEquals( $key, $keyProperty->getValue( $message ) );
- $this->assertEquals( $params, $paramsProperty->getValue( $message ) );
- $this->assertEquals( $expectedLang, $langProperty->getValue( $message ) );
+ $this->assertEquals( $key, $message->getKey() );
+ $this->assertEquals( $params, $message->getParams() );
+ $this->assertEquals( $expectedLang, $message->getLanguage() );
}
public static function provideConstructor() {
@@ -45,21 +34,62 @@ class MessageTest extends MediaWikiLangTestCase {
);
}
- public static function provideTestParams() {
+ public static function provideConstructorParams() {
return array(
- array( array() ),
- array( array( 'foo' ), 'foo' ),
- array( array( 'foo', 'bar' ), 'foo', 'bar' ),
- array( array( 'baz' ), array( 'baz' ) ),
- array( array( 'baz', 'foo' ), array( 'baz', 'foo' ) ),
- array( array( 'baz', 'foo' ), array( 'baz', 'foo' ), 'hhh' ),
- array( array( 'baz', 'foo' ), array( 'baz', 'foo' ), 'hhh', array( 'ahahahahha' ) ),
- array( array( 'baz', 'foo' ), array( 'baz', 'foo' ), array( 'ahahahahha' ) ),
- array( array( 'baz' ), array( 'baz' ), array( 'ahahahahha' ) ),
+ array(
+ array(),
+ array(),
+ ),
+ array(
+ array( 'foo' ),
+ array( 'foo' ),
+ ),
+ array(
+ array( 'foo', 'bar' ),
+ array( 'foo', 'bar' ),
+ ),
+ array(
+ array( 'baz' ),
+ array( array( 'baz' ) ),
+ ),
+ array(
+ array( 'baz', 'foo' ),
+ array( array( 'baz', 'foo' ) ),
+ ),
+ array(
+ array( 'baz', 'foo' ),
+ array( array( 'baz', 'foo' ), 'hhh' ),
+ ),
+ array(
+ array( 'baz', 'foo' ),
+ array( array( 'baz', 'foo' ), 'hhh', array( 'ahahahahha' ) ),
+ ),
+ array(
+ array( 'baz', 'foo' ),
+ array( array( 'baz', 'foo' ), array( 'ahahahahha' ) ),
+ ),
+ array(
+ array( 'baz' ),
+ array( array( 'baz' ), array( 'ahahahahha' ) ),
+ ),
);
}
- public function getLanguageProvider() {
+ /**
+ * @covers Message::__construct
+ * @covers Message::getParams
+ * @dataProvider provideConstructorParams
+ */
+ public function testConstructorParams( $expected, $args ) {
+ $msg = new Message( 'imasomething' );
+
+ $returned = call_user_func_array( array( $msg, 'params' ), $args );
+
+ $this->assertSame( $msg, $returned );
+ $this->assertEquals( $expected, $msg->getParams() );
+ }
+
+ public static function provideConstructorLanguage() {
return array(
array( 'foo', array( 'bar' ), 'en' ),
array( 'foo', array( 'bar' ), 'de' )
@@ -67,27 +97,98 @@ class MessageTest extends MediaWikiLangTestCase {
}
/**
+ * @covers Message::__construct
* @covers Message::getLanguage
- * @dataProvider getLanguageProvider
+ * @dataProvider provideConstructorLanguage
*/
- public function testGetLanguageCode( $key, $params, $languageCode ) {
+ public function testConstructorLanguage( $key, $params, $languageCode ) {
$language = Language::factory( $languageCode );
$message = new Message( $key, $params, $language );
$this->assertEquals( $language, $message->getLanguage() );
}
+ public static function provideKeys() {
+ return array(
+ 'string' => array(
+ 'key' => 'mainpage',
+ 'expected' => array( 'mainpage' ),
+ ),
+ 'single' => array(
+ 'key' => array( 'mainpage' ),
+ 'expected' => array( 'mainpage' ),
+ ),
+ 'multi' => array(
+ 'key' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
+ 'expected' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
+ ),
+ 'empty' => array(
+ 'key' => array(),
+ 'expected' => null,
+ 'exception' => 'InvalidArgumentException',
+ ),
+ 'null' => array(
+ 'key' => null,
+ 'expected' => null,
+ 'exception' => 'InvalidArgumentException',
+ ),
+ 'bad type' => array(
+ 'key' => 123,
+ 'expected' => null,
+ 'exception' => 'InvalidArgumentException',
+ ),
+ );
+ }
+
/**
- * @covers Message::params
- * @dataProvider provideTestParams
+ * @covers Message::__construct
+ * @covers Message::getKey
+ * @covers Message::isMultiKey
+ * @covers Message::getKeysToTry
+ * @dataProvider provideKeys
*/
- public function testParams( $expected ) {
- $msg = new Message( 'imasomething' );
+ public function testKeys( $key, $expected, $exception = null ) {
+ if ( $exception ) {
+ $this->setExpectedException( $exception );
+ }
+
+ $msg = new Message( $key );
+ $this->assertContains( $msg->getKey(), $expected );
+ $this->assertEquals( $expected, $msg->getKeysToTry() );
+ $this->assertEquals( count( $expected ) > 1, $msg->isMultiKey() );
+ }
- $returned = call_user_func_array( array( $msg, 'params' ), array_slice( func_get_args(), 1 ) );
+ /**
+ * @covers ::wfMessage
+ */
+ public function testWfMessage() {
+ $this->assertInstanceOf( 'Message', wfMessage( 'mainpage' ) );
+ $this->assertInstanceOf( 'Message', wfMessage( 'i-dont-exist-evar' ) );
+ }
- $this->assertSame( $msg, $returned );
- $this->assertEquals( $expected, $msg->getParams() );
+ /**
+ * @covers Message::newFromKey
+ */
+ public function testNewFromKey() {
+ $this->assertInstanceOf( 'Message', Message::newFromKey( 'mainpage' ) );
+ $this->assertInstanceOf( 'Message', Message::newFromKey( 'i-dont-exist-evar' ) );
+ }
+
+ /**
+ * @covers ::wfMessage
+ * @covers Message::__construct
+ */
+ public function testWfMessageParams() {
+ $this->assertEquals( 'Return to $1.', wfMessage( 'returnto' )->text() );
+ $this->assertEquals( 'Return to $1.', wfMessage( 'returnto', array() )->text() );
+ $this->assertEquals(
+ 'You have foo (bar).',
+ wfMessage( 'youhavenewmessages', 'foo', 'bar' )->text()
+ );
+ $this->assertEquals(
+ 'You have foo (bar).',
+ wfMessage( 'youhavenewmessages', array( 'foo', 'bar' ) )->text()
+ );
}
/**
@@ -104,14 +205,42 @@ class MessageTest extends MediaWikiLangTestCase {
/**
* @covers Message::__construct
+ * @covers Message::text
+ * @covers Message::plain
+ * @covers Message::escaped
+ * @covers Message::toString
*/
- public function testKey() {
- $this->assertInstanceOf( 'Message', wfMessage( 'mainpage' ) );
- $this->assertInstanceOf( 'Message', wfMessage( 'i-dont-exist-evar' ) );
+ public function testToStringKey() {
$this->assertEquals( 'Main Page', wfMessage( 'mainpage' )->text() );
- $this->assertEquals( '&lt;i-dont-exist-evar&gt;', wfMessage( 'i-dont-exist-evar' )->text() );
+ $this->assertEquals( '<i-dont-exist-evar>', wfMessage( 'i-dont-exist-evar' )->text() );
+ $this->assertEquals( '<i<dont>exist-evar>', wfMessage( 'i<dont>exist-evar' )->text() );
$this->assertEquals( '<i-dont-exist-evar>', wfMessage( 'i-dont-exist-evar' )->plain() );
+ $this->assertEquals( '<i<dont>exist-evar>', wfMessage( 'i<dont>exist-evar' )->plain() );
$this->assertEquals( '&lt;i-dont-exist-evar&gt;', wfMessage( 'i-dont-exist-evar' )->escaped() );
+ $this->assertEquals(
+ '&lt;i&lt;dont&gt;exist-evar&gt;',
+ wfMessage( 'i<dont>exist-evar' )->escaped()
+ );
+ }
+
+ public static function provideToString() {
+ return array(
+ array( 'mainpage', 'Main Page' ),
+ array( 'i-dont-exist-evar', '<i-dont-exist-evar>' ),
+ array( 'i-dont-exist-evar', '&lt;i-dont-exist-evar&gt;', 'escaped' ),
+ );
+ }
+
+ /**
+ * @covers Message::toString
+ * @covers Message::__toString
+ * @dataProvider provideToString
+ */
+ public function testToString( $key, $expect, $format = 'plain' ) {
+ $msg = new Message( $key );
+ $msg->$format();
+ $this->assertEquals( $expect, $msg->toString() );
+ $this->assertEquals( $expect, $msg->__toString() );
}
/**
@@ -132,26 +261,10 @@ class MessageTest extends MediaWikiLangTestCase {
}
/**
- * @covers Message::__construct
- */
- public function testMessageParams() {
- $this->assertEquals( 'Return to $1.', wfMessage( 'returnto' )->text() );
- $this->assertEquals( 'Return to $1.', wfMessage( 'returnto', array() )->text() );
- $this->assertEquals(
- 'You have foo (bar).',
- wfMessage( 'youhavenewmessages', 'foo', 'bar' )->text()
- );
- $this->assertEquals(
- 'You have foo (bar).',
- wfMessage( 'youhavenewmessages', array( 'foo', 'bar' ) )->text()
- );
- }
-
- /**
- * @covers Message::__construct
+ * @covers Message::rawParam
* @covers Message::rawParams
*/
- public function testMessageParamSubstitution() {
+ public function testRawParams() {
$this->assertEquals(
'(Заглавная страница)',
wfMessage( 'parentheses', 'Заглавная страница' )->plain()
@@ -171,10 +284,21 @@ class MessageTest extends MediaWikiLangTestCase {
}
/**
- * @covers Message::__construct
+ * @covers RawMessage::__construct
+ * @covers RawMessage::fetchMessage
+ */
+ public function testRawMessage() {
+ $msg = new RawMessage( 'example &' );
+ $this->assertEquals( 'example &', $msg->plain() );
+ $this->assertEquals( 'example &amp;', $msg->escaped() );
+ }
+
+ /**
* @covers Message::params
+ * @covers Message::toString
+ * @covers Message::replaceParameters
*/
- public function testDeliciouslyManyParams() {
+ public function testReplaceManyParams() {
$msg = new RawMessage( '$1$2$3$4$5$6$7$8$9$10$11$12' );
// One less than above has placeholders
$params = array( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k' );
@@ -183,12 +307,20 @@ class MessageTest extends MediaWikiLangTestCase {
$msg->params( $params )->plain(),
'Params > 9 are replaced correctly'
);
+
+ $msg = new RawMessage( 'Params$*' );
+ $params = array( 'ab', 'bc', 'cd' );
+ $this->assertEquals(
+ 'Params: ab, bc, cd',
+ $msg->params( $params )->text()
+ );
}
/**
+ * @covers Message::numParam
* @covers Message::numParams
*/
- public function testMessageNumParams() {
+ public function testNumParams() {
$lang = Language::factory( 'en' );
$msg = new RawMessage( '$1' );
@@ -200,9 +332,10 @@ class MessageTest extends MediaWikiLangTestCase {
}
/**
+ * @covers Message::durationParam
* @covers Message::durationParams
*/
- public function testMessageDurationParams() {
+ public function testDurationParams() {
$lang = Language::factory( 'en' );
$msg = new RawMessage( '$1' );
@@ -216,9 +349,10 @@ class MessageTest extends MediaWikiLangTestCase {
/**
* FIXME: This should not need database, but Language#formatExpiry does (bug 55912)
* @group Database
+ * @covers Message::expiryParam
* @covers Message::expiryParams
*/
- public function testMessageExpiryParams() {
+ public function testExpiryParams() {
$lang = Language::factory( 'en' );
$msg = new RawMessage( '$1' );
@@ -230,9 +364,10 @@ class MessageTest extends MediaWikiLangTestCase {
}
/**
+ * @covers Message::timeperiodParam
* @covers Message::timeperiodParams
*/
- public function testMessageTimeperiodParams() {
+ public function testTimeperiodParams() {
$lang = Language::factory( 'en' );
$msg = new RawMessage( '$1' );
@@ -244,9 +379,10 @@ class MessageTest extends MediaWikiLangTestCase {
}
/**
+ * @covers Message::sizeParam
* @covers Message::sizeParams
*/
- public function testMessageSizeParams() {
+ public function testSizeParams() {
$lang = Language::factory( 'en' );
$msg = new RawMessage( '$1' );
@@ -258,9 +394,10 @@ class MessageTest extends MediaWikiLangTestCase {
}
/**
+ * @covers Message::bitrateParam
* @covers Message::bitrateParams
*/
- public function testMessageBitrateParams() {
+ public function testBitrateParams() {
$lang = Language::factory( 'en' );
$msg = new RawMessage( '$1' );
@@ -271,6 +408,100 @@ class MessageTest extends MediaWikiLangTestCase {
);
}
+ public static function providePlaintextParams() {
+ return array(
+ array(
+ 'one $2 <div>foo</div> [[Bar]] {{Baz}} &lt;',
+ 'plain',
+ ),
+
+ array(
+ // expect
+ 'one $2 <div>foo</div> [[Bar]] {{Baz}} &lt;',
+ // format
+ 'text',
+ ),
+ array(
+ 'one $2 &lt;div&gt;foo&lt;/div&gt; [[Bar]] {{Baz}} &amp;lt;',
+ 'escaped',
+ ),
+
+ array(
+ 'one $2 &lt;div&gt;foo&lt;/div&gt; [[Bar]] {{Baz}} &amp;lt;',
+ 'parse',
+ ),
+
+ array(
+ "<p>one $2 &lt;div&gt;foo&lt;/div&gt; [[Bar]] {{Baz}} &amp;lt;\n</p>",
+ 'parseAsBlock',
+ ),
+ );
+ }
+
+ /**
+ * @covers Message::plaintextParam
+ * @covers Message::plaintextParams
+ * @covers Message::formatPlaintext
+ * @covers Message::toString
+ * @covers Message::parse
+ * @covers Message::parseAsBlock
+ * @dataProvider providePlaintextParams
+ */
+ public function testPlaintextParams( $expect, $format ) {
+ $lang = Language::factory( 'en' );
+
+ $msg = new RawMessage( '$1 $2' );
+ $params = array(
+ 'one $2',
+ '<div>foo</div> [[Bar]] {{Baz}} &lt;',
+ );
+ $this->assertEquals(
+ $expect,
+ $msg->inLanguage( $lang )->plaintextParams( $params )->$format(),
+ "Fail formatting for $format"
+ );
+ }
+
+ public static function provideParser() {
+ return array(
+ array(
+ "''&'' <x><!-- x -->",
+ 'plain',
+ ),
+
+ array(
+ "''&'' <x><!-- x -->",
+ 'text',
+ ),
+ array(
+ '<i>&amp;</i> &lt;x&gt;',
+ 'parse',
+ ),
+
+ array(
+ "<p><i>&amp;</i> &lt;x&gt;\n</p>",
+ 'parseAsBlock',
+ ),
+ );
+ }
+
+ /**
+ * @covers Message::text
+ * @covers Message::parse
+ * @covers Message::parseAsBlock
+ * @covers Message::toString
+ * @covers Message::transformText
+ * @covers Message::parseText
+ * @dataProvider provideParser
+ */
+ public function testParser( $expect, $format ) {
+ $msg = new RawMessage( "''&'' <x><!-- x -->" );
+ $this->assertEquals(
+ $expect,
+ $msg->inLanguage( 'en' )->$format()
+ );
+ }
+
/**
* @covers Message::inContentLanguage
*/
@@ -317,52 +548,4 @@ class MessageTest extends MediaWikiLangTestCase {
public function testInLanguageThrows() {
wfMessage( 'foo' )->inLanguage( 123 );
}
-
- public function keyProvider() {
- return array(
- 'string' => array(
- 'key' => 'mainpage',
- 'expected' => array( 'mainpage' ),
- ),
- 'single' => array(
- 'key' => array( 'mainpage' ),
- 'expected' => array( 'mainpage' ),
- ),
- 'multi' => array(
- 'key' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
- 'expected' => array( 'mainpage-foo', 'mainpage-bar', 'mainpage' ),
- ),
- 'empty' => array(
- 'key' => array(),
- 'expected' => null,
- 'exception' => 'InvalidArgumentException',
- ),
- 'null' => array(
- 'key' => null,
- 'expected' => null,
- 'exception' => 'InvalidArgumentException',
- ),
- 'bad type' => array(
- 'key' => 17,
- 'expected' => null,
- 'exception' => 'InvalidArgumentException',
- ),
- );
- }
-
- /**
- * @dataProvider keyProvider()
- *
- * @covers Message::getKey
- */
- public function testGetKey( $key, $expected, $exception = null ) {
- if ( $exception ) {
- $this->setExpectedException( $exception );
- }
-
- $msg = new Message( $key );
- $this->assertEquals( $expected, $msg->getKeysToTry() );
- $this->assertEquals( count( $expected ) > 1, $msg->isMultiKey() );
- $this->assertContains( $msg->getKey(), $expected );
- }
}
diff --git a/tests/phpunit/includes/MovePageTest.php b/tests/phpunit/includes/MovePageTest.php
new file mode 100644
index 00000000..9501e452
--- /dev/null
+++ b/tests/phpunit/includes/MovePageTest.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @group Database
+ */
+class MovePageTest extends MediaWikiTestCase {
+
+ /**
+ * @dataProvider provideIsValidMove
+ * @covers MovePage::isValidMove
+ * @covers MovePage::isValidFileMove
+ */
+ public function testIsValidMove( $old, $new, $error ) {
+ $this->setMwGlobals( 'wgContentHandlerUseDB', false );
+ $mp = new MovePage(
+ Title::newFromText( $old ),
+ Title::newFromText( $new )
+ );
+ $status = $mp->isValidMove();
+ if ( $error === true ) {
+ $this->assertTrue( $status->isGood() );
+ } else {
+ $this->assertTrue( $status->hasMessage( $error ) );
+ }
+ }
+
+ /**
+ * This should be kept in sync with TitleTest::provideTestIsValidMoveOperation
+ */
+ public static function provideIsValidMove() {
+ return array(
+ // for MovePage::isValidMove
+ array( 'Test', 'Test', 'selfmove' ),
+ array( 'Special:FooBar', 'Test', 'immobile-source-namespace' ),
+ array( 'Test', 'Special:FooBar', 'immobile-target-namespace' ),
+ array( 'MediaWiki:Common.js', 'Help:Some wikitext page', 'bad-target-model' ),
+ array( 'Page', 'File:Test.jpg', 'nonfile-cannot-move-to-file' ),
+ // for MovePage::isValidFileMove
+ array( 'File:Test.jpg', 'Page', 'imagenocrossnamespace' ),
+ );
+ }
+
+ /**
+ * Integration test to catch regressions like T74870. Taken and modified
+ * from SemanticMediaWiki
+ */
+ public function testTitleMoveCompleteIntegrationTest() {
+ $oldTitle = Title::newFromText( 'Help:Some title' );
+ WikiPage::factory( $oldTitle )->doEditContent( new WikitextContent( 'foo' ), 'bar' );
+ $newTitle = Title::newFromText( 'Help:Some other title' );
+ $this->assertNull(
+ WikiPage::factory( $newTitle )->getRevision()
+ );
+
+ $this->assertTrue( $oldTitle->moveTo( $newTitle, false, 'test1', true ) );
+ $this->assertNotNull(
+ WikiPage::factory( $oldTitle )->getRevision()
+ );
+ $this->assertNotNull(
+ WikiPage::factory( $newTitle)->getRevision()
+ );
+ }
+}
diff --git a/tests/phpunit/includes/OutputPageTest.php b/tests/phpunit/includes/OutputPageTest.php
index d7e8cd31..6c6d95ee 100644
--- a/tests/phpunit/includes/OutputPageTest.php
+++ b/tests/phpunit/includes/OutputPageTest.php
@@ -172,18 +172,18 @@ mw.test.baz({token:123});mw.loader.state({"test.quux":"ready"});
array(
array( 'test.quux', ResourceLoaderModule::TYPE_COMBINED ),
'<script>if(window.mw){
-mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"css":[".mw-icon{transition:none}\n"]},{});
+mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"css":[".mw-icon{transition:none}\n"]});
}</script>
'
),
- // Load module script with with ESI
+ // Load module script with ESI
array(
array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS, true ),
'<script><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=scripts&amp;skin=fallback&amp;*" /></script>
'
),
- // Load module styles with with ESI
+ // Load module styles with ESI
array(
array( 'test.foo', ResourceLoaderModule::TYPE_STYLES, true ),
'<style><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=styles&amp;skin=fallback&amp;*" /></style>
@@ -203,9 +203,13 @@ mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"
// Load two modules in separate groups
array(
array( array( 'test.group.foo', 'test.group.bar' ), ResourceLoaderModule::TYPE_COMBINED ),
- '<script src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.group.bar&amp;skin=fallback&amp;*"></script>
-<script src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.group.foo&amp;skin=fallback&amp;*"></script>
-',
+ '<script>if(window.mw){
+document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.group.bar\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");
+}</script>
+<script>if(window.mw){
+document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.group.foo\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");
+}</script>
+'
),
);
}
@@ -213,6 +217,11 @@ mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"
/**
* @dataProvider provideMakeResourceLoaderLink
* @covers OutputPage::makeResourceLoaderLink
+ * @covers ResourceLoader::makeLoaderImplementScript
+ * @covers ResourceLoader::makeModuleResponse
+ * @covers ResourceLoader::makeInlineScript
+ * @covers ResourceLoader::makeLoaderStateScript
+ * @covers ResourceLoader::createLoaderURL
*/
public function testMakeResourceLoaderLink( $args, $expectedHtml ) {
$this->setMwGlobals( array(
@@ -230,6 +239,7 @@ mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"
$ctx->setLanguage( 'en' );
$out = new OutputPage( $ctx );
$rl = $out->getResourceLoader();
+ $rl->setMessageBlobStore( new NullMessageBlobStore() );
$rl->register( array(
'test.foo' => new ResourceLoaderTestModule( array(
'script' => 'mw.test.foo( { a: true } );',
@@ -271,3 +281,26 @@ mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"
$this->assertEquals( $expectedHtml, $actualHtml );
}
}
+
+/**
+ * MessageBlobStore that doesn't do anything
+ */
+class NullMessageBlobStore extends MessageBlobStore {
+ public function get ( ResourceLoader $resourceLoader, $modules, $lang ) {
+ return array();
+ }
+
+ public function insertMessageBlob ( $name, ResourceLoaderModule $module, $lang ) {
+ return false;
+ }
+
+ public function updateModule ( $name, ResourceLoaderModule $module, $lang ) {
+ return;
+ }
+
+ public function updateMessage ( $key ) {
+ }
+ public function clear() {
+ }
+}
+
diff --git a/tests/phpunit/includes/PrefixSearchTest.php b/tests/phpunit/includes/PrefixSearchTest.php
new file mode 100644
index 00000000..d63541b7
--- /dev/null
+++ b/tests/phpunit/includes/PrefixSearchTest.php
@@ -0,0 +1,306 @@
+<?php
+/**
+ * @group Search
+ * @group Database
+ */
+class PrefixSearchTest extends MediaWikiLangTestCase {
+
+ public function addDBData() {
+ $this->insertPage( 'Sandbox' );
+ $this->insertPage( 'Bar' );
+ $this->insertPage( 'Example' );
+ $this->insertPage( 'Example Bar' );
+ $this->insertPage( 'Example Foo' );
+ $this->insertPage( 'Example Foo/Bar' );
+ $this->insertPage( 'Example/Baz' );
+ $this->insertPage( 'Redirect test', '#REDIRECT [[Redirect Test]]' );
+ $this->insertPage( 'Redirect Test' );
+ $this->insertPage( 'Redirect Test Worse Result' );
+ $this->insertPage( 'Redirect test2', '#REDIRECT [[Redirect Test2]]' );
+ $this->insertPage( 'Redirect TEST2', '#REDIRECT [[Redirect Test2]]' );
+ $this->insertPage( 'Redirect Test2' );
+ $this->insertPage( 'Redirect Test2 Worse Result' );
+
+ $this->insertPage( 'Talk:Sandbox' );
+ $this->insertPage( 'Talk:Example' );
+
+ $this->insertPage( 'User:Example' );
+ }
+
+ protected function setUp() {
+ parent::setUp();
+
+ if ( !$this->isWikitextNS( NS_MAIN ) ) {
+ $this->markTestSkipped( 'Main namespace does not support wikitext.' );
+ }
+
+ // Avoid special pages from extensions interferring with the tests
+ $this->setMwGlobals( 'wgSpecialPages', array() );
+ }
+
+ protected function searchProvision( Array $results = null ) {
+ if ( $results === null ) {
+ $this->setMwGlobals( 'wgHooks', array() );
+ } else {
+ $this->setMwGlobals( 'wgHooks', array(
+ 'PrefixSearchBackend' => array(
+ function ( $namespaces, $search, $limit, &$srchres ) use ( $results ) {
+ $srchres = $results;
+ return false;
+ }
+ ),
+ ) );
+ }
+ }
+
+ public static function provideSearch() {
+ return array(
+ array( array(
+ 'Empty string',
+ 'query' => '',
+ 'results' => array(),
+ ) ),
+ array( array(
+ 'Main namespace with title prefix',
+ 'query' => 'Ex',
+ 'results' => array(
+ 'Example',
+ 'Example/Baz',
+ 'Example Bar',
+ ),
+ // Third result when testing offset
+ 'offsetresult' => array(
+ 'Example Foo',
+ ),
+ ) ),
+ array( array(
+ 'Talk namespace prefix',
+ 'query' => 'Talk:',
+ 'results' => array(
+ 'Talk:Example',
+ 'Talk:Sandbox',
+ ),
+ ) ),
+ array( array(
+ 'User namespace prefix',
+ 'query' => 'User:',
+ 'results' => array(
+ 'User:Example',
+ ),
+ ) ),
+ array( array(
+ 'Special namespace prefix',
+ 'query' => 'Special:',
+ 'results' => array(
+ 'Special:ActiveUsers',
+ 'Special:AllMessages',
+ 'Special:AllMyFiles',
+ ),
+ // Third result when testing offset
+ 'offsetresult' => array(
+ 'Special:AllMyUploads',
+ ),
+ ) ),
+ array( array(
+ 'Special namespace with prefix',
+ 'query' => 'Special:Un',
+ 'results' => array(
+ 'Special:Unblock',
+ 'Special:UncategorizedCategories',
+ 'Special:UncategorizedFiles',
+ ),
+ // Third result when testing offset
+ 'offsetresult' => array(
+ 'Special:UncategorizedImages',
+ ),
+ ) ),
+ array( array(
+ 'Special page name',
+ 'query' => 'Special:EditWatchlist',
+ 'results' => array(
+ 'Special:EditWatchlist',
+ ),
+ ) ),
+ array( array(
+ 'Special page subpages',
+ 'query' => 'Special:EditWatchlist/',
+ 'results' => array(
+ 'Special:EditWatchlist/clear',
+ 'Special:EditWatchlist/raw',
+ ),
+ ) ),
+ array( array(
+ 'Special page subpages with prefix',
+ 'query' => 'Special:EditWatchlist/cl',
+ 'results' => array(
+ 'Special:EditWatchlist/clear',
+ ),
+ ) ),
+ );
+ }
+
+ /**
+ * @dataProvider provideSearch
+ * @covers PrefixSearch::search
+ * @covers PrefixSearch::searchBackend
+ */
+ public function testSearch( Array $case ) {
+ $this->searchProvision( null );
+ $searcher = new StringPrefixSearch;
+ $results = $searcher->search( $case['query'], 3 );
+ $this->assertEquals(
+ $case['results'],
+ $results,
+ $case[0]
+ );
+ }
+
+ /**
+ * @dataProvider provideSearch
+ * @covers PrefixSearch::search
+ * @covers PrefixSearch::searchBackend
+ */
+ public function testSearchWithOffset( Array $case ) {
+ $this->searchProvision( null );
+ $searcher = new StringPrefixSearch;
+ $results = $searcher->search( $case['query'], 3, array(), 1 );
+
+ // We don't expect the first result when offsetting
+ array_shift( $case['results'] );
+ // And sometimes we expect a different last result
+ $expected = isset( $case['offsetresult'] ) ?
+ array_merge( $case['results'], $case['offsetresult'] ) :
+ $case['results'];
+
+ $this->assertEquals(
+ $expected,
+ $results,
+ $case[0]
+ );
+ }
+
+ public static function provideSearchBackend() {
+ return array(
+ array( array(
+ 'Simple case',
+ 'provision' => array(
+ 'Bar',
+ 'Barcelona',
+ 'Barbara',
+ ),
+ 'query' => 'Bar',
+ 'results' => array(
+ 'Bar',
+ 'Barcelona',
+ 'Barbara',
+ ),
+ ) ),
+ array( array(
+ 'Exact match not on top (bug 70958)',
+ 'provision' => array(
+ 'Barcelona',
+ 'Bar',
+ 'Barbara',
+ ),
+ 'query' => 'Bar',
+ 'results' => array(
+ 'Bar',
+ 'Barcelona',
+ 'Barbara',
+ ),
+ ) ),
+ array( array(
+ 'Exact match missing (bug 70958)',
+ 'provision' => array(
+ 'Barcelona',
+ 'Barbara',
+ 'Bart',
+ ),
+ 'query' => 'Bar',
+ 'results' => array(
+ 'Bar',
+ 'Barcelona',
+ 'Barbara',
+ ),
+ ) ),
+ array( array(
+ 'Exact match missing and not existing',
+ 'provision' => array(
+ 'Exile',
+ 'Exist',
+ 'External',
+ ),
+ 'query' => 'Ex',
+ 'results' => array(
+ 'Exile',
+ 'Exist',
+ 'External',
+ ),
+ ) ),
+ array( array(
+ "Exact match shouldn't override already found match if " .
+ "exact is redirect and found isn't",
+ 'provision' => array(
+ // Target of the exact match is low in the list
+ 'Redirect Test Worse Result',
+ 'Redirect Test',
+ ),
+ 'query' => 'redirect test',
+ 'results' => array(
+ // Redirect target is pulled up and exact match isn't added
+ 'Redirect Test',
+ 'Redirect Test Worse Result',
+ ),
+ ) ),
+ array( array(
+ "Exact match shouldn't override already found match if " .
+ "both exact match and found match are redirect",
+ 'provision' => array(
+ // Another redirect to the same target as the exact match
+ // is low in the list
+ 'Redirect Test2 Worse Result',
+ 'Redirect test2',
+ ),
+ 'query' => 'redirect TEST2',
+ 'results' => array(
+ // Found redirect is pulled to the top and exact match isn't
+ // added
+ 'Redirect test2',
+ 'Redirect Test2 Worse Result',
+ ),
+ ) ),
+ array( array(
+ "Exact match should override any already found matches that " .
+ "are redirects to it",
+ 'provision' => array(
+ // Another redirect to the same target as the exact match
+ // is low in the list
+ 'Redirect Test Worse Result',
+ 'Redirect test',
+ ),
+ 'query' => 'Redirect Test',
+ 'results' => array(
+ // Found redirect is pulled to the top and exact match isn't
+ // added
+ 'Redirect Test',
+ 'Redirect Test Worse Result',
+ ),
+ ) ),
+ );
+ }
+
+ /**
+ * @dataProvider provideSearchBackend
+ * @covers PrefixSearch::searchBackend
+ */
+ public function testSearchBackend( Array $case ) {
+ $this->searchProvision( $case['provision'] );
+ $searcher = new StringPrefixSearch;
+ $results = $searcher->search( $case['query'], 3 );
+ $this->assertEquals(
+ $case['results'],
+ $results,
+ $case[0]
+ );
+ }
+}
diff --git a/tests/phpunit/includes/SampleTest.php b/tests/phpunit/includes/SampleTest.php
index 25858110..c5944d16 100644
--- a/tests/phpunit/includes/SampleTest.php
+++ b/tests/phpunit/includes/SampleTest.php
@@ -97,7 +97,7 @@ class TestSample extends MediaWikiLangTestCase {
// @codingStandardsIgnoreStart Ignore long line warning
/**
- * @expectedException MWException object
+ * @expectedException InvalidArgumentException
* See http://phpunit.de/manual/3.7/en/appendixes.annotations.html#appendixes.annotations.expectedException
*/
// @codingStandardsIgnoreEnd
diff --git a/tests/phpunit/includes/SanitizerTest.php b/tests/phpunit/includes/SanitizerTest.php
index 50c1e509..c615c460 100644
--- a/tests/phpunit/includes/SanitizerTest.php
+++ b/tests/phpunit/includes/SanitizerTest.php
@@ -6,12 +6,6 @@
*/
class SanitizerTest extends MediaWikiTestCase {
- protected function setUp() {
- parent::setUp();
-
- AutoLoader::loadClass( 'Sanitizer' );
- }
-
/**
* @covers Sanitizer::decodeCharReferences
*/
@@ -85,7 +79,7 @@ class SanitizerTest extends MediaWikiTestCase {
*/
public function testInvalidNumberedEntities() {
$this->assertEquals(
- UTF8_REPLACEMENT,
+ UtfNormal\Constants::UTF8_REPLACEMENT,
Sanitizer::decodeCharReferences( "&#88888888888888;" ),
'Invalid numbered entity'
);
@@ -346,4 +340,25 @@ class SanitizerTest extends MediaWikiTestCase {
$message
);
}
+
+ /**
+ * @dataProvider provideEscapeHtmlAllowEntities
+ * @covers Sanitizer::escapeHtmlAllowEntities
+ */
+ public function testEscapeHtmlAllowEntities( $expected, $html ) {
+ $this->assertEquals(
+ $expected,
+ Sanitizer::escapeHtmlAllowEntities( $html )
+ );
+ }
+
+ public static function provideEscapeHtmlAllowEntities() {
+ return array(
+ array( 'foo', 'foo' ),
+ array( 'a¡b', 'a&#161;b' ),
+ array( 'foo&#039;bar', "foo'bar" ),
+ array( '&lt;script&gt;foo&lt;/script&gt;', '<script>foo</script>' ),
+ );
+ }
+
}
diff --git a/tests/phpunit/includes/StatusTest.php b/tests/phpunit/includes/StatusTest.php
index 628c59b6..c013f4fc 100644
--- a/tests/phpunit/includes/StatusTest.php
+++ b/tests/phpunit/includes/StatusTest.php
@@ -57,6 +57,17 @@ class StatusTest extends MediaWikiLangTestCase {
}
/**
+ *
+ */
+ public function testOkAndErrors() {
+ $status = Status::newGood( 'foo' );
+ $this->assertTrue( $status->ok );
+ $status = Status::newFatal( 'foo', 1, 2 );
+ $this->assertFalse( $status->ok );
+ $this->assertArrayEquals( array( array( 'type' => 'error', 'message' => 'foo', 'params' => array( 1, 2 ) ) ), $status->errors );
+ }
+
+ /**
* @dataProvider provideSetResult
* @covers Status::setResult
*/
@@ -109,7 +120,9 @@ class StatusTest extends MediaWikiLangTestCase {
public function testIsGood( $ok, $errors, $expected ) {
$status = new Status();
$status->ok = $ok;
- $status->errors = $errors;
+ foreach ( $errors as $error ) {
+ $status->warning( $error );
+ }
$this->assertEquals( $expected, $status->isGood() );
}
diff --git a/tests/phpunit/includes/TemplateParserTest.php b/tests/phpunit/includes/TemplateParserTest.php
new file mode 100644
index 00000000..81854ff3
--- /dev/null
+++ b/tests/phpunit/includes/TemplateParserTest.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @group Templates
+ */
+class TemplateParserTest extends MediaWikiTestCase {
+
+ protected $templateDir;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->setMwGlobals( array(
+ 'wgSecretKey' => 'foo',
+ 'wgMemc' => new EmptyBagOStuff(),
+ ) );
+
+ $this->templateDir = dirname( __DIR__ ) . '/data/templates/';
+ }
+
+ /**
+ * @dataProvider provideProcessTemplate
+ * @covers TemplateParser::processTemplate
+ * @covers TemplateParser::getTemplate
+ * @covers TemplateParser::getTemplateFilename
+ */
+ public function testProcessTemplate( $name, $args, $result, $exception = false ) {
+ if ( $exception ) {
+ $this->setExpectedException( $exception );
+ }
+ $tp = new TemplateParser( $this->templateDir );
+ $this->assertEquals( $result, $tp->processTemplate( $name, $args ) );
+ }
+
+ public static function provideProcessTemplate() {
+ return array(
+ array(
+ 'foobar',
+ array(),
+ "hello world!\n"
+ ),
+ array(
+ 'foobar_args',
+ array(
+ 'planet' => 'world',
+ ),
+ "hello world!\n",
+ ),
+ array(
+ '../foobar',
+ array(),
+ false,
+ 'UnexpectedValueException'
+ ),
+ array(
+ 'nonexistenttemplate',
+ array(),
+ false,
+ 'RuntimeException',
+ )
+ );
+ }
+}
diff --git a/tests/phpunit/includes/TestUser.php b/tests/phpunit/includes/TestUser.php
index 610a6acd..754568d0 100644
--- a/tests/phpunit/includes/TestUser.php
+++ b/tests/phpunit/includes/TestUser.php
@@ -5,24 +5,41 @@
* like password if we log in via the API.
*/
class TestUser {
+ /**
+ * @deprecated Since 1.25. Use TestUser::getUser()->getName()
+ * @private
+ * @var string
+ */
public $username;
+
+ /**
+ * @deprecated Since 1.25. Use TestUser::getPassword()
+ * @private
+ * @var string
+ */
public $password;
- public $email;
- public $groups;
+
+ /**
+ * @deprecated Since 1.25. Use TestUser::getUser()
+ * @private
+ * @var User
+ */
public $user;
+ private function assertNotReal() {
+ global $wgDBprefix;
+ if ( $wgDBprefix !== MediaWikiTestCase::DB_PREFIX && $wgDBprefix !== MediaWikiTestCase::ORA_DB_PREFIX ) {
+ throw new MWException( "Can't create user on real database" );
+ }
+ }
+
public function __construct( $username, $realname = 'Real Name',
$email = 'sample@example.com', $groups = array()
) {
- $this->username = $username;
- $this->realname = $realname;
- $this->email = $email;
- $this->groups = $groups;
+ $this->assertNotReal();
- // don't allow user to hardcode or select passwords -- people sometimes run tests
- // on live wikis. Sometimes we create sysop users in these tests. A sysop user with
- // a known password would be a Bad Thing.
- $this->password = User::randomPassword();
+ $this->username = $username;
+ $this->password = 'TestUser';
$this->user = User::newFromName( $this->username );
$this->user->load();
@@ -31,32 +48,99 @@ class TestUser {
// But for now, we just need to create or update the user with the desired properties.
// we particularly need the new password, since we just generated it randomly.
// In core MediaWiki, there is no functionality to delete users, so this is the best we can do.
- if ( !$this->user->getID() ) {
+ if ( !$this->user->isLoggedIn() ) {
// create the user
$this->user = User::createNew(
$this->username, array(
- "email" => $this->email,
- "real_name" => $this->realname
+ "email" => $email,
+ "real_name" => $realname
)
);
+
if ( !$this->user ) {
- throw new Exception( "error creating user" );
+ throw new MWException( "Error creating TestUser " . $username );
}
}
- // update the user to use the new random password and other details
- $this->user->setPassword( $this->password );
- $this->user->setEmail( $this->email );
- $this->user->setRealName( $this->realname );
+ // Update the user to use the password and other details
+ $change = $this->setPassword( $this->password ) ||
+ $this->setEmail( $email ) ||
+ $this->setRealName( $realname );
// Adjust groups by adding any missing ones and removing any extras
$currentGroups = $this->user->getGroups();
- foreach ( array_diff( $this->groups, $currentGroups ) as $group ) {
+ foreach ( array_diff( $groups, $currentGroups ) as $group ) {
$this->user->addGroup( $group );
}
- foreach ( array_diff( $currentGroups, $this->groups ) as $group ) {
+ foreach ( array_diff( $currentGroups, $groups ) as $group ) {
$this->user->removeGroup( $group );
}
- $this->user->saveSettings();
+ if ( $change ) {
+ $this->user->saveSettings();
+ }
+ }
+
+ /**
+ * @param string $realname
+ * @return bool
+ */
+ private function setRealName( $realname ) {
+ if ( $this->user->getRealName() !== $realname ) {
+ $this->user->setRealName( $realname );
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param string $email
+ * @return bool
+ */
+ private function setEmail( $email ) {
+ if ( $this->user->getEmail() !== $email ) {
+ $this->user->setEmail( $email );
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param string $password
+ * @return bool
+ */
+ private function setPassword( $password ) {
+ $passwordFactory = $this->user->getPasswordFactory();
+ $oldDefaultType = $passwordFactory->getDefaultType();
+
+ // A is unsalted MD5 (thus fast) ... we don't care about security here, this is test only
+ $passwordFactory->setDefaultType( 'A' );
+ $newPassword = $passwordFactory->newFromPlaintext( $password, $this->user->getPassword() );
+
+ $change = false;
+ if ( !$this->user->getPassword()->equals( $newPassword ) ) {
+ // Password changed
+ $this->user->setPassword( $password );
+ $change = true;
+ }
+
+ $passwordFactory->setDefaultType( $oldDefaultType );
+
+ return $change;
+ }
+
+ /**
+ * @return User
+ */
+ public function getUser() {
+ return $this->user;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPassword() {
+ return $this->password;
}
}
diff --git a/tests/phpunit/includes/TestingAccessWrapper.php b/tests/phpunit/includes/TestingAccessWrapper.php
new file mode 100644
index 00000000..84c0f9b5
--- /dev/null
+++ b/tests/phpunit/includes/TestingAccessWrapper.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Circumvent access restrictions on object internals
+ *
+ * This can be helpful for writing tests that can probe object internals,
+ * without having to modify the class under test to accomodate.
+ *
+ * Wrap an object with private methods as follows:
+ * $title = TestingAccessWrapper::newFromObject( Title::newFromDBkey( $key ) );
+ *
+ * You can access private and protected instance methods and variables:
+ * $formatter = $title->getTitleFormatter();
+ *
+ * TODO:
+ * - Provide access to static methods and properties.
+ * - Organize other helper classes in tests/testHelpers.inc into a directory.
+ */
+class TestingAccessWrapper {
+ public $object;
+
+ /**
+ * Return the same object, without access restrictions.
+ */
+ public static function newFromObject( $object ) {
+ $wrapper = new TestingAccessWrapper();
+ $wrapper->object = $object;
+ return $wrapper;
+ }
+
+ public function __call( $method, $args ) {
+ $classReflection = new ReflectionClass( $this->object );
+ $methodReflection = $classReflection->getMethod( $method );
+ $methodReflection->setAccessible( true );
+ return $methodReflection->invokeArgs( $this->object, $args );
+ }
+
+ public function __set( $name, $value ) {
+ $classReflection = new ReflectionClass( $this->object );
+ $propertyReflection = $classReflection->getProperty( $name );
+ $propertyReflection->setAccessible( true );
+ $propertyReflection->setValue( $this->object, $value );
+ }
+
+ public function __get( $name ) {
+ $classReflection = new ReflectionClass( $this->object );
+ $propertyReflection = $classReflection->getProperty( $name );
+ $propertyReflection->setAccessible( true );
+ return $propertyReflection->getValue( $this->object );
+ }
+}
diff --git a/tests/phpunit/includes/TestingAccessWrapperTest.php b/tests/phpunit/includes/TestingAccessWrapperTest.php
new file mode 100644
index 00000000..7e5b91a1
--- /dev/null
+++ b/tests/phpunit/includes/TestingAccessWrapperTest.php
@@ -0,0 +1,34 @@
+<?php
+
+class TestingAccessWrapperTest extends MediaWikiTestCase {
+ protected $raw;
+ protected $wrapped;
+
+ function setUp() {
+ parent::setUp();
+
+ require_once __DIR__ . '/../data/helpers/WellProtectedClass.php';
+ $this->raw = new WellProtectedClass();
+ $this->wrapped = TestingAccessWrapper::newFromObject( $this->raw );
+ }
+
+ function testGetProperty() {
+ $this->assertSame( 1, $this->wrapped->property );
+ }
+
+ function testSetProperty() {
+ $this->wrapped->property = 10;
+ $this->assertSame( 10, $this->wrapped->property );
+ $this->assertSame( 10, $this->raw->getProperty() );
+ }
+
+ function testCallMethod() {
+ $this->wrapped->incrementPropertyValue();
+ $this->assertSame( 2, $this->wrapped->property );
+ $this->assertSame( 2, $this->raw->getProperty() );
+ }
+
+ function testCallMethodTwoArgs() {
+ $this->assertSame( 'two', $this->wrapped->whatSecondArg( 'one', 'two' ) );
+ }
+}
diff --git a/tests/phpunit/includes/TitleMethodsTest.php b/tests/phpunit/includes/TitleMethodsTest.php
index 5904facd..e186438b 100644
--- a/tests/phpunit/includes/TitleMethodsTest.php
+++ b/tests/phpunit/includes/TitleMethodsTest.php
@@ -7,7 +7,7 @@
* @note We don't make assumptions about the main namespace.
* But we do expect the Help namespace to contain Wikitext.
*/
-class TitleMethodsTest extends MediaWikiTestCase {
+class TitleMethodsTest extends MediaWikiLangTestCase {
protected function setUp() {
global $wgContLang;
@@ -297,4 +297,43 @@ class TitleMethodsTest extends MediaWikiTestCase {
$title = Title::newFromText( $title );
$this->assertEquals( $expectedBool, $title->isWikitextPage() );
}
+
+ public static function provideGetOtherPage() {
+ return array(
+ array( 'Main Page', 'Talk:Main Page' ),
+ array( 'Talk:Main Page', 'Main Page' ),
+ array( 'Help:Main Page', 'Help talk:Main Page' ),
+ array( 'Help talk:Main Page', 'Help:Main Page' ),
+ array( 'Special:FooBar', null ),
+ );
+ }
+
+ /**
+ * @dataProvider provideGetOtherpage
+ * @covers Title::getOtherPage
+ *
+ * @param string $text
+ * @param string|null $expected
+ */
+ public function testGetOtherPage( $text, $expected ) {
+ if ( $expected === null ) {
+ $this->setExpectedException( 'MWException' );
+ }
+
+ $title = Title::newFromText( $text );
+ $this->assertEquals( $expected, $title->getOtherPage()->getPrefixedText() );
+ }
+
+ public function testClearCaches() {
+ $linkCache = LinkCache::singleton();
+
+ $title1 = Title::newFromText( 'Foo' );
+ $linkCache->addGoodLinkObj( 23, $title1 );
+
+ Title::clearCaches();
+
+ $title2 = Title::newFromText( 'Foo' );
+ $this->assertNotSame( $title1, $title2, 'title cache should be empty' );
+ $this->assertEquals( 0, $linkCache->getGoodLinkID( 'Foo' ), 'link cache should be empty' );
+ }
}
diff --git a/tests/phpunit/includes/TitlePermissionTest.php b/tests/phpunit/includes/TitlePermissionTest.php
index d2400b3f..022c7d53 100644
--- a/tests/phpunit/includes/TitlePermissionTest.php
+++ b/tests/phpunit/includes/TitlePermissionTest.php
@@ -326,6 +326,10 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
$this->setUserPerm( null );
$this->assertEquals( $check[$action][0],
$this->title->getUserPermissionsErrors( $action, $this->user, true ) );
+ $this->assertEquals( $check[$action][0],
+ $this->title->getUserPermissionsErrors( $action, $this->user, 'full' ) );
+ $this->assertEquals( $check[$action][0],
+ $this->title->getUserPermissionsErrors( $action, $this->user, 'secure' ) );
global $wgGroupPermissions;
$old = $wgGroupPermissions;
@@ -333,11 +337,19 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
$this->assertEquals( $check[$action][1],
$this->title->getUserPermissionsErrors( $action, $this->user, true ) );
+ $this->assertEquals( $check[$action][1],
+ $this->title->getUserPermissionsErrors( $action, $this->user, 'full' ) );
+ $this->assertEquals( $check[$action][1],
+ $this->title->getUserPermissionsErrors( $action, $this->user, 'secure' ) );
$wgGroupPermissions = $old;
$this->setUserPerm( $action );
$this->assertEquals( $check[$action][2],
$this->title->getUserPermissionsErrors( $action, $this->user, true ) );
+ $this->assertEquals( $check[$action][2],
+ $this->title->getUserPermissionsErrors( $action, $this->user, 'full' ) );
+ $this->assertEquals( $check[$action][2],
+ $this->title->getUserPermissionsErrors( $action, $this->user, 'secure' ) );
$this->setUserPerm( $action );
$this->assertEquals( $check[$action][3],
@@ -403,7 +415,8 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
$this->setTitle( NS_USER );
$this->setUserPerm( '' );
- $this->assertEquals( array( array( 'badaccess-group0' ), array( 'namespaceprotected', 'User', 'bogus' ) ),
+ $this->assertEquals( array( array( 'badaccess-group0' ),
+ array( 'namespaceprotected', 'User', 'bogus' ) ),
$this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
$this->setTitle( NS_MEDIAWIKI );
@@ -630,7 +643,8 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
$this->assertEquals( false,
$this->title->userCan( 'bogus', $this->user ) );
- $this->assertEquals( array( array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ),
+ $this->assertEquals( array(
+ array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ),
array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ),
array( "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ) ),
$this->title->getUserPermissionsErrors( 'bogus', $this->user ) );
@@ -648,10 +662,10 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
public function testActionPermissions() {
$this->setUserPerm( array( "createpage" ) );
$this->setTitle( NS_MAIN, "test page" );
- $this->title->mTitleProtection['pt_create_perm'] = '';
- $this->title->mTitleProtection['pt_user'] = $this->user->getID();
- $this->title->mTitleProtection['pt_expiry'] = wfGetDB( DB_SLAVE )->getInfinity();
- $this->title->mTitleProtection['pt_reason'] = 'test';
+ $this->title->mTitleProtection['permission'] = '';
+ $this->title->mTitleProtection['user'] = $this->user->getID();
+ $this->title->mTitleProtection['expiry'] = wfGetDB( DB_SLAVE )->getInfinity();
+ $this->title->mTitleProtection['reason'] = 'test';
$this->title->mCascadeRestriction = false;
$this->assertEquals( array( array( 'titleprotected', 'Useruser', 'test' ) ),
@@ -659,7 +673,7 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
$this->assertEquals( false,
$this->title->userCan( 'create', $this->user ) );
- $this->title->mTitleProtection['pt_create_perm'] = 'sysop';
+ $this->title->mTitleProtection['permission'] = 'editprotected';
$this->setUserPerm( array( 'createpage', 'protect' ) );
$this->assertEquals( array( array( 'titleprotected', 'Useruser', 'test' ) ),
$this->title->getUserPermissionsErrors( 'create', $this->user ) );
diff --git a/tests/phpunit/includes/TitleTest.php b/tests/phpunit/includes/TitleTest.php
index fb58381f..d55f958b 100644
--- a/tests/phpunit/includes/TitleTest.php
+++ b/tests/phpunit/includes/TitleTest.php
@@ -14,6 +14,7 @@ class TitleTest extends MediaWikiTestCase {
'wgLang' => Language::factory( 'en' ),
'wgAllowUserJs' => false,
'wgDefaultLanguageVariant' => false,
+ 'wgMetaNamespace' => 'Project',
) );
}
@@ -324,36 +325,19 @@ class TitleTest extends MediaWikiTestCase {
$whitelistRegexp = array( $whitelistRegexp );
}
+ $this->setMwGlobals( array(
+ // So User::isEveryoneAllowed( 'read' ) === false
+ 'wgGroupPermissions' => array( '*' => array( 'read' => false ) ),
+ 'wgWhitelistRead' => array( 'some random non sense title' ),
+ 'wgWhitelistReadRegexp' => $whitelistRegexp,
+ ) );
+
$title = Title::newFromDBkey( $source );
- global $wgGroupPermissions;
- $oldPermissions = $wgGroupPermissions;
- // Disallow all so we can ensure our regex works
- $wgGroupPermissions = array();
- $wgGroupPermissions['*']['read'] = false;
-
- global $wgWhitelistRead;
- $oldWhitelist = $wgWhitelistRead;
- // Undo any LocalSettings explicite whitelists so they won't cause a
- // failing test to succeed. Set it to some random non sense just
- // to make sure we properly test Title::checkReadPermissions()
- $wgWhitelistRead = array( 'some random non sense title' );
-
- global $wgWhitelistReadRegexp;
- $oldWhitelistRegexp = $wgWhitelistReadRegexp;
- $wgWhitelistReadRegexp = $whitelistRegexp;
-
- // Just use $wgUser which in test is a user object for '127.0.0.1'
- global $wgUser;
- // Invalidate user rights cache to take in account $wgGroupPermissions
- // change above.
- $wgUser->clearInstanceCache();
- $errors = $title->userCan( $action, $wgUser );
-
- // Restore globals
- $wgGroupPermissions = $oldPermissions;
- $wgWhitelistRead = $oldWhitelist;
- $wgWhitelistReadRegexp = $oldWhitelistRegexp;
+ // New anonymous user with no rights
+ $user = new User;
+ $user->mRights = array();
+ $errors = $title->userCan( $action, $user );
if ( is_bool( $expected ) ) {
# Forge the assertion message depending on the assertion expectation
@@ -428,14 +412,14 @@ class TitleTest extends MediaWikiTestCase {
public function testGetPageViewLanguage( $expected, $titleText, $contLang,
$lang, $variant, $msg = ''
) {
- global $wgLanguageCode, $wgContLang, $wgLang, $wgDefaultLanguageVariant, $wgAllowUserJs;
-
// Setup environnement for this test
- $wgLanguageCode = $contLang;
- $wgContLang = Language::factory( $contLang );
- $wgLang = Language::factory( $lang );
- $wgDefaultLanguageVariant = $variant;
- $wgAllowUserJs = true;
+ $this->setMwGlobals( array(
+ 'wgLanguageCode' => $contLang,
+ 'wgContLang' => Language::factory( $contLang ),
+ 'wgLang' => Language::factory( $lang ),
+ 'wgDefaultLanguageVariant' => $variant,
+ 'wgAllowUserJs' => true,
+ ) );
$title = Title::newFromText( $titleText );
$this->assertInstanceOf( 'Title', $title,
diff --git a/tests/phpunit/includes/UserTest.php b/tests/phpunit/includes/UserTest.php
index af95a721..b74a7ead 100644
--- a/tests/phpunit/includes/UserTest.php
+++ b/tests/phpunit/includes/UserTest.php
@@ -214,8 +214,10 @@ class UserTest extends MediaWikiTestCase {
*/
public function testEditCount() {
$user = User::newFromName( 'UnitTestUser' );
- $user->loadDefaults();
- $user->addToDatabase();
+
+ if ( !$user->getId() ) {
+ $user->addToDatabase();
+ }
// let the user have a few (3) edits
$page = WikiPage::factory( Title::newFromText( 'Help:UserTest_EditCount' ) );
@@ -248,14 +250,17 @@ class UserTest extends MediaWikiTestCase {
*/
public function testOptions() {
$user = User::newFromName( 'UnitTestUser' );
- $user->addToDatabase();
- $user->setOption( 'someoption', 'test' );
+ if ( !$user->getId() ) {
+ $user->addToDatabase();
+ }
+
+ $user->setOption( 'userjs-someoption', 'test' );
$user->setOption( 'cols', 200 );
$user->saveSettings();
$user = User::newFromName( 'UnitTestUser' );
- $this->assertEquals( 'test', $user->getOption( 'someoption' ) );
+ $this->assertEquals( 'test', $user->getOption( 'userjs-someoption' ) );
$this->assertEquals( 200, $user->getOption( 'cols' ) );
}
@@ -266,9 +271,9 @@ class UserTest extends MediaWikiTestCase {
*/
public function testAnonOptions() {
global $wgDefaultUserOptions;
- $this->user->setOption( 'someoption', 'test' );
+ $this->user->setOption( 'userjs-someoption', 'test' );
$this->assertEquals( $wgDefaultUserOptions['cols'], $this->user->getOption( 'cols' ) );
- $this->assertEquals( 'test', $this->user->getOption( 'someoption' ) );
+ $this->assertEquals( 'test', $this->user->getOption( 'userjs-someoption' ) );
}
/**
@@ -276,12 +281,10 @@ class UserTest extends MediaWikiTestCase {
* @covers User::getPasswordExpired()
*/
public function testPasswordExpire() {
- global $wgPasswordExpireGrace;
- $wgTemp = $wgPasswordExpireGrace;
- $wgPasswordExpireGrace = 3600 * 24 * 7; // 7 days
+ $this->setMwGlobals( 'wgPasswordExpireGrace', 3600 * 24 * 7 ); // 7 days
$user = User::newFromName( 'UnitTestUser' );
- $user->loadDefaults();
+ $user->loadDefaults( 'UnitTestUser' );
$this->assertEquals( false, $user->getPasswordExpired() );
$ts = time() - ( 3600 * 24 * 1 ); // 1 day ago
@@ -291,8 +294,6 @@ class UserTest extends MediaWikiTestCase {
$ts = time() - ( 3600 * 24 * 10 ); // 10 days ago
$user->expirePassword( $ts );
$this->assertEquals( 'hard', $user->getPasswordExpired() );
-
- $wgPasswordExpireGrace = $wgTemp;
}
/**
@@ -343,8 +344,8 @@ class UserTest extends MediaWikiTestCase {
public function testGetCanonicalName( $name, $expectedArray, $msg ) {
foreach ( $expectedArray as $validate => $expected ) {
$this->assertEquals(
- User::getCanonicalName( $name, $validate === 'false' ? false : $validate ),
$expected,
+ User::getCanonicalName( $name, $validate === 'false' ? false : $validate ),
$msg . ' (' . $validate . ')'
);
}
@@ -352,8 +353,8 @@ class UserTest extends MediaWikiTestCase {
public static function provideGetCanonicalName() {
return array(
- array( ' trailing space ', array( 'creatable' => 'Trailing space' ), 'Trailing spaces' ),
- // @todo FIXME: Maybe the createable name should be 'Talk:Username' or false to reject?
+ array( ' Trailing space ', array( 'creatable' => 'Trailing space' ), 'Trailing spaces' ),
+ // @todo FIXME: Maybe the creatable name should be 'Talk:Username' or false to reject?
array( 'Talk:Username', array( 'creatable' => 'Username', 'usable' => 'Username',
'valid' => 'Username', 'false' => 'Talk:Username' ), 'Namespace prefix' ),
array( ' name with # hash', array( 'creatable' => false, 'usable' => false ), 'With hash' ),
@@ -366,4 +367,62 @@ class UserTest extends MediaWikiTestCase {
'false' => 'With / slash' ), 'With slash' ),
);
}
+
+ /**
+ * @covers User::equals
+ */
+ public function testEquals() {
+ $first = User::newFromName( 'EqualUser' );
+ $second = User::newFromName( 'EqualUser' );
+
+ $this->assertTrue( $first->equals( $first ) );
+ $this->assertTrue( $first->equals( $second ) );
+ $this->assertTrue( $second->equals( $first ) );
+
+ $third = User::newFromName( '0' );
+ $fourth = User::newFromName( '000' );
+
+ $this->assertFalse( $third->equals( $fourth ) );
+ $this->assertFalse( $fourth->equals( $third ) );
+
+ // Test users loaded from db with id
+ $user = User::newFromName( 'EqualUnitTestUser' );
+ if ( !$user->getId() ) {
+ $user->addToDatabase();
+ }
+
+ $id = $user->getId();
+
+ $fifth = User::newFromId( $id );
+ $sixth = User::newFromName( 'EqualUnitTestUser' );
+ $this->assertTrue( $fifth->equals( $sixth ) );
+ }
+
+ /**
+ * @covers User::getId
+ */
+ public function testGetId() {
+ $user = User::newFromName( 'UTSysop' );
+ $this->assertTrue( $user->getId() > 0 );
+
+ }
+
+ /**
+ * @covers User::isLoggedIn
+ * @covers User::isAnon
+ */
+ public function testLoggedIn() {
+ $user = User::newFromName( 'UTSysop' );
+ $this->assertTrue( $user->isLoggedIn() );
+ $this->assertFalse( $user->isAnon() );
+
+ // Non-existent users are perceived as anonymous
+ $user = User::newFromName( 'UTNonexistent' );
+ $this->assertFalse( $user->isLoggedIn() );
+ $this->assertTrue( $user->isAnon() );
+
+ $user = new User;
+ $this->assertFalse( $user->isLoggedIn() );
+ $this->assertTrue( $user->isAnon() );
+ }
}
diff --git a/tests/phpunit/includes/XmlSelectTest.php b/tests/phpunit/includes/XmlSelectTest.php
index 9f154bb7..0e03add4 100644
--- a/tests/phpunit/includes/XmlSelectTest.php
+++ b/tests/phpunit/includes/XmlSelectTest.php
@@ -166,7 +166,7 @@ class XmlSelectTest extends MediaWikiTestCase {
'razor'
);
- # inexistant keys should give us 'null'
+ # inexistent keys should give us 'null'
$this->assertEquals(
$this->select->getAttribute( 'I DO NOT EXIT' ),
null
diff --git a/tests/phpunit/includes/XmlTest.php b/tests/phpunit/includes/XmlTest.php
index e6558819..382e3d89 100644
--- a/tests/phpunit/includes/XmlTest.php
+++ b/tests/phpunit/includes/XmlTest.php
@@ -81,7 +81,7 @@ class XmlTest extends MediaWikiTestCase {
*/
public function testElementInputCanHaveAValueOfZero() {
$this->assertEquals(
- '<input name="name" value="0" class="mw-ui-input" />',
+ '<input name="name" value="0" />',
Xml::input( 'name', false, 0 ),
'Input with a value of 0 (bug 23797)'
);
@@ -152,7 +152,7 @@ class XmlTest extends MediaWikiTestCase {
$this->assertEquals(
'<label for="year">From year (and earlier):</label> ' .
- '<input id="year" maxlength="4" size="7" type="number" value="2011" name="year" class="mw-ui-input" /> ' .
+ '<input id="year" maxlength="4" size="7" type="number" value="2011" name="year" /> ' .
'<label for="month">From month (and earlier):</label> ' .
'<select id="month" name="month" class="mw-month-selector">' .
'<option value="-1">all</option>' . "\n" .
@@ -173,7 +173,7 @@ class XmlTest extends MediaWikiTestCase {
);
$this->assertEquals(
'<label for="year">From year (and earlier):</label> ' .
- '<input id="year" maxlength="4" size="7" type="number" value="2011" name="year" class="mw-ui-input" /> ' .
+ '<input id="year" maxlength="4" size="7" type="number" value="2011" name="year" /> ' .
'<label for="month">From month (and earlier):</label> ' .
'<select id="month" name="month" class="mw-month-selector">' .
'<option value="-1">all</option>' . "\n" .
@@ -207,7 +207,7 @@ class XmlTest extends MediaWikiTestCase {
$this->assertEquals(
'<label for="year">From year (and earlier):</label> ' .
- '<input id="year" maxlength="4" size="7" type="number" name="year" class="mw-ui-input" /> ' .
+ '<input id="year" maxlength="4" size="7" type="number" name="year" /> ' .
'<label for="month">From month (and earlier):</label> ' .
'<select id="month" name="month" class="mw-month-selector">' .
'<option value="-1">all</option>' . "\n" .
@@ -233,7 +233,7 @@ class XmlTest extends MediaWikiTestCase {
*/
public function testTextareaNoContent() {
$this->assertEquals(
- '<textarea name="name" id="name" cols="40" rows="5" class="mw-ui-input"></textarea>',
+ '<textarea name="name" id="name" cols="40" rows="5"></textarea>',
Xml::textarea( 'name', '' ),
'textarea() with not content'
);
@@ -244,7 +244,7 @@ class XmlTest extends MediaWikiTestCase {
*/
public function testTextareaAttribs() {
$this->assertEquals(
- '<textarea name="name" id="name" cols="20" rows="10" class="mw-ui-input">&lt;txt&gt;</textarea>',
+ '<textarea name="name" id="name" cols="20" rows="10">&lt;txt&gt;</textarea>',
Xml::textarea( 'name', '<txt>', 20, 10 ),
'textarea() with custom attribs'
);
diff --git a/tests/phpunit/includes/actions/ActionTest.php b/tests/phpunit/includes/actions/ActionTest.php
index cc6fb11a..3babb97f 100644
--- a/tests/phpunit/includes/actions/ActionTest.php
+++ b/tests/phpunit/includes/actions/ActionTest.php
@@ -3,7 +3,6 @@
/**
* @covers Action
*
- * @licence GNU GPL v2+
* @author Thiemo Mättig
*
* @group Action
@@ -20,7 +19,7 @@ class ActionTest extends MediaWikiTestCase {
'disabled' => false,
'view' => true,
'edit' => true,
- 'revisiondelete' => true,
+ 'revisiondelete' => 'SpecialPageAction',
'dummy' => true,
'string' => 'NamedDummyAction',
'declared' => 'NonExistingClassName',
@@ -117,6 +116,15 @@ class ActionTest extends MediaWikiTestCase {
$this->assertEquals( 'revisiondelete', $actionName );
}
+ public function testGetActionName_whenCanNotUseWikiPage_defaultsToView() {
+ $request = new FauxRequest( array( 'action' => 'edit' ) );
+ $context = new DerivativeContext( RequestContext::getMain() );
+ $context->setRequest( $request );
+ $actionName = Action::getActionName( $context );
+
+ $this->assertEquals( 'view', $actionName );
+ }
+
/**
* @dataProvider actionProvider
* @param string $requestedAction
diff --git a/tests/phpunit/includes/api/ApiContinuationManagerTest.php b/tests/phpunit/includes/api/ApiContinuationManagerTest.php
new file mode 100644
index 00000000..2edf0c6f
--- /dev/null
+++ b/tests/phpunit/includes/api/ApiContinuationManagerTest.php
@@ -0,0 +1,195 @@
+<?php
+
+/**
+ * @covers ApiContinuationManager
+ * @group API
+ */
+class ApiContinuationManagerTest extends MediaWikiTestCase {
+
+ private static function getManager( $continue, $allModules, $generatedModules ) {
+ $context = new DerivativeContext( RequestContext::getMain() );
+ $context->setRequest( new FauxRequest( array( 'continue' => $continue ) ) );
+ $main = new ApiMain( $context );
+ return new ApiContinuationManager( $main, $allModules, $generatedModules );
+ }
+
+ public function testContinuation() {
+ $allModules = array(
+ new MockApiQueryBase( 'mock1' ),
+ new MockApiQueryBase( 'mock2' ),
+ new MockApiQueryBase( 'mocklist' ),
+ );
+ $generator = new MockApiQueryBase( 'generator' );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( 'ApiMain', $manager->getSource() );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $manager->addContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $manager->addGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $this->assertSame( array( array(
+ 'mlcontinue' => 2,
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2',
+ ), false ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $manager->getRawContinuation() );
+
+ $result = new ApiResult( 0 );
+ $manager->setContinuationIntoResult( $result );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $manager->addGeneratorContinueParam( $generator, 'gcontinue', array( 3, 4 ) );
+ $this->assertSame( array( array(
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2|mocklist',
+ ), false ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'generator' => array( 'gcontinue' => '3|4' ),
+ ), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $manager->addGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $this->assertSame( array( array(
+ 'mlcontinue' => 2,
+ 'gcontinue' => 3,
+ 'continue' => 'gcontinue||',
+ ), true ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $manager->getRawContinuation() );
+
+ $result = new ApiResult( 0 );
+ $manager->setContinuationIntoResult( $result );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'gcontinue' => 3,
+ 'continue' => 'gcontinue||',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $this->assertSame( array( array(
+ 'gcontinue' => 3,
+ 'continue' => 'gcontinue||mocklist',
+ ), true ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $manager->addContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $this->assertSame( array( array(
+ 'mlcontinue' => 2,
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2',
+ ), false ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ ), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $this->assertSame( array( array(
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2|mocklist',
+ ), false ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ ), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $this->assertSame( array( array(
+ 'mlcontinue' => 2,
+ 'continue' => '-||mock1|mock2',
+ ), true ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ ), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $this->assertSame( array( array(), true ), $manager->getContinuation() );
+ $this->assertSame( array(), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '||mock2', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame(
+ array_values( array_diff_key( $allModules, array( 1 => 1 ) ) ),
+ $manager->getRunModules()
+ );
+
+ $manager = self::getManager( '-||', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( true, $manager->isGeneratorDone() );
+ $this->assertSame(
+ array_values( array_diff_key( $allModules, array( 0 => 0, 1 => 1 ) ) ),
+ $manager->getRunModules()
+ );
+
+ try {
+ self::getManager( 'foo', $allModules, array( 'mock1', 'mock2' ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UsageException $ex ) {
+ $this->assertSame(
+ 'Invalid continue param. You should pass the original value returned by the previous query',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $manager = self::getManager( '||mock2', array_slice( $allModules, 0, 2 ), array( 'mock1', 'mock2' ) );
+ try {
+ $manager->addContinueParam( $allModules[1], 'm2continue', 1 );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UnexpectedValueException $ex ) {
+ $this->assertSame(
+ 'Module \'mock2\' was not supposed to have been executed, but it was executed anyway',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $manager->addContinueParam( $allModules[2], 'mlcontinue', 1 );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UnexpectedValueException $ex ) {
+ $this->assertSame(
+ 'Module \'mocklist\' called ApiContinuationManager::addContinueParam but was not passed to ApiContinuationManager::__construct',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ }
+
+}
diff --git a/tests/phpunit/includes/api/ApiErrorFormatterTest.php b/tests/phpunit/includes/api/ApiErrorFormatterTest.php
new file mode 100644
index 00000000..8ebdf60f
--- /dev/null
+++ b/tests/phpunit/includes/api/ApiErrorFormatterTest.php
@@ -0,0 +1,351 @@
+<?php
+
+/**
+ * @group API
+ */
+class ApiErrorFormatterTest extends MediaWikiTestCase {
+
+ /**
+ * @covers ApiErrorFormatter
+ * @dataProvider provideErrorFormatter
+ */
+ public function testErrorFormatter( $format, $lang, $useDB,
+ $expect1, $expect2, $expect3
+ ) {
+ $result = new ApiResult( 8388608 );
+ $formatter = new ApiErrorFormatter( $result, Language::factory( $lang ), $format, $useDB );
+
+ // Add default type
+ $expect1[ApiResult::META_TYPE] = 'assoc';
+ $expect2[ApiResult::META_TYPE] = 'assoc';
+ $expect3[ApiResult::META_TYPE] = 'assoc';
+
+ $formatter->addWarning( 'string', 'mainpage' );
+ $formatter->addError( 'err', 'mainpage' );
+ $this->assertSame( $expect1, $result->getResultData(), 'Simple test' );
+
+ $result->reset();
+ $formatter->addWarning( 'foo', 'mainpage' );
+ $formatter->addWarning( 'foo', 'mainpage' );
+ $formatter->addWarning( 'foo', array( 'parentheses', 'foobar' ) );
+ $msg1 = wfMessage( 'mainpage' );
+ $formatter->addWarning( 'message', $msg1 );
+ $msg2 = new ApiMessage( 'mainpage', 'overriddenCode', array( 'overriddenData' => true ) );
+ $formatter->addWarning( 'messageWithData', $msg2 );
+ $formatter->addError( 'errWithData', $msg2 );
+ $this->assertSame( $expect2, $result->getResultData(), 'Complex test' );
+
+ $result->reset();
+ $status = Status::newGood();
+ $status->warning( 'mainpage' );
+ $status->warning( 'parentheses', 'foobar' );
+ $status->warning( $msg1 );
+ $status->warning( $msg2 );
+ $status->error( 'mainpage' );
+ $status->error( 'parentheses', 'foobar' );
+ $formatter->addMessagesFromStatus( 'status', $status );
+ $this->assertSame( $expect3, $result->getResultData(), 'Status test' );
+
+ $this->assertSame(
+ $expect3['errors']['status'],
+ $formatter->arrayFromStatus( $status, 'error' ),
+ 'arrayFromStatus test for error'
+ );
+ $this->assertSame(
+ $expect3['warnings']['status'],
+ $formatter->arrayFromStatus( $status, 'warning' ),
+ 'arrayFromStatus test for warning'
+ );
+ }
+
+ public static function provideErrorFormatter() {
+ $mainpagePlain = wfMessage( 'mainpage' )->useDatabase( false )->plain();
+ $parensPlain = wfMessage( 'parentheses', 'foobar' )->useDatabase( false )->plain();
+ $mainpageText = wfMessage( 'mainpage' )->inLanguage( 'de' )->text();
+ $parensText = wfMessage( 'parentheses', 'foobar' )->inLanguage( 'de' )->text();
+ $C = ApiResult::META_CONTENT;
+ $I = ApiResult::META_INDEXED_TAG_NAME;
+
+ return array(
+ array( 'wikitext', 'de', true,
+ array(
+ 'errors' => array(
+ 'err' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'string' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'errWithData' => array(
+ array( 'code' => 'overriddenCode', 'text' => $mainpageText,
+ 'overriddenData' => true, $C => 'text' ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'messageWithData' => array(
+ array( 'code' => 'overriddenCode', 'text' => $mainpageText,
+ 'overriddenData' => true, $C => 'text' ),
+ $I => 'warning',
+ ),
+ 'message' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ $I => 'warning',
+ ),
+ 'foo' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ array( 'code' => 'parentheses', 'text' => $parensText, $C => 'text' ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ array( 'code' => 'parentheses', 'text' => $parensText, $C => 'text' ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ array( 'code' => 'parentheses', 'text' => $parensText, $C => 'text' ),
+ array( 'code' => 'overriddenCode', 'text' => $mainpageText,
+ 'overriddenData' => true, $C => 'text' ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ ),
+ array( 'raw', 'fr', true,
+ array(
+ 'errors' => array(
+ 'err' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'string' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'errWithData' => array(
+ array( 'code' => 'overriddenCode', 'message' => 'mainpage', 'params' => array( $I => 'param' ),
+ 'overriddenData' => true ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'messageWithData' => array(
+ array( 'code' => 'overriddenCode', 'message' => 'mainpage', 'params' => array( $I => 'param' ),
+ 'overriddenData' => true ),
+ $I => 'warning',
+ ),
+ 'message' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ $I => 'warning',
+ ),
+ 'foo' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ array( 'code' => 'parentheses', 'message' => 'parentheses', 'params' => array( 'foobar', $I => 'param' ) ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ array( 'code' => 'parentheses', 'message' => 'parentheses', 'params' => array( 'foobar', $I => 'param' ) ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ array( 'code' => 'parentheses', 'message' => 'parentheses', 'params' => array( 'foobar', $I => 'param' ) ),
+ array( 'code' => 'overriddenCode', 'message' => 'mainpage', 'params' => array( $I => 'param' ),
+ 'overriddenData' => true ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ ),
+ array( 'none', 'fr', true,
+ array(
+ 'errors' => array(
+ 'err' => array(
+ array( 'code' => 'mainpage' ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'string' => array(
+ array( 'code' => 'mainpage' ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'errWithData' => array(
+ array( 'code' => 'overriddenCode', 'overriddenData' => true ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'messageWithData' => array(
+ array( 'code' => 'overriddenCode', 'overriddenData' => true ),
+ $I => 'warning',
+ ),
+ 'message' => array(
+ array( 'code' => 'mainpage' ),
+ $I => 'warning',
+ ),
+ 'foo' => array(
+ array( 'code' => 'mainpage' ),
+ array( 'code' => 'parentheses' ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage' ),
+ array( 'code' => 'parentheses' ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage' ),
+ array( 'code' => 'parentheses' ),
+ array( 'code' => 'overriddenCode', 'overriddenData' => true ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @covers ApiErrorFormatter_BackCompat
+ */
+ public function testErrorFormatterBC() {
+ $mainpagePlain = wfMessage( 'mainpage' )->useDatabase( false )->plain();
+ $parensPlain = wfMessage( 'parentheses', 'foobar' )->useDatabase( false )->plain();
+
+ $result = new ApiResult( 8388608 );
+ $formatter = new ApiErrorFormatter_BackCompat( $result );
+
+ $formatter->addWarning( 'string', 'mainpage' );
+ $formatter->addError( 'err', 'mainpage' );
+ $this->assertSame( array(
+ 'error' => array(
+ 'code' => 'mainpage',
+ 'info' => $mainpagePlain,
+ ),
+ 'warnings' => array(
+ 'string' => array(
+ 'warnings' => $mainpagePlain,
+ ApiResult::META_CONTENT => 'warnings',
+ ),
+ ),
+ ApiResult::META_TYPE => 'assoc',
+ ), $result->getResultData(), 'Simple test' );
+
+ $result->reset();
+ $formatter->addWarning( 'foo', 'mainpage' );
+ $formatter->addWarning( 'foo', 'mainpage' );
+ $formatter->addWarning( 'foo', array( 'parentheses', 'foobar' ) );
+ $msg1 = wfMessage( 'mainpage' );
+ $formatter->addWarning( 'message', $msg1 );
+ $msg2 = new ApiMessage( 'mainpage', 'overriddenCode', array( 'overriddenData' => true ) );
+ $formatter->addWarning( 'messageWithData', $msg2 );
+ $formatter->addError( 'errWithData', $msg2 );
+ $this->assertSame( array(
+ 'error' => array(
+ 'code' => 'overriddenCode',
+ 'info' => $mainpagePlain,
+ 'overriddenData' => true,
+ ),
+ 'warnings' => array(
+ 'messageWithData' => array(
+ 'warnings' => $mainpagePlain,
+ ApiResult::META_CONTENT => 'warnings',
+ ),
+ 'message' => array(
+ 'warnings' => $mainpagePlain,
+ ApiResult::META_CONTENT => 'warnings',
+ ),
+ 'foo' => array(
+ 'warnings' => "$mainpagePlain\n$parensPlain",
+ ApiResult::META_CONTENT => 'warnings',
+ ),
+ ),
+ ApiResult::META_TYPE => 'assoc',
+ ), $result->getResultData(), 'Complex test' );
+
+ $result->reset();
+ $status = Status::newGood();
+ $status->warning( 'mainpage' );
+ $status->warning( 'parentheses', 'foobar' );
+ $status->warning( $msg1 );
+ $status->warning( $msg2 );
+ $status->error( 'mainpage' );
+ $status->error( 'parentheses', 'foobar' );
+ $formatter->addMessagesFromStatus( 'status', $status );
+ $this->assertSame( array(
+ 'error' => array(
+ 'code' => 'parentheses',
+ 'info' => $parensPlain,
+ ),
+ 'warnings' => array(
+ 'status' => array(
+ 'warnings' => "$mainpagePlain\n$parensPlain",
+ ApiResult::META_CONTENT => 'warnings',
+ ),
+ ),
+ ApiResult::META_TYPE => 'assoc',
+ ), $result->getResultData(), 'Status test' );
+
+ $I = ApiResult::META_INDEXED_TAG_NAME;
+ $this->assertSame(
+ array(
+ array( 'type' => 'error', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ array( 'type' => 'error', 'message' => 'parentheses', 'params' => array( 'foobar', $I => 'param' ) ),
+ $I => 'error',
+ ),
+ $formatter->arrayFromStatus( $status, 'error' ),
+ 'arrayFromStatus test for error'
+ );
+ $this->assertSame(
+ array(
+ array( 'type' => 'warning', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ array( 'type' => 'warning', 'message' => 'parentheses', 'params' => array( 'foobar', $I => 'param' ) ),
+ array( 'message' => 'mainpage', 'params' => array( $I => 'param' ), 'type' => 'warning' ),
+ array( 'message' => 'mainpage', 'params' => array( $I => 'param' ), 'type' => 'warning' ),
+ $I => 'warning',
+ ),
+ $formatter->arrayFromStatus( $status, 'warning' ),
+ 'arrayFromStatus test for warning'
+ );
+ }
+
+}
diff --git a/tests/phpunit/includes/api/ApiLoginTest.php b/tests/phpunit/includes/api/ApiLoginTest.php
index 67a75f36..88a99e9b 100644
--- a/tests/phpunit/includes/api/ApiLoginTest.php
+++ b/tests/phpunit/includes/api/ApiLoginTest.php
@@ -123,7 +123,8 @@ class ApiLoginTest extends ApiTestCase {
"lgname" => $user->username,
"lgpassword" => $user->password
)
- )
+ ),
+ __METHOD__
);
$req->execute();
diff --git a/tests/phpunit/includes/api/ApiMainTest.php b/tests/phpunit/includes/api/ApiMainTest.php
index 780cf9ed..e8ef1804 100644
--- a/tests/phpunit/includes/api/ApiMainTest.php
+++ b/tests/phpunit/includes/api/ApiMainTest.php
@@ -2,7 +2,6 @@
/**
* @group API
- * @group Database
* @group medium
*
* @covers ApiMain
@@ -10,41 +9,25 @@
class ApiMainTest extends ApiTestCase {
/**
- * Test that the API will accept a FauxRequest and execute. The help action
- * (default) throws a UsageException. Just validate we're getting proper XML
- *
- * @expectedException UsageException
+ * Test that the API will accept a FauxRequest and execute.
*/
public function testApi() {
$api = new ApiMain(
- new FauxRequest( array( 'action' => 'help', 'format' => 'xml' ) )
+ new FauxRequest( array( 'action' => 'query', 'meta' => 'siteinfo' ) )
);
$api->execute();
- $api->getPrinter()->setBufferResult( true );
- $api->printResult( false );
- $resp = $api->getPrinter()->getBuffer();
-
- libxml_use_internal_errors( true );
- $sxe = simplexml_load_string( $resp );
- $this->assertNotInternalType( "bool", $sxe );
- $this->assertThat( $sxe, $this->isInstanceOf( "SimpleXMLElement" ) );
+ $data = $api->getResult()->getResultData();
+ $this->assertInternalType( 'array', $data );
+ $this->assertArrayHasKey( 'query', $data );
}
public static function provideAssert() {
- $anon = new User();
- $bot = new User();
- $bot->setName( 'Bot' );
- $bot->addToDatabase();
- $bot->addGroup( 'bot' );
- $user = new User();
- $user->setName( 'User' );
- $user->addToDatabase();
return array(
- array( $anon, 'user', 'assertuserfailed' ),
- array( $user, 'user', false ),
- array( $user, 'bot', 'assertbotfailed' ),
- array( $bot, 'user', false ),
- array( $bot, 'bot', false ),
+ array( false, array(), 'user', 'assertuserfailed' ),
+ array( true, array(), 'user', false ),
+ array( true, array(), 'bot', 'assertbotfailed' ),
+ array( true, array( 'bot' ), 'user', false ),
+ array( true, array( 'bot' ), 'bot', false ),
);
}
@@ -53,11 +36,17 @@ class ApiMainTest extends ApiTestCase {
*
* @covers ApiMain::checkAsserts
* @dataProvider provideAssert
- * @param User $user
+ * @param bool $registered
+ * @param array $rights
* @param string $assert
* @param string|bool $error False if no error expected
*/
- public function testAssert( $user, $assert, $error ) {
+ public function testAssert( $registered, $rights, $assert, $error ) {
+ $user = new User();
+ if ( $registered ) {
+ $user->setId( 1 );
+ }
+ $user->mRights = $rights;
try {
$this->doApiRequest( array(
'action' => 'query',
@@ -69,4 +58,25 @@ class ApiMainTest extends ApiTestCase {
}
}
+ /**
+ * Test if all classes in the main module manager exists
+ */
+ public function testClassNamesInModuleManager() {
+ global $wgAutoloadLocalClasses, $wgAutoloadClasses;
+
+ // wgAutoloadLocalClasses has precedence, just like in includes/AutoLoader.php
+ $classes = $wgAutoloadLocalClasses + $wgAutoloadClasses;
+
+ $api = new ApiMain(
+ new FauxRequest( array( 'action' => 'query', 'meta' => 'siteinfo' ) )
+ );
+ $modules = $api->getModuleManager()->getNamesWithClasses();
+ foreach( $modules as $name => $class ) {
+ $this->assertArrayHasKey(
+ $class,
+ $classes,
+ 'Class ' . $class . ' for api module ' . $name . ' not in autoloader (with exact case)'
+ );
+ }
+ }
}
diff --git a/tests/phpunit/includes/api/ApiMessageTest.php b/tests/phpunit/includes/api/ApiMessageTest.php
new file mode 100644
index 00000000..6c3ce60d
--- /dev/null
+++ b/tests/phpunit/includes/api/ApiMessageTest.php
@@ -0,0 +1,103 @@
+<?php
+
+/**
+ * @group API
+ */
+class ApiMessageTest extends MediaWikiTestCase {
+
+ private function compareMessages( $msg, $msg2 ) {
+ $this->assertSame( $msg->getKey(), $msg2->getKey(), 'getKey' );
+ $this->assertSame( $msg->getKeysToTry(), $msg2->getKeysToTry(), 'getKeysToTry' );
+ $this->assertSame( $msg->getParams(), $msg2->getParams(), 'getParams' );
+ $this->assertSame( $msg->getFormat(), $msg2->getFormat(), 'getFormat' );
+ $this->assertSame( $msg->getLanguage(), $msg2->getLanguage(), 'getLanguage' );
+
+ $msg = TestingAccessWrapper::newFromObject( $msg );
+ $msg2 = TestingAccessWrapper::newFromObject( $msg2 );
+ foreach ( array( 'interface', 'useDatabase', 'title' ) as $key ) {
+ $this->assertSame( $msg->$key, $msg2->$key, $key );
+ }
+ }
+
+ /**
+ * @covers ApiMessage
+ */
+ public function testApiMessage() {
+ $msg = new Message( array( 'foo', 'bar' ), array( 'baz' ) );
+ $msg->inLanguage( 'de' )->title( Title::newMainPage() );
+ $msg2 = new ApiMessage( $msg, 'code', array( 'data' ) );
+ $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 );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+
+ $msg = new Message( 'foo' );
+ $msg2 = new ApiMessage( 'foo' );
+ $this->compareMessages( $msg, $msg2 );
+ $this->assertEquals( 'foo', $msg2->getApiCode() );
+ $this->assertEquals( array(), $msg2->getApiData() );
+
+ $msg2->setApiCode( 'code', array( 'data' ) );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+ $msg2->setApiCode( null );
+ $this->assertEquals( 'foo', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+ $msg2->setApiData( array( 'data2' ) );
+ $this->assertEquals( array( 'data2' ), $msg2->getApiData() );
+ }
+
+ /**
+ * @covers ApiRawMessage
+ */
+ public function testApiRawMessage() {
+ $msg = new RawMessage( 'foo', array( 'baz' ) );
+ $msg->inLanguage( 'de' )->title( Title::newMainPage() );
+ $msg2 = new ApiRawMessage( $msg, 'code', array( 'data' ) );
+ $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 );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+
+ $msg = new RawMessage( 'foo' );
+ $msg2 = new ApiRawMessage( 'foo', 'code', array( 'data' ) );
+ $this->compareMessages( $msg, $msg2 );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+
+ $msg2->setApiCode( 'code', array( 'data' ) );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+ $msg2->setApiCode( null );
+ $this->assertEquals( 'foo', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+ $msg2->setApiData( array( 'data2' ) );
+ $this->assertEquals( array( 'data2' ), $msg2->getApiData() );
+ }
+
+ /**
+ * @covers ApiMessage::create
+ */
+ public function testApiMessageCreate() {
+ $this->assertInstanceOf( 'ApiMessage', ApiMessage::create( new Message( 'mainpage' ) ) );
+ $this->assertInstanceOf( 'ApiRawMessage', ApiMessage::create( new RawMessage( 'mainpage' ) ) );
+ $this->assertInstanceOf( 'ApiMessage', ApiMessage::create( 'mainpage' ) );
+
+ $msg = new ApiMessage( 'mainpage' );
+ $this->assertSame( $msg, ApiMessage::create( $msg ) );
+
+ $msg = new ApiRawMessage( 'mainpage' );
+ $this->assertSame( $msg, ApiMessage::create( $msg ) );
+ }
+
+}
diff --git a/tests/phpunit/includes/api/ApiOptionsTest.php b/tests/phpunit/includes/api/ApiOptionsTest.php
index 5f955bbc..51154ae3 100644
--- a/tests/phpunit/includes/api/ApiOptionsTest.php
+++ b/tests/phpunit/includes/api/ApiOptionsTest.php
@@ -17,8 +17,6 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
/** @var DerivativeContext */
private $mContext;
- private $mOldGetPreferencesHooks;
-
private static $Success = array( 'options' => 'success' );
protected function setUp() {
@@ -50,21 +48,11 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
$this->mTested = new ApiOptions( $main, 'options' );
- global $wgHooks;
- if ( !isset( $wgHooks['GetPreferences'] ) ) {
- $wgHooks['GetPreferences'] = array();
- }
- $this->mOldGetPreferencesHooks = $wgHooks['GetPreferences'];
- $wgHooks['GetPreferences'][] = array( $this, 'hookGetPreferences' );
- }
-
- protected function tearDown() {
- global $wgHooks;
-
- $wgHooks['GetPreferences'] = $this->mOldGetPreferencesHooks;
- $this->mOldGetPreferencesHooks = false;
-
- parent::tearDown();
+ $this->mergeMwGlobalArrayValue( 'wgHooks', array(
+ 'GetPreferences' => array(
+ array( $this, 'hookGetPreferences' )
+ )
+ ) );
}
public function hookGetPreferences( $user, &$preferences ) {
@@ -150,7 +138,7 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
$this->mContext->setRequest( new FauxRequest( $request, true, $this->mSession ) );
$this->mTested->execute();
- return $this->mTested->getResult()->getData();
+ return $this->mTested->getResult()->getResultData( null, array( 'Strip' => 'all' ) );
}
/**
@@ -408,7 +396,7 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
'options' => 'success',
'warnings' => array(
'options' => array(
- '*' => "Validation error for 'special': cannot be set by this module"
+ 'warnings' => "Validation error for 'special': cannot be set by this module"
)
)
), $response );
@@ -431,7 +419,7 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
'options' => 'success',
'warnings' => array(
'options' => array(
- '*' => "Validation error for 'unknownOption': not a valid preference"
+ 'warnings' => "Validation error for 'unknownOption': not a valid preference"
)
)
), $response );
diff --git a/tests/phpunit/includes/api/ApiResultTest.php b/tests/phpunit/includes/api/ApiResultTest.php
new file mode 100644
index 00000000..f0d84552
--- /dev/null
+++ b/tests/phpunit/includes/api/ApiResultTest.php
@@ -0,0 +1,1563 @@
+<?php
+
+/**
+ * @covers ApiResult
+ * @group API
+ */
+class ApiResultTest extends MediaWikiTestCase {
+
+ /**
+ * @covers ApiResult
+ */
+ public function testStaticDataMethods() {
+ $arr = array();
+
+ ApiResult::setValue( $arr, 'setValue', '1' );
+
+ ApiResult::setValue( $arr, null, 'unnamed 1' );
+ ApiResult::setValue( $arr, null, 'unnamed 2' );
+
+ ApiResult::setValue( $arr, 'deleteValue', '2' );
+ ApiResult::unsetValue( $arr, 'deleteValue' );
+
+ ApiResult::setContentValue( $arr, 'setContentValue', '3' );
+
+ $this->assertSame( array(
+ 'setValue' => '1',
+ 'unnamed 1',
+ 'unnamed 2',
+ ApiResult::META_CONTENT => 'setContentValue',
+ 'setContentValue' => '3',
+ ), $arr );
+
+ try {
+ ApiResult::setValue( $arr, 'setValue', '99' );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Attempting to add element setValue=99, existing value is 1',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ try {
+ ApiResult::setContentValue( $arr, 'setContentValue2', '99' );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Attempting to set content element as setContentValue2 when setContentValue ' .
+ 'is already set as the content element',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ ApiResult::setValue( $arr, 'setValue', '99', ApiResult::OVERRIDE );
+ $this->assertSame( '99', $arr['setValue'] );
+
+ ApiResult::setContentValue( $arr, 'setContentValue2', '99', ApiResult::OVERRIDE );
+ $this->assertSame( 'setContentValue2', $arr[ApiResult::META_CONTENT] );
+
+ $arr = array( 'foo' => 1, 'bar' => 1 );
+ ApiResult::setValue( $arr, 'top', '2', ApiResult::ADD_ON_TOP );
+ ApiResult::setValue( $arr, null, '2', ApiResult::ADD_ON_TOP );
+ ApiResult::setValue( $arr, 'bottom', '2' );
+ ApiResult::setValue( $arr, 'foo', '2', ApiResult::OVERRIDE );
+ ApiResult::setValue( $arr, 'bar', '2', ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP );
+ $this->assertSame( array( 0, 'top', 'foo', 'bar', 'bottom' ), array_keys( $arr ) );
+
+ $arr = array();
+ ApiResult::setValue( $arr, 'sub', array( 'foo' => 1 ) );
+ ApiResult::setValue( $arr, 'sub', array( 'bar' => 1 ) );
+ $this->assertSame( array( 'sub' => array( 'foo' => 1, 'bar' => 1 ) ), $arr );
+
+ try {
+ ApiResult::setValue( $arr, 'sub', array( 'foo' => 2, 'baz' => 2 ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Conflicting keys (foo) when attempting to merge element sub',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $arr = array();
+ $title = Title::newFromText( "MediaWiki:Foobar" );
+ $obj = new stdClass;
+ $obj->foo = 1;
+ $obj->bar = 2;
+ ApiResult::setValue( $arr, 'title', $title );
+ ApiResult::setValue( $arr, 'obj', $obj );
+ $this->assertSame( array(
+ 'title' => (string)$title,
+ 'obj' => array( 'foo' => 1, 'bar' => 2, ApiResult::META_TYPE => 'assoc' ),
+ ), $arr );
+
+ $fh = tmpfile();
+ try {
+ ApiResult::setValue( $arr, 'file', $fh );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ ApiResult::setValue( $arr, null, $fh );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $obj->file = $fh;
+ ApiResult::setValue( $arr, 'sub', $obj );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $obj->file = $fh;
+ ApiResult::setValue( $arr, null, $obj );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ fclose( $fh );
+
+ try {
+ ApiResult::setValue( $arr, 'inf', INF );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add non-finite floats to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ ApiResult::setValue( $arr, null, INF );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add non-finite floats to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ ApiResult::setValue( $arr, 'nan', NAN );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add non-finite floats to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ ApiResult::setValue( $arr, null, NAN );
+ $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' );
+ ApiResult::setValue( $arr, 'baz', $result2 );
+ $this->assertSame( array(
+ 'baz' => array(
+ ApiResult::META_TYPE => 'assoc',
+ 'foo' => 'bar',
+ )
+ ), $arr );
+
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', "foo\x80bar" );
+ ApiResult::setValue( $arr, 'bar', "a\xcc\x81" );
+ ApiResult::setValue( $arr, 'baz', 74 );
+ ApiResult::setValue( $arr, null, "foo\x80bar" );
+ ApiResult::setValue( $arr, null, "a\xcc\x81" );
+ $this->assertSame( array(
+ 'foo' => "foo\xef\xbf\xbdbar",
+ 'bar' => "\xc3\xa1",
+ 'baz' => 74,
+ 0 => "foo\xef\xbf\xbdbar",
+ 1 => "\xc3\xa1",
+ ), $arr );
+ }
+
+ /**
+ * @covers ApiResult
+ */
+ public function testInstanceDataMethods() {
+ $result = new ApiResult( 8388608 );
+
+ $result->addValue( null, 'setValue', '1' );
+
+ $result->addValue( null, null, 'unnamed 1' );
+ $result->addValue( null, null, 'unnamed 2' );
+
+ $result->addValue( null, 'deleteValue', '2' );
+ $result->removeValue( null, 'deleteValue' );
+
+ $result->addValue( array( 'a', 'b' ), 'deleteValue', '3' );
+ $result->removeValue( array( 'a', 'b', 'deleteValue' ), null, '3' );
+
+ $result->addContentValue( null, 'setContentValue', '3' );
+
+ $this->assertSame( array(
+ 'setValue' => '1',
+ 'unnamed 1',
+ 'unnamed 2',
+ 'a' => array( 'b' => array() ),
+ 'setContentValue' => '3',
+ ApiResult::META_TYPE => 'assoc',
+ ApiResult::META_CONTENT => 'setContentValue',
+ ), $result->getResultData() );
+ $this->assertSame( 20, $result->getSize() );
+
+ try {
+ $result->addValue( null, 'setValue', '99' );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Attempting to add element setValue=99, existing value is 1',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ try {
+ $result->addContentValue( null, 'setContentValue2', '99' );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Attempting to set content element as setContentValue2 when setContentValue ' .
+ 'is already set as the content element',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $result->addValue( null, 'setValue', '99', ApiResult::OVERRIDE );
+ $this->assertSame( '99', $result->getResultData( array( 'setValue' ) ) );
+
+ $result->addContentValue( null, 'setContentValue2', '99', ApiResult::OVERRIDE );
+ $this->assertSame( 'setContentValue2',
+ $result->getResultData( array( ApiResult::META_CONTENT ) ) );
+
+ $result->reset();
+ $this->assertSame( array(
+ ApiResult::META_TYPE => 'assoc',
+ ), $result->getResultData() );
+ $this->assertSame( 0, $result->getSize() );
+
+ $result->addValue( null, 'foo', 1 );
+ $result->addValue( null, 'bar', 1 );
+ $result->addValue( null, 'top', '2', ApiResult::ADD_ON_TOP );
+ $result->addValue( null, null, '2', ApiResult::ADD_ON_TOP );
+ $result->addValue( null, 'bottom', '2' );
+ $result->addValue( null, 'foo', '2', ApiResult::OVERRIDE );
+ $result->addValue( null, 'bar', '2', ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP );
+ $this->assertSame( array( 0, 'top', 'foo', 'bar', 'bottom', ApiResult::META_TYPE ),
+ array_keys( $result->getResultData() ) );
+
+ $result->reset();
+ $result->addValue( null, 'foo', array( 'bar' => 1 ) );
+ $result->addValue( array( 'foo', 'top' ), 'x', 2, ApiResult::ADD_ON_TOP );
+ $result->addValue( array( 'foo', 'bottom' ), 'x', 2 );
+ $this->assertSame( array( 'top', 'bar', 'bottom' ),
+ array_keys( $result->getResultData( array( 'foo' ) ) ) );
+
+ $result->reset();
+ $result->addValue( null, 'sub', array( 'foo' => 1 ) );
+ $result->addValue( null, 'sub', array( 'bar' => 1 ) );
+ $this->assertSame( array(
+ 'sub' => array( 'foo' => 1, 'bar' => 1 ),
+ ApiResult::META_TYPE => 'assoc',
+ ), $result->getResultData() );
+
+ try {
+ $result->addValue( null, 'sub', array( 'foo' => 2, 'baz' => 2 ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Conflicting keys (foo) when attempting to merge element sub',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $result->reset();
+ $title = Title::newFromText( "MediaWiki:Foobar" );
+ $obj = new stdClass;
+ $obj->foo = 1;
+ $obj->bar = 2;
+ $result->addValue( null, 'title', $title );
+ $result->addValue( null, 'obj', $obj );
+ $this->assertSame( array(
+ 'title' => (string)$title,
+ 'obj' => array( 'foo' => 1, 'bar' => 2, ApiResult::META_TYPE => 'assoc' ),
+ ApiResult::META_TYPE => 'assoc',
+ ), $result->getResultData() );
+
+ $fh = tmpfile();
+ try {
+ $result->addValue( null, 'file', $fh );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $result->addValue( null, null, $fh );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $obj->file = $fh;
+ $result->addValue( null, 'sub', $obj );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $obj->file = $fh;
+ $result->addValue( null, null, $obj );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ fclose( $fh );
+
+ try {
+ $result->addValue( null, 'inf', INF );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add non-finite floats to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $result->addValue( null, null, INF );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add non-finite floats to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $result->addValue( null, 'nan', NAN );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add non-finite floats to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $result->addValue( null, null, NAN );
+ $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(
+ 'limits' => array( 'foo' => 12 ),
+ ApiResult::META_TYPE => 'assoc',
+ ), $result->getResultData() );
+ $result->addParsedLimit( 'foo', 13 );
+ $this->assertSame( array(
+ 'limits' => array( 'foo' => 13 ),
+ ApiResult::META_TYPE => 'assoc',
+ ), $result->getResultData() );
+ $this->assertSame( null, $result->getResultData( array( 'foo', 'bar', 'baz' ) ) );
+ $this->assertSame( 13, $result->getResultData( array( 'limits', 'foo' ) ) );
+ try {
+ $result->getResultData( array( 'limits', 'foo', 'bar' ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Path limits.foo is not an array',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $result = new ApiResult( 10 );
+ $formatter = new ApiErrorFormatter( $result, Language::factory( 'en' ), 'none', false );
+ $result->setErrorFormatter( $formatter );
+ $this->assertFalse( $result->addValue( null, 'foo', '12345678901' ) );
+ $this->assertTrue( $result->addValue( null, 'foo', '12345678901', ApiResult::NO_SIZE_CHECK ) );
+ $this->assertSame( 0, $result->getSize() );
+ $result->reset();
+ $this->assertTrue( $result->addValue( null, 'foo', '1234567890' ) );
+ $this->assertFalse( $result->addValue( null, 'foo', '1' ) );
+ $result->removeValue( null, 'foo' );
+ $this->assertTrue( $result->addValue( null, 'foo', '1' ) );
+
+ $result = new ApiResult( 8388608 );
+ $result2 = new ApiResult( 8388608 );
+ $result2->addValue( null, 'foo', 'bar' );
+ $result->addValue( null, 'baz', $result2 );
+ $this->assertSame( array(
+ 'baz' => array(
+ 'foo' => 'bar',
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ ApiResult::META_TYPE => 'assoc',
+ ), $result->getResultData() );
+
+ $result = new ApiResult( 8388608 );
+ $result->addValue( null, 'foo', "foo\x80bar" );
+ $result->addValue( null, 'bar', "a\xcc\x81" );
+ $result->addValue( null, 'baz', 74 );
+ $result->addValue( null, null, "foo\x80bar" );
+ $result->addValue( null, null, "a\xcc\x81" );
+ $this->assertSame( array(
+ 'foo' => "foo\xef\xbf\xbdbar",
+ 'bar' => "\xc3\xa1",
+ 'baz' => 74,
+ 0 => "foo\xef\xbf\xbdbar",
+ 1 => "\xc3\xa1",
+ ApiResult::META_TYPE => 'assoc',
+ ), $result->getResultData() );
+ }
+
+ /**
+ * @covers ApiResult
+ */
+ public function testMetadata() {
+ $arr = array( 'foo' => array( 'bar' => array() ) );
+ $result = new ApiResult( 8388608 );
+ $result->addValue( null, 'foo', array( 'bar' => array() ) );
+
+ $expect = array(
+ 'foo' => array(
+ 'bar' => array(
+ ApiResult::META_INDEXED_TAG_NAME => 'ritn',
+ ApiResult::META_TYPE => 'default',
+ ),
+ ApiResult::META_INDEXED_TAG_NAME => 'ritn',
+ ApiResult::META_TYPE => 'default',
+ ),
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar' ),
+ ApiResult::META_TYPE => 'array',
+ );
+
+ ApiResult::setSubelementsList( $arr, 'foo' );
+ ApiResult::setSubelementsList( $arr, array( 'bar', 'baz' ) );
+ ApiResult::unsetSubelementsList( $arr, 'baz' );
+ ApiResult::setIndexedTagNameRecursive( $arr, 'ritn' );
+ ApiResult::setIndexedTagName( $arr, 'itn' );
+ ApiResult::setPreserveKeysList( $arr, 'foo' );
+ ApiResult::setPreserveKeysList( $arr, array( 'bar', 'baz' ) );
+ ApiResult::unsetPreserveKeysList( $arr, 'baz' );
+ ApiResult::setArrayTypeRecursive( $arr, 'default' );
+ ApiResult::setArrayType( $arr, 'array' );
+ $this->assertSame( $expect, $arr );
+
+ $result->addSubelementsList( null, 'foo' );
+ $result->addSubelementsList( null, array( 'bar', 'baz' ) );
+ $result->removeSubelementsList( null, 'baz' );
+ $result->addIndexedTagNameRecursive( null, 'ritn' );
+ $result->addIndexedTagName( null, 'itn' );
+ $result->addPreserveKeysList( null, 'foo' );
+ $result->addPreserveKeysList( null, array( 'bar', 'baz' ) );
+ $result->removePreserveKeysList( null, 'baz' );
+ $result->addArrayTypeRecursive( null, 'default' );
+ $result->addArrayType( null, 'array' );
+ $this->assertEquals( $expect, $result->getResultData() );
+
+ $arr = array( 'foo' => array( 'bar' => array() ) );
+ $expect = array(
+ 'foo' => array(
+ 'bar' => array(
+ ApiResult::META_TYPE => 'kvp',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ ApiResult::META_TYPE => 'kvp',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ ApiResult::META_TYPE => 'BCkvp',
+ ApiResult::META_KVP_KEY_NAME => 'bc',
+ );
+ ApiResult::setArrayTypeRecursive( $arr, 'kvp', 'key' );
+ ApiResult::setArrayType( $arr, 'BCkvp', 'bc' );
+ $this->assertSame( $expect, $arr );
+ }
+
+ /**
+ * @covers ApiResult
+ */
+ public function testUtilityFunctions() {
+ $arr = array(
+ 'foo' => array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ 'foo2' => (object)array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ '_dummy' => 'foobaz',
+ '_dummy2' => 'foobaz!',
+ );
+ $this->assertEquals( array(
+ 'foo' => array(
+ 'bar' => array(),
+ 'bar2' => (object)array(),
+ 'x' => 'ok',
+ ),
+ 'foo2' => (object)array(
+ 'bar' => array(),
+ 'bar2' => (object)array(),
+ 'x' => 'ok',
+ ),
+ '_dummy2' => 'foobaz!',
+ ), ApiResult::stripMetadata( $arr ), 'ApiResult::stripMetadata' );
+
+ $metadata = array();
+ $data = ApiResult::stripMetadataNonRecursive( $arr, $metadata );
+ $this->assertEquals( array(
+ 'foo' => array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ 'foo2' => (object)array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ '_dummy2' => 'foobaz!',
+ ), $data, 'ApiResult::stripMetadataNonRecursive ($data)' );
+ $this->assertEquals( array(
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ '_dummy' => 'foobaz',
+ ), $metadata, 'ApiResult::stripMetadataNonRecursive ($metadata)' );
+
+ $metadata = null;
+ $data = ApiResult::stripMetadataNonRecursive( (object)$arr, $metadata );
+ $this->assertEquals( (object)array(
+ 'foo' => array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ 'foo2' => (object)array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ '_dummy2' => 'foobaz!',
+ ), $data, 'ApiResult::stripMetadataNonRecursive on object ($data)' );
+ $this->assertEquals( array(
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ '_dummy' => 'foobaz',
+ ), $metadata, 'ApiResult::stripMetadataNonRecursive on object ($metadata)' );
+ }
+
+ /**
+ * @covers ApiResult
+ * @dataProvider provideTransformations
+ * @param string $label
+ * @param array $input
+ * @param array $transforms
+ * @param array|Exception $expect
+ */
+ public function testTransformations( $label, $input, $transforms, $expect ) {
+ $result = new ApiResult( false );
+ $result->addValue( null, 'test', $input );
+
+ if ( $expect instanceof Exception ) {
+ try {
+ $output = $result->getResultData( 'test', $transforms );
+ $this->fail( 'Expected exception not thrown', $label );
+ } catch ( Exception $ex ) {
+ $this->assertEquals( $ex, $expect, $label );
+ }
+ } else {
+ $output = $result->getResultData( 'test', $transforms );
+ $this->assertEquals( $expect, $output, $label );
+ }
+ }
+
+ public function provideTransformations() {
+ $kvp = function ( $keyKey, $key, $valKey, $value ) {
+ return array(
+ $keyKey => $key,
+ $valKey => $value,
+ ApiResult::META_PRESERVE_KEYS => array( $keyKey ),
+ ApiResult::META_CONTENT => $valKey,
+ ApiResult::META_TYPE => 'assoc',
+ );
+ };
+ $typeArr = array(
+ 'defaultArray' => array( 2 => 'a', 0 => 'b', 1 => 'c' ),
+ 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c' ),
+ 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c' ),
+ 'array' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'array' ),
+ 'BCarray' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'BCarray' ),
+ 'BCassoc' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'BCassoc' ),
+ 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => array( 'x' => 'a', 'y' => 'b', 'z' => array( 'c' ), ApiResult::META_TYPE => 'kvp' ),
+ 'BCkvp' => array( 'x' => 'a', 'y' => 'b',
+ ApiResult::META_TYPE => 'BCkvp',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1 ),
+ 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ );
+ $stripArr = array(
+ 'foo' => array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'baz' => array(
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ '_dummy' => 'foobaz',
+ '_dummy2' => 'foobaz!',
+ );
+
+ return array(
+ array(
+ 'BC: META_BC_BOOLS',
+ array(
+ 'BCtrue' => true,
+ 'BCfalse' => false,
+ 'true' => true,
+ 'false' => false,
+ ApiResult::META_BC_BOOLS => array( 0, 'true', 'false' ),
+ ),
+ array( 'BC' => array() ),
+ array(
+ 'BCtrue' => '',
+ 'true' => true,
+ 'false' => false,
+ ApiResult::META_BC_BOOLS => array( 0, 'true', 'false' ),
+ )
+ ),
+ array(
+ 'BC: META_BC_SUBELEMENTS',
+ array(
+ 'bc' => 'foo',
+ 'nobc' => 'bar',
+ ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
+ ),
+ array( 'BC' => array() ),
+ array(
+ 'bc' => array(
+ '*' => 'foo',
+ ApiResult::META_CONTENT => '*',
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ 'nobc' => 'bar',
+ ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
+ ),
+ ),
+ array(
+ 'BC: META_CONTENT',
+ array(
+ 'content' => '!!!',
+ ApiResult::META_CONTENT => 'content',
+ ),
+ array( 'BC' => array() ),
+ array(
+ '*' => '!!!',
+ ApiResult::META_CONTENT => '*',
+ ),
+ ),
+ array(
+ 'BC: BCkvp type',
+ array(
+ 'foo' => 'foo value',
+ 'bar' => 'bar value',
+ '_baz' => 'baz value',
+ ApiResult::META_TYPE => 'BCkvp',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
+ ),
+ array( 'BC' => array() ),
+ array(
+ $kvp( 'key', 'foo', '*', 'foo value' ),
+ $kvp( 'key', 'bar', '*', 'bar value' ),
+ $kvp( 'key', '_baz', '*', 'baz value' ),
+ ApiResult::META_TYPE => 'array',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
+ ),
+ ),
+ array(
+ 'BC: BCarray type',
+ array(
+ ApiResult::META_TYPE => 'BCarray',
+ ),
+ array( 'BC' => array() ),
+ array(
+ ApiResult::META_TYPE => 'default',
+ ),
+ ),
+ array(
+ 'BC: BCassoc type',
+ array(
+ ApiResult::META_TYPE => 'BCassoc',
+ ),
+ array( 'BC' => array() ),
+ array(
+ ApiResult::META_TYPE => 'default',
+ ),
+ ),
+ array(
+ 'BC: BCkvp exception',
+ array(
+ ApiResult::META_TYPE => 'BCkvp',
+ ),
+ array( 'BC' => array() ),
+ new UnexpectedValueException(
+ 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
+ ),
+ ),
+ array(
+ 'BC: nobool, no*, nosub',
+ array(
+ 'true' => true,
+ 'false' => false,
+ 'content' => 'content',
+ ApiResult::META_CONTENT => 'content',
+ 'bc' => 'foo',
+ ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
+ 'BCarray' => array( ApiResult::META_TYPE => 'BCarray' ),
+ 'BCassoc' => array( ApiResult::META_TYPE => 'BCassoc' ),
+ 'BCkvp' => array(
+ 'foo' => 'foo value',
+ 'bar' => 'bar value',
+ '_baz' => 'baz value',
+ ApiResult::META_TYPE => 'BCkvp',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
+ ),
+ ),
+ array( 'BC' => array( 'nobool', 'no*', 'nosub' ) ),
+ array(
+ 'true' => true,
+ 'false' => false,
+ 'content' => 'content',
+ 'bc' => 'foo',
+ 'BCarray' => array( ApiResult::META_TYPE => 'default' ),
+ 'BCassoc' => array( ApiResult::META_TYPE => 'default' ),
+ 'BCkvp' => array(
+ $kvp( 'key', 'foo', '*', 'foo value' ),
+ $kvp( 'key', 'bar', '*', 'bar value' ),
+ $kvp( 'key', '_baz', '*', 'baz value' ),
+ ApiResult::META_TYPE => 'array',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
+ ),
+ ApiResult::META_CONTENT => 'content',
+ ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
+ ),
+ ),
+
+ array(
+ 'Types: Normal transform',
+ $typeArr,
+ array( 'Types' => array() ),
+ array(
+ 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
+ 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'defaultAssoc2' => 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' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => array( 'x' => 'a', 'y' => 'b',
+ 'z' => array( 'c', ApiResult::META_TYPE => 'array' ),
+ ApiResult::META_TYPE => 'assoc'
+ ),
+ 'BCkvp' => array( 'x' => 'a', 'y' => 'b',
+ ApiResult::META_TYPE => 'assoc',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
+ 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ ),
+ array(
+ 'Types: AssocAsObject',
+ $typeArr,
+ 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' ),
+ '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' ),
+ 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => (object)array( 'x' => 'a', 'y' => 'b',
+ 'z' => array( 'c', ApiResult::META_TYPE => 'array' ),
+ ApiResult::META_TYPE => 'assoc'
+ ),
+ 'BCkvp' => (object)array( 'x' => 'a', 'y' => 'b',
+ ApiResult::META_TYPE => 'assoc',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
+ 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ ),
+ array(
+ 'Types: ArmorKVP',
+ $typeArr,
+ array( 'Types' => array( 'ArmorKVP' => 'name' ) ),
+ array(
+ 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
+ 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'defaultAssoc2' => 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' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => array(
+ $kvp( 'name', 'x', 'value', 'a' ),
+ $kvp( 'name', 'y', 'value', 'b' ),
+ $kvp( 'name', 'z', 'value', array( 'c', ApiResult::META_TYPE => 'array' ) ),
+ ApiResult::META_TYPE => 'array'
+ ),
+ 'BCkvp' => array(
+ $kvp( 'key', 'x', 'value', 'a' ),
+ $kvp( 'key', 'y', 'value', 'b' ),
+ ApiResult::META_TYPE => 'array',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
+ 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ ),
+ array(
+ 'Types: ArmorKVP + BC',
+ $typeArr,
+ array( 'BC' => array(), 'Types' => array( 'ArmorKVP' => 'name' ) ),
+ array(
+ 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
+ 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
+ 'BCarray' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'BCassoc' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'array' ),
+ 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => array(
+ $kvp( 'name', 'x', '*', 'a' ),
+ $kvp( 'name', 'y', '*', 'b' ),
+ $kvp( 'name', 'z', '*', array( 'c', ApiResult::META_TYPE => 'array' ) ),
+ ApiResult::META_TYPE => 'array'
+ ),
+ 'BCkvp' => array(
+ $kvp( 'key', 'x', '*', 'a' ),
+ $kvp( 'key', 'y', '*', 'b' ),
+ ApiResult::META_TYPE => 'array',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
+ 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ ),
+ array(
+ 'Types: ArmorKVP + AssocAsObject',
+ $typeArr,
+ 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' ),
+ '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' ),
+ 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => array(
+ (object)$kvp( 'name', 'x', 'value', 'a' ),
+ (object)$kvp( 'name', 'y', 'value', 'b' ),
+ (object)$kvp( 'name', 'z', 'value', array( 'c', ApiResult::META_TYPE => 'array' ) ),
+ ApiResult::META_TYPE => 'array'
+ ),
+ 'BCkvp' => array(
+ (object)$kvp( 'key', 'x', 'value', 'a' ),
+ (object)$kvp( 'key', 'y', 'value', 'b' ),
+ ApiResult::META_TYPE => 'array',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
+ 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ ),
+ array(
+ 'Types: BCkvp exception',
+ array(
+ ApiResult::META_TYPE => 'BCkvp',
+ ),
+ array( 'Types' => array() ),
+ new UnexpectedValueException(
+ 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
+ ),
+ ),
+
+ array(
+ 'Strip: With ArmorKVP + AssocAsObject transforms',
+ $typeArr,
+ array( 'Types' => array( 'ArmorKVP' => 'name', 'AssocAsObject' => true ), 'Strip' => 'all' ),
+ (object)array(
+ 'defaultArray' => array( 'b', 'c', 'a' ),
+ 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b', 0 => 'c' ),
+ 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b', 0 => 'c' ),
+ 'array' => array( 'a', 'c', 'b' ),
+ 'BCarray' => array( 'a', 'c', 'b' ),
+ 'BCassoc' => (object)array( 'a', 'b', 'c' ),
+ 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c' ),
+ 'kvp' => array(
+ (object)array( 'name' => 'x', 'value' => 'a' ),
+ (object)array( 'name' => 'y', 'value' => 'b' ),
+ (object)array( 'name' => 'z', 'value' => array( 'c' ) ),
+ ),
+ 'BCkvp' => array(
+ (object)array( 'key' => 'x', 'value' => 'a' ),
+ (object)array( 'key' => 'y', 'value' => 'b' ),
+ ),
+ 'emptyDefault' => array(),
+ 'emptyAssoc' => (object)array(),
+ '_dummy' => 1,
+ ),
+ ),
+
+ array(
+ 'Strip: all',
+ $stripArr,
+ array( 'Strip' => 'all' ),
+ array(
+ 'foo' => array(
+ 'bar' => array(),
+ 'baz' => array(),
+ 'x' => 'ok',
+ ),
+ '_dummy2' => 'foobaz!',
+ ),
+ ),
+ array(
+ 'Strip: base',
+ $stripArr,
+ array( 'Strip' => 'base' ),
+ array(
+ 'foo' => array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'baz' => array(
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ '_dummy2' => 'foobaz!',
+ ),
+ ),
+ array(
+ 'Strip: bc',
+ $stripArr,
+ array( 'Strip' => 'bc' ),
+ array(
+ 'foo' => array(
+ 'bar' => array(),
+ 'baz' => array(
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ),
+ 'x' => 'ok',
+ ),
+ '_dummy2' => 'foobaz!',
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ),
+ ),
+
+ array(
+ 'Custom transform',
+ array(
+ 'foo' => '?',
+ 'bar' => '?',
+ '_dummy' => '?',
+ '_dummy2' => '?',
+ '_dummy3' => '?',
+ ApiResult::META_CONTENT => 'foo',
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy2', '_dummy3' ),
+ ),
+ array(
+ 'Custom' => array( $this, 'customTransform' ),
+ 'BC' => array(),
+ 'Types' => array(),
+ 'Strip' => 'all'
+ ),
+ array(
+ '*' => 'FOO',
+ 'bar' => 'BAR',
+ 'baz' => array( 'a', 'b' ),
+ '_dummy2' => '_DUMMY2',
+ '_dummy3' => '_DUMMY3',
+ ApiResult::META_CONTENT => 'bar',
+ ),
+ ),
+ );
+
+ }
+
+ /**
+ * Custom transformer for testTransformations
+ * @param array &$data
+ * @param array &$metadata
+ */
+ public function customTransform( &$data, &$metadata ) {
+ // Prevent recursion
+ if ( isset( $metadata['_added'] ) ) {
+ $metadata[ApiResult::META_TYPE] = 'array';
+ return;
+ }
+
+ foreach ( $data as $k => $v ) {
+ $data[$k] = strtoupper( $k );
+ }
+ $data['baz'] = array( '_added' => 1, 'z' => 'b', 'y' => 'a' );
+ $metadata[ApiResult::META_PRESERVE_KEYS][0] = '_dummy';
+ $data[ApiResult::META_CONTENT] = 'bar';
+ }
+
+ /**
+ * @covers ApiResult
+ */
+ public function testDeprecatedFunctions() {
+ // Ignore ApiResult deprecation warnings during this test
+ set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
+ 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 ) ) {
+ return true;
+ }
+ return false;
+ } );
+ $reset = new ScopedCallback( 'restore_error_handler' );
+
+ $context = new DerivativeContext( RequestContext::getMain() );
+ $context->setConfig( new HashConfig( array(
+ 'APIModules' => array(),
+ 'APIFormatModules' => array(),
+ 'APIMaxResultSize' => 42,
+ ) ) );
+ $main = new ApiMain( $context );
+ $result = TestingAccessWrapper::newFromObject( new ApiResult( $main ) );
+ $this->assertSame( 42, $result->maxSize );
+ $this->assertSame( $main->getErrorFormatter(), $result->errorFormatter );
+ $this->assertSame( $main, $result->mainForContinuation );
+
+ $result = new ApiResult( 8388608 );
+
+ $result->addContentValue( null, 'test', 'content' );
+ $result->addContentValue( array( 'foo', 'bar' ), 'test', 'content' );
+ $result->addIndexedTagName( null, 'itn' );
+ $result->addSubelementsList( null, array( 'sub' ) );
+ $this->assertSame( array(
+ 'foo' => array(
+ 'bar' => array(
+ '*' => 'content',
+ ),
+ ),
+ '*' => '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' );
+ ApiResult::setContent( $arr, 'value2', 'foobar' );
+ $this->assertSame( array(
+ ApiResult::META_CONTENT => 'content',
+ 'content' => 'value',
+ 'foobar' => array(
+ ApiResult::META_CONTENT => 'content',
+ 'content' => 'value2',
+ ),
+ ), $arr );
+
+ $result = new ApiResult( 3 );
+ $formatter = new ApiErrorFormatter_BackCompat( $result );
+ $result->setErrorFormatter( $formatter );
+ $result->disableSizeCheck();
+ $this->assertTrue( $result->addValue( null, 'foo', '1234567890' ) );
+ $result->enableSizeCheck();
+ $this->assertSame( 0, $result->getSize() );
+ $this->assertFalse( $result->addValue( null, 'foo', '1234567890' ) );
+
+ $arr = array( 'foo' => array( 'bar' => 1 ) );
+ $result->setIndexedTagName_recursive( $arr, 'itn' );
+ $this->assertSame( array(
+ 'foo' => array(
+ 'bar' => 1,
+ ApiResult::META_INDEXED_TAG_NAME => 'itn'
+ ),
+ ), $arr );
+
+ $status = Status::newGood();
+ $status->fatal( 'parentheses', '1' );
+ $status->fatal( 'parentheses', '2' );
+ $status->warning( 'parentheses', '3' );
+ $status->warning( 'parentheses', '4' );
+ $this->assertSame( array(
+ array(
+ 'type' => 'error',
+ 'message' => 'parentheses',
+ 'params' => array(
+ 0 => '1',
+ ApiResult::META_INDEXED_TAG_NAME => 'param',
+ ),
+ ),
+ array(
+ 'type' => 'error',
+ 'message' => 'parentheses',
+ 'params' => array(
+ 0 => '2',
+ ApiResult::META_INDEXED_TAG_NAME => 'param',
+ ),
+ ),
+ ApiResult::META_INDEXED_TAG_NAME => 'error',
+ ), $result->convertStatusToArray( $status, 'error' ) );
+ $this->assertSame( array(
+ array(
+ 'type' => 'warning',
+ 'message' => 'parentheses',
+ 'params' => array(
+ 0 => '3',
+ ApiResult::META_INDEXED_TAG_NAME => 'param',
+ ),
+ ),
+ array(
+ 'type' => 'warning',
+ 'message' => 'parentheses',
+ 'params' => array(
+ 0 => '4',
+ ApiResult::META_INDEXED_TAG_NAME => 'param',
+ ),
+ ),
+ ApiResult::META_INDEXED_TAG_NAME => 'warning',
+ ), $result->convertStatusToArray( $status, 'warning' ) );
+ }
+
+ /**
+ * @covers ApiResult
+ */
+ public function testDeprecatedContinuation() {
+ // Ignore ApiResult deprecation warnings during this test
+ set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
+ if ( preg_match( '/Use of ApiResult::\S+ was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
+ return true;
+ }
+ return false;
+ } );
+
+ $reset = new ScopedCallback( 'restore_error_handler' );
+ $allModules = array(
+ new MockApiQueryBase( 'mock1' ),
+ new MockApiQueryBase( 'mock2' ),
+ new MockApiQueryBase( 'mocklist' ),
+ );
+ $generator = new MockApiQueryBase( 'generator' );
+
+ $main = new ApiMain( RequestContext::getMain() );
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $result->setGeneratorContinueParam( $generator, 'gcontinue', array( 3, 4 ) );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2|mocklist',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'generator' => array( 'gcontinue' => '3|4' ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'gcontinue' => 3,
+ 'continue' => 'gcontinue||',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'gcontinue' => 3,
+ 'continue' => 'gcontinue||mocklist',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2|mocklist',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'continue' => '-||mock1|mock2',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( null, $result->getResultData( 'continue' ) );
+ $this->assertSame( true, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( null, $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( '||mock2', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame(
+ array( false, array_values( array_diff_key( $allModules, array( 1 => 1 ) ) ) ),
+ $ret
+ );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( '-||', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame(
+ array( true, array_values( array_diff_key( $allModules, array( 0 => 0, 1 => 1 ) ) ) ),
+ $ret
+ );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ try {
+ $result->beginContinuation( 'foo', $allModules, array( 'mock1', 'mock2' ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UsageException $ex ) {
+ $this->assertSame(
+ 'Invalid continue param. You should pass the original value returned by the previous query',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $result->beginContinuation( '||mock2', array_slice( $allModules, 0, 2 ), array( 'mock1', 'mock2' ) );
+ try {
+ $result->setContinueParam( $allModules[1], 'm2continue', 1 );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UnexpectedValueException $ex ) {
+ $this->assertSame(
+ 'Module \'mock2\' was not supposed to have been executed, but it was executed anyway',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $result->setContinueParam( $allModules[2], 'mlcontinue', 1 );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UnexpectedValueException $ex ) {
+ $this->assertSame(
+ 'Module \'mocklist\' called ApiContinuationManager::addContinueParam but was not passed to ApiContinuationManager::__construct',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ $main->setContinuationManager( null );
+
+ }
+
+ public function testObjectSerialization() {
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', (object)array( 'a' => 1, 'b' => 2 ) );
+ $this->assertSame( array(
+ 'a' => 1,
+ 'b' => 2,
+ ApiResult::META_TYPE => 'assoc',
+ ), $arr['foo'] );
+
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', new ApiResultTestStringifiableObject() );
+ $this->assertSame( 'Ok', $arr['foo'] );
+
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( 'Ok' ) );
+ $this->assertSame( 'Ok', $arr['foo'] );
+
+ try {
+ $arr = array();
+ 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',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ try {
+ $arr = array();
+ 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',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
+ array(
+ 'one' => new ApiResultTestStringifiableObject( '1' ),
+ 'two' => new ApiResultTestSerializableObject( 2 ),
+ )
+ ) );
+ $this->assertSame( array(
+ 'one' => '1',
+ 'two' => 2,
+ ), $arr['foo'] );
+ }
+
+}
+
+class ApiResultTestStringifiableObject {
+ private $ret;
+
+ public function __construct( $ret = 'Ok' ) {
+ $this->ret = $ret;
+ }
+
+ public function __toString() {
+ return $this->ret;
+ }
+}
+
+class ApiResultTestSerializableObject {
+ private $ret;
+
+ public function __construct( $ret ) {
+ $this->ret = $ret;
+ }
+
+ public function __toString() {
+ return "Fail";
+ }
+
+ public function serializeForApiResult() {
+ return $this->ret;
+ }
+}
diff --git a/tests/phpunit/includes/api/ApiTestCase.php b/tests/phpunit/includes/api/ApiTestCase.php
index cd141947..da62bb0a 100644
--- a/tests/phpunit/includes/api/ApiTestCase.php
+++ b/tests/phpunit/includes/api/ApiTestCase.php
@@ -8,6 +8,11 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
*/
protected $apiContext;
+ /**
+ * @var array
+ */
+ protected $tablesUsed = array( 'user', 'user_groups', 'user_properties' );
+
protected function setUp() {
global $wgServer;
@@ -41,6 +46,17 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
$this->apiContext = new ApiTestContext();
}
+ protected function tearDown() {
+ // Avoid leaking session over tests
+ if ( session_id() != '' ) {
+ global $wgUser;
+ $wgUser->logout();
+ session_destroy();
+ }
+
+ parent::tearDown();
+ }
+
/**
* Edits or creates a page/revision
* @param string $pageName Page title
@@ -100,7 +116,7 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
// construct result
$results = array(
- $module->getResultData(),
+ $module->getResult()->getResultData( null, array( 'Strip' => 'all' ) ),
$context->getRequest(),
$context->getRequest()->getSessionArray()
);
@@ -134,10 +150,14 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
}
if ( isset( $session['wsToken'] ) && $session['wsToken'] ) {
+ // @todo Why does this directly mess with the session? Fix that.
// add edit token to fake session
$session['wsEditToken'] = $session['wsToken'];
// add token to request parameters
- $params['token'] = md5( $session['wsToken'] ) . User::EDIT_TOKEN_SUFFIX;
+ $timestamp = wfTimestamp();
+ $params['token'] = hash_hmac( 'md5', $timestamp, $session['wsToken'] ) .
+ dechex( $timestamp ) .
+ User::EDIT_TOKEN_SUFFIX;
return $this->doApiRequest( $params, $session, false, $user );
} else {
diff --git a/tests/phpunit/includes/api/ApiTestCaseUpload.php b/tests/phpunit/includes/api/ApiTestCaseUpload.php
index 7e513394..87f794c1 100644
--- a/tests/phpunit/includes/api/ApiTestCaseUpload.php
+++ b/tests/phpunit/includes/api/ApiTestCaseUpload.php
@@ -1,9 +1,8 @@
<?php
/**
- * * Abstract class to support upload tests
+ * Abstract class to support upload tests
*/
-
abstract class ApiTestCaseUpload extends ApiTestCase {
/**
* Fixture -- run before every test
@@ -21,12 +20,6 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
$this->clearFakeUploads();
}
- protected function tearDown() {
- $this->clearTempUpload();
-
- parent::tearDown();
- }
-
/**
* Helper function -- remove files and associated articles by Title
*
@@ -105,7 +98,7 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
* @return bool
*/
function fakeUploadFile( $fieldName, $fileName, $type, $filePath ) {
- $tmpName = tempnam( wfTempDir(), "" );
+ $tmpName = $this->getNewTempFile();
if ( !file_exists( $filePath ) ) {
throw new Exception( "$filePath doesn't exist!" );
}
@@ -132,7 +125,7 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
}
function fakeUploadChunk( $fieldName, $fileName, $type, & $chunkData ) {
- $tmpName = tempnam( wfTempDir(), "" );
+ $tmpName = $this->getNewTempFile();
// copy the chunk data to temp location:
if ( !file_put_contents( $tmpName, $chunkData ) ) {
throw new Exception( "couldn't copy chunk data to $tmpName" );
@@ -153,15 +146,6 @@ abstract class ApiTestCaseUpload extends ApiTestCase {
);
}
- function clearTempUpload() {
- if ( isset( $_FILES['file']['tmp_name'] ) ) {
- $tmp = $_FILES['file']['tmp_name'];
- if ( file_exists( $tmp ) ) {
- unlink( $tmp );
- }
- }
- }
-
/**
* Remove traces of previous fake uploads
*/
diff --git a/tests/phpunit/includes/api/ApiUploadTest.php b/tests/phpunit/includes/api/ApiUploadTest.php
index 8ea761f8..f74fc354 100644
--- a/tests/phpunit/includes/api/ApiUploadTest.php
+++ b/tests/phpunit/includes/api/ApiUploadTest.php
@@ -1,31 +1,24 @@
<?php
/**
- * @group API
- * @group Database
- * @group medium
- */
-
-/**
* n.b. Ensure that you can write to the images/ directory as the
* user that will run tests.
- */
-
-// Note for reviewers: this intentionally duplicates functionality already in
-// "ApiSetup" and so on. This framework works better IMO and has less
-// strangeness (such as test cases inheriting from "ApiSetup"...) (and in the
-// case of the other Upload tests, this flat out just actually works... )
-
-// @todo Port the other Upload tests, and other API tests to this framework
-
-require_once 'ApiTestCaseUpload.php';
-
-/**
- * @group Database
- * @group Broken
- * Broken test, reports false errors from time to time.
+ *
+ * Note for reviewers: this intentionally duplicates functionality already in
+ * "ApiSetup" and so on. This framework works better IMO and has less
+ * strangeness (such as test cases inheriting from "ApiSetup"...) (and in the
+ * case of the other Upload tests, this flat out just actually works... )
+ *
+ * @todo Port the other Upload tests, and other API tests to this framework
+ *
+ * @todo Broken test, reports false errors from time to time.
* See https://bugzilla.wikimedia.org/26169
*
- * This is pretty sucky... needs to be prettified.
+ * @todo This is pretty sucky... needs to be prettified.
+ *
+ * @group API
+ * @group Database
+ * @group medium
+ * @group Broken
*/
class ApiUploadTest extends ApiTestCaseUpload {
/**
@@ -105,7 +98,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
try {
$randomImageGenerator = new RandomImageGenerator();
- $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
+ $filePaths = $randomImageGenerator->writeImages( 1, $extension, $this->getNewTempDirectory() );
} catch ( Exception $e ) {
$this->markTestIncomplete( $e->getMessage() );
}
@@ -145,7 +138,6 @@ class ApiUploadTest extends ApiTestCaseUpload {
// clean up
$this->deleteFileByFilename( $fileName );
- unlink( $filePath );
}
/**
@@ -154,7 +146,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
public function testUploadZeroLength( $session ) {
$mimeType = 'image/png';
- $filePath = tempnam( wfTempDir(), "" );
+ $filePath = $this->getNewTempFile();
$fileName = "apiTestUploadZeroLength.png";
$this->deleteFileByFileName( $fileName );
@@ -182,7 +174,6 @@ class ApiUploadTest extends ApiTestCaseUpload {
// clean up
$this->deleteFileByFilename( $fileName );
- unlink( $filePath );
}
/**
@@ -194,7 +185,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
try {
$randomImageGenerator = new RandomImageGenerator();
- $filePaths = $randomImageGenerator->writeImages( 2, $extension, wfTempDir() );
+ $filePaths = $randomImageGenerator->writeImages( 2, $extension, $this->getNewTempDirectory() );
} catch ( Exception $e ) {
$this->markTestIncomplete( $e->getMessage() );
}
@@ -253,8 +244,6 @@ class ApiUploadTest extends ApiTestCaseUpload {
// clean up
$this->deleteFileByFilename( $fileName );
- unlink( $filePaths[0] );
- unlink( $filePaths[1] );
}
/**
@@ -266,7 +255,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
try {
$randomImageGenerator = new RandomImageGenerator();
- $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
+ $filePaths = $randomImageGenerator->writeImages( 1, $extension, $this->getNewTempDirectory() );
} catch ( Exception $e ) {
$this->markTestIncomplete( $e->getMessage() );
}
@@ -335,7 +324,6 @@ class ApiUploadTest extends ApiTestCaseUpload {
// clean up
$this->deleteFileByFilename( $fileNames[0] );
$this->deleteFileByFilename( $fileNames[1] );
- unlink( $filePaths[0] );
}
/**
@@ -351,7 +339,7 @@ class ApiUploadTest extends ApiTestCaseUpload {
try {
$randomImageGenerator = new RandomImageGenerator();
- $filePaths = $randomImageGenerator->writeImages( 1, $extension, wfTempDir() );
+ $filePaths = $randomImageGenerator->writeImages( 1, $extension, $this->getNewTempDirectory() );
} catch ( Exception $e ) {
$this->markTestIncomplete( $e->getMessage() );
}
@@ -419,7 +407,6 @@ class ApiUploadTest extends ApiTestCaseUpload {
// clean up
$this->deleteFileByFilename( $fileName );
- unlink( $filePath );
}
/**
@@ -433,16 +420,14 @@ class ApiUploadTest extends ApiTestCaseUpload {
$chunkSize = 1048576;
// Download a large image file
- // ( using RandomImageGenerator for large files is not stable )
+ // (using RandomImageGenerator for large files is not stable)
+ // @todo Don't download files from wikimedia.org
$mimeType = 'image/jpeg';
$url = 'http://upload.wikimedia.org/wikipedia/commons/'
. 'e/ed/Oberaargletscher_from_Oberaar%2C_2010_07.JPG';
- $filePath = wfTempDir() . '/Oberaargletscher_from_Oberaar.jpg';
+ $filePath = $this->getNewTempDirectory() . '/Oberaargletscher_from_Oberaar.jpg';
try {
- // Only download if the file is not avaliable in the temp location:
- if ( !is_file( $filePath ) ) {
- copy( $url, $filePath );
- }
+ copy( $url, $filePath );
} catch ( Exception $e ) {
$this->markTestIncomplete( $e->getMessage() );
}
@@ -566,7 +551,5 @@ class ApiUploadTest extends ApiTestCaseUpload {
// clean up
$this->deleteFileByFilename( $fileName );
- // don't remove downloaded temporary file for fast subquent tests.
- //unlink( $filePath );
}
}
diff --git a/tests/phpunit/includes/api/MockApi.php b/tests/phpunit/includes/api/MockApi.php
index d94aa2cd..516da0c8 100644
--- a/tests/phpunit/includes/api/MockApi.php
+++ b/tests/phpunit/includes/api/MockApi.php
@@ -4,9 +4,6 @@ class MockApi extends ApiBase {
public function execute() {
}
- public function getVersion() {
- }
-
public function __construct() {
}
diff --git a/tests/phpunit/includes/api/MockApiQueryBase.php b/tests/phpunit/includes/api/MockApiQueryBase.php
index 4bede519..f5b50e5a 100644
--- a/tests/phpunit/includes/api/MockApiQueryBase.php
+++ b/tests/phpunit/includes/api/MockApiQueryBase.php
@@ -1,11 +1,15 @@
<?php
class MockApiQueryBase extends ApiQueryBase {
+ private $name;
+
public function execute() {
}
- public function getVersion() {
+ public function __construct( $name = 'mock' ) {
+ $this->name = $name;
}
- public function __construct() {
+ public function getModuleName() {
+ return $this->name;
}
}
diff --git a/tests/phpunit/includes/api/PrefixUniquenessTest.php b/tests/phpunit/includes/api/PrefixUniquenessTest.php
index 13da33c7..d04766be 100644
--- a/tests/phpunit/includes/api/PrefixUniquenessTest.php
+++ b/tests/phpunit/includes/api/PrefixUniquenessTest.php
@@ -20,7 +20,7 @@ class PrefixUniquenessTest extends MediaWikiTestCase {
$class = get_class( $module );
$prefix = $module->getModulePrefix();
- if ( isset( $prefixes[$prefix] ) ) {
+ if ( $prefix !== '' && isset( $prefixes[$prefix] ) ) {
$this->fail( "Module prefix '{$prefix}' is shared between {$class} and {$prefixes[$prefix]}" );
}
$prefixes[$module->getModulePrefix()] = $class;
diff --git a/tests/phpunit/includes/api/format/ApiFormatDbgTest.php b/tests/phpunit/includes/api/format/ApiFormatDbgTest.php
new file mode 100644
index 00000000..3fcfc73f
--- /dev/null
+++ b/tests/phpunit/includes/api/format/ApiFormatDbgTest.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @group API
+ * @covers ApiFormatDbg
+ */
+class ApiFormatDbgTest extends ApiFormatTestBase {
+
+ protected $printerName = 'dbg';
+
+ public static function provideGeneralEncoding() {
+ $warning = "\n 'warnings' => \n array (\n 'dbg' => \n array (\n" .
+ " '*' => 'format=dbg has been deprecated. Please use format=json instead.',\n" .
+ " ),\n ),";
+
+ return array(
+ // Basic types
+ array( array( null ), "array ({$warning}\n 0 => NULL,\n)" ),
+ array( array( true ), "array ({$warning}\n 0 => '',\n)" ),
+ array( array( false ), "array ({$warning}\n)" ),
+ array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ "array ({$warning}\n 0 => true,\n)" ),
+ array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ "array ({$warning}\n 0 => false,\n)" ),
+ array( array( 42 ), "array ({$warning}\n 0 => 42,\n)" ),
+ array( array( 42.5 ), "array ({$warning}\n 0 => 42.5,\n)" ),
+ array( array( 1e42 ), "array ({$warning}\n 0 => 1.0E+42,\n)" ),
+ array( array( 'foo' ), "array ({$warning}\n 0 => 'foo',\n)" ),
+ array( array( 'fóo' ), "array ({$warning}\n 0 => 'fóo',\n)" ),
+
+ // Arrays and objects
+ array( array( array() ), "array ({$warning}\n 0 => \n array (\n ),\n)" ),
+ array( array( array( 1 ) ), "array ({$warning}\n 0 => \n array (\n 0 => 1,\n ),\n)" ),
+ array( array( array( 'x' => 1 ) ), "array ({$warning}\n 0 => \n array (\n 'x' => 1,\n ),\n)" ),
+ array( array( array( 2 => 1 ) ), "array ({$warning}\n 0 => \n array (\n 2 => 1,\n ),\n)" ),
+ array( array( (object)array() ), "array ({$warning}\n 0 => \n array (\n ),\n)" ),
+ array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), "array ({$warning}\n 0 => \n array (\n 0 => 1,\n ),\n)" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), "array ({$warning}\n 0 => \n array (\n 0 => 1,\n ),\n)" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), "array ({$warning}\n 0 => \n array (\n 'x' => 1,\n ),\n)" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ "array ({$warning}\n 0 => \n array (\n 0 => \n array (\n 'key' => 'x',\n '*' => 1,\n ),\n ),\n)" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), "array ({$warning}\n 0 => \n array (\n 'x' => 1,\n ),\n)" ),
+ array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), "array ({$warning}\n 0 => \n array (\n 0 => 'a',\n 1 => 'b',\n ),\n)" ),
+
+ // Content
+ array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ "array ({$warning}\n '*' => 'foo',\n)" ),
+
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
+ "array ({$warning}\n 'foo' => \n array (\n '*' => 'foo',\n ),\n)" ),
+ );
+ }
+
+}
diff --git a/tests/phpunit/includes/api/format/ApiFormatDumpTest.php b/tests/phpunit/includes/api/format/ApiFormatDumpTest.php
new file mode 100644
index 00000000..c0f67f8d
--- /dev/null
+++ b/tests/phpunit/includes/api/format/ApiFormatDumpTest.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @group API
+ * @covers ApiFormatDump
+ */
+class ApiFormatDumpTest extends ApiFormatTestBase {
+
+ protected $printerName = 'dump';
+
+ public static function provideGeneralEncoding() {
+ // Sigh. Docs claim it's a boolean, but can have values 0, 1, or 2.
+ // Fortunately wfIniGetBool does the right thing.
+ if ( wfIniGetBool( 'xdebug.overload_var_dump' ) ) {
+ return array(
+ array( array(), 'Cannot test ApiFormatDump when xDebug overloads var_dump', array( 'SKIP' => 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/ApiFormatJsonTest.php b/tests/phpunit/includes/api/format/ApiFormatJsonTest.php
index fc1f9021..3dfcaf0f 100644
--- a/tests/phpunit/includes/api/format/ApiFormatJsonTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatJsonTest.php
@@ -2,21 +2,109 @@
/**
* @group API
- * @group Database
- * @group medium
* @covers ApiFormatJson
*/
class ApiFormatJsonTest extends ApiFormatTestBase {
- public function testValidSyntax( ) {
- $data = $this->apiRequest( 'json', array( 'action' => 'query', 'meta' => 'siteinfo' ) );
+ protected $printerName = 'json';
- $this->assertInternalType( 'array', json_decode( $data, true ) );
- $this->assertGreaterThan( 0, count( (array)$data ) );
+ private static function addFormatVersion( $format, $arr ) {
+ foreach ( $arr as &$p ) {
+ if ( !isset( $p[2] ) ) {
+ $p[2] = array( 'formatversion' => $format );
+ } else {
+ $p[2]['formatversion'] = $format;
+ }
+ }
+ return $arr;
}
- public function testJsonpInjection( ) {
- $data = $this->apiRequest( 'json', array( 'action' => 'query', 'meta' => 'siteinfo', 'callback' => 'myCallback' ) );
- $this->assertEquals( '/**/myCallback(', substr( $data, 0, 15 ) );
+ public static function provideGeneralEncoding() {
+ return array_merge(
+ self::addFormatVersion( 1, array(
+ // Basic types
+ array( array( null ), '[null]' ),
+ array( array( true ), '[""]' ),
+ array( array( false ), '[]' ),
+ array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), '[true]' ),
+ array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), '[false]' ),
+ array( array( 42 ), '[42]' ),
+ array( array( 42.5 ), '[42.5]' ),
+ array( array( 1e42 ), '[1.0e+42]' ),
+ array( array( 'foo' ), '["foo"]' ),
+ array( array( 'fóo' ), '["f\u00f3o"]' ),
+ array( array( 'fóo' ), '["fóo"]', array( 'utf8' => 1 ) ),
+
+ // Arrays and objects
+ array( array( array() ), '[[]]' ),
+ array( array( array( 1 ) ), '[[1]]' ),
+ array( array( array( 'x' => 1 ) ), '[{"x":1}]' ),
+ array( array( array( 2 => 1 ) ), '[{"2":1}]' ),
+ array( array( (object)array() ), '[{}]' ),
+ array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), '[{"0":1}]' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), '[[1]]' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), '[{"x":1}]' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ '[[{"key":"x","*":1}]]' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), '[{"x":1}]' ),
+ array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), '[["a","b"]]' ),
+
+ // Content
+ array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ '{"*":"foo"}' ),
+
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
+ '{"foo":{"*":"foo"}}' ),
+
+ // Callbacks
+ array( array( 1 ), '/**/myCallback([1])', array( 'callback' => 'myCallback' ) ),
+
+ // Cross-domain mangling
+ array( array( '< Cross-Domain-Policy >' ), '["\u003C Cross-Domain-Policy \u003E"]' ),
+ ) ),
+ self::addFormatVersion( 2, array(
+ // Basic types
+ array( array( null ), '[null]' ),
+ array( array( true ), '[true]' ),
+ array( array( false ), '[false]' ),
+ array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), '[true]' ),
+ array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), '[false]' ),
+ array( array( 42 ), '[42]' ),
+ array( array( 42.5 ), '[42.5]' ),
+ array( array( 1e42 ), '[1.0e+42]' ),
+ array( array( 'foo' ), '["foo"]' ),
+ array( array( 'fóo' ), '["fóo"]' ),
+ array( array( 'fóo' ), '["f\u00f3o"]', array( 'ascii' => 1 ) ),
+
+ // Arrays and objects
+ array( array( array() ), '[[]]' ),
+ array( array( array( 'x' => 1 ) ), '[{"x":1}]' ),
+ array( array( array( 2 => 1 ) ), '[{"2":1}]' ),
+ array( array( (object)array() ), '[{}]' ),
+ array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), '[{"0":1}]' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), '[[1]]' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), '[{"x":1}]' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ '[{"x":1}]' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), '[[1]]' ),
+ array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), '[{"0":"a","1":"b"}]' ),
+
+ // Content
+ array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ '{"content":"foo"}' ),
+
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
+ '{"foo":"foo"}' ),
+
+ // Callbacks
+ array( array( 1 ), '/**/myCallback([1])', array( 'callback' => 'myCallback' ) ),
+
+ // Cross-domain mangling
+ array( array( '< Cross-Domain-Policy >' ), '["\u003C Cross-Domain-Policy \u003E"]' ),
+ ) )
+ );
}
+
}
diff --git a/tests/phpunit/includes/api/format/ApiFormatNoneTest.php b/tests/phpunit/includes/api/format/ApiFormatNoneTest.php
index cabd750b..8f81a411 100644
--- a/tests/phpunit/includes/api/format/ApiFormatNoneTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatNoneTest.php
@@ -2,15 +2,43 @@
/**
* @group API
- * @group Database
- * @group medium
* @covers ApiFormatNone
*/
class ApiFormatNoneTest extends ApiFormatTestBase {
- public function testValidSyntax( ) {
- $data = $this->apiRequest( 'none', array( 'action' => 'query', 'meta' => 'siteinfo' ) );
+ protected $printerName = 'none';
- $this->assertEquals( '', $data ); // No output!
+ public static function provideGeneralEncoding() {
+ return array(
+ // Basic types
+ array( array( null ), '' ),
+ array( array( true ), '' ),
+ array( array( false ), '' ),
+ array( array( 42 ), '' ),
+ array( array( 42.5 ), '' ),
+ array( array( 1e42 ), '' ),
+ array( array( 'foo' ), '' ),
+ array( array( 'fóo' ), '' ),
+
+ // Arrays and objects
+ array( array( array() ), '' ),
+ array( array( array( 1 ) ), '' ),
+ array( array( array( 'x' => 1 ) ), '' ),
+ array( array( array( 2 => 1 ) ), '' ),
+ array( array( (object)array() ), '' ),
+ array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), '' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), '' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), '' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), '' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), '' ),
+ array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), '' ),
+
+ // Content
+ array( array( '*' => 'foo' ), '' ),
+
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), '' ),
+ );
}
+
}
diff --git a/tests/phpunit/includes/api/format/ApiFormatPhpTest.php b/tests/phpunit/includes/api/format/ApiFormatPhpTest.php
index 54f447a9..0cb44e92 100644
--- a/tests/phpunit/includes/api/format/ApiFormatPhpTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatPhpTest.php
@@ -2,16 +2,143 @@
/**
* @group API
- * @group Database
- * @group medium
* @covers ApiFormatPhp
*/
class ApiFormatPhpTest extends ApiFormatTestBase {
- public function testValidSyntax( ) {
- $data = $this->apiRequest( 'php', array( 'action' => 'query', 'meta' => 'siteinfo' ) );
+ protected $printerName = 'php';
- $this->assertInternalType( 'array', unserialize( $data ) );
- $this->assertGreaterThan( 0, count( (array)$data ) );
+ private static function addFormatVersion( $format, $arr ) {
+ foreach ( $arr as &$p ) {
+ if ( !isset( $p[2] ) ) {
+ $p[2] = array( 'formatversion' => $format );
+ } else {
+ $p[2]['formatversion'] = $format;
+ }
+ }
+ return $arr;
}
+
+ public static function provideGeneralEncoding() {
+ return array_merge(
+ self::addFormatVersion( 1, array(
+ // Basic types
+ array( array( null ), 'a:1:{i:0;N;}' ),
+ array( array( true ), 'a:1:{i:0;s:0:"";}' ),
+ array( array( false ), 'a:0:{}' ),
+ array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ 'a:1:{i:0;b:1;}' ),
+ array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ 'a:1:{i:0;b:0;}' ),
+ array( array( 42 ), 'a:1:{i:0;i:42;}' ),
+ array( array( 42.5 ), 'a:1:{i:0;d:42.5;}' ),
+ array( array( 1e42 ), 'a:1:{i:0;d:1.0E+42;}' ),
+ array( array( 'foo' ), 'a:1:{i:0;s:3:"foo";}' ),
+ array( array( 'fóo' ), 'a:1:{i:0;s:4:"fóo";}' ),
+
+ // Arrays and objects
+ array( array( array() ), 'a:1:{i:0;a:0:{}}' ),
+ array( array( array( 1 ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
+ array( array( array( 'x' => 1 ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
+ array( array( array( 2 => 1 ) ), 'a:1:{i:0;a:1:{i:2;i:1;}}' ),
+ array( array( (object)array() ), 'a:1:{i:0;a:0:{}}' ),
+ array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ 'a:1:{i:0;a:1:{i:0;a:2:{s:3:"key";s:1:"x";s:1:"*";i:1;}}}' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
+ array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), 'a:1:{i:0;a:2:{i:0;s:1:"a";i:1;s:1:"b";}}' ),
+
+ // Content
+ array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ 'a:1:{s:1:"*";s:3:"foo";}' ),
+
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
+ 'a:1:{s:3:"foo";a:1:{s:1:"*";s:3:"foo";}}' ),
+ ) ),
+ self::addFormatVersion( 2, array(
+ // Basic types
+ array( array( null ), 'a:1:{i:0;N;}' ),
+ array( array( true ), 'a:1:{i:0;b:1;}' ),
+ array( array( false ), 'a:1:{i:0;b:0;}' ),
+ array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ 'a:1:{i:0;b:1;}' ),
+ array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ 'a:1:{i:0;b:0;}' ),
+ array( array( 42 ), 'a:1:{i:0;i:42;}' ),
+ array( array( 42.5 ), 'a:1:{i:0;d:42.5;}' ),
+ array( array( 1e42 ), 'a:1:{i:0;d:1.0E+42;}' ),
+ array( array( 'foo' ), 'a:1:{i:0;s:3:"foo";}' ),
+ array( array( 'fóo' ), 'a:1:{i:0;s:4:"fóo";}' ),
+
+ // Arrays and objects
+ array( array( array() ), 'a:1:{i:0;a:0:{}}' ),
+ array( array( array( 1 ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
+ array( array( array( 'x' => 1 ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
+ array( array( array( 2 => 1 ) ), 'a:1:{i:0;a:1:{i:2;i:1;}}' ),
+ array( array( (object)array() ), 'a:1:{i:0;a:0:{}}' ),
+ array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ),
+ array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), 'a:1:{i:0;a:2:{i:0;s:1:"a";i:1;s:1:"b";}}' ),
+
+ // Content
+ array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ 'a:1:{s:7:"content";s:3:"foo";}' ),
+
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
+ 'a:1:{s:3:"foo";s:3:"foo";}' ),
+ ) )
+ );
+ }
+
+ public function testCrossDomainMangling() {
+ $config = new HashConfig( array( 'MangleFlashPolicy' => false ) );
+ $context = new RequestContext;
+ $context->setConfig( new MultiConfig( array(
+ $config,
+ $context->getConfig(),
+ ) ) );
+ $main = new ApiMain( $context );
+ $main->getResult()->addValue( null, null, '< Cross-Domain-Policy >' );
+
+ if ( !function_exists( 'wfOutputHandler' ) ) {
+ function wfOutputHandler( $s ) {
+ return $s;
+ }
+ }
+
+ $printer = $main->createPrinterByName( 'php' );
+ ob_start( 'wfOutputHandler' );
+ $printer->initPrinter();
+ $printer->execute();
+ $printer->closePrinter();
+ $ret = ob_get_clean();
+ $this->assertSame( 'a:1:{i:0;s:23:"< Cross-Domain-Policy >";}', $ret );
+
+ $config->set( 'MangleFlashPolicy', true );
+ $printer = $main->createPrinterByName( 'php' );
+ ob_start( 'wfOutputHandler' );
+ try {
+ $printer->initPrinter();
+ $printer->execute();
+ $printer->closePrinter();
+ ob_end_clean();
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UsageException $ex ) {
+ ob_end_clean();
+ $this->assertSame(
+ 'This response cannot be represented using format=php. See https://bugzilla.wikimedia.org/show_bug.cgi?id=66776',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ }
+
}
diff --git a/tests/phpunit/includes/api/format/ApiFormatTestBase.php b/tests/phpunit/includes/api/format/ApiFormatTestBase.php
index 5f6d53ce..cabf62b1 100644
--- a/tests/phpunit/includes/api/format/ApiFormatTestBase.php
+++ b/tests/phpunit/includes/api/format/ApiFormatTestBase.php
@@ -1,32 +1,64 @@
<?php
-abstract class ApiFormatTestBase extends ApiTestCase {
+abstract class ApiFormatTestBase extends MediaWikiTestCase {
/**
- * @param string $format
- * @param array $params
- * @param array $data
- *
- * @return string
+ * Name of the formatter being tested
+ * @var string
*/
- protected function apiRequest( $format, $params, $data = null ) {
- $data = parent::doApiRequest( $params, $data, true );
-
- /** @var ApiMain $module */
- $module = $data[3];
+ protected $printerName;
- $printer = $module->createPrinterByName( $format );
- $printer->setUnescapeAmps( false );
+ /**
+ * Return general data to be encoded for testing
+ * @return array See self::testGeneralEncoding
+ * @throws Exception
+ */
+ public static function provideGeneralEncoding() {
+ throw new Exception( 'Subclass must implement ' . __METHOD__ );
+ }
- $printer->initPrinter( false );
+ /**
+ * Get the formatter output for the given input data
+ * @param array $params Query parameters
+ * @param array $data Data to encode
+ * @param string $class Printer class to use instead of the normal one
+ * @return string
+ * @throws Exception
+ */
+ protected function encodeData( array $params, array $data, $class = null ) {
+ $context = new RequestContext;
+ $context->setRequest( new FauxRequest( $params, true ) );
+ $main = new ApiMain( $context );
+ if ( $class !== null ) {
+ $main->getModuleManager()->addModule( $this->printerName, 'format', $class );
+ }
+ $result = $main->getResult();
+ $result->addArrayType( null, 'default' );
+ foreach ( $data as $k => $v ) {
+ $result->addValue( null, $k, $v );
+ }
- ob_start();
+ $printer = $main->createPrinterByName( $this->printerName );
+ $printer->initPrinter();
$printer->execute();
- $out = ob_get_clean();
-
- $printer->closePrinter();
+ ob_start();
+ try {
+ $printer->closePrinter();
+ return ob_get_clean();
+ } catch ( Exception $ex ) {
+ ob_end_clean();
+ throw $ex;
+ }
+ }
- return $out;
+ /**
+ * @dataProvider provideGeneralEncoding
+ */
+ public function testGeneralEncoding( array $data, $expect, array $params = array() ) {
+ if ( isset( $params['SKIP'] ) ) {
+ $this->markTestSkipped( $expect );
+ }
+ $this->assertSame( $expect, $this->encodeData( $params, $data ) );
}
}
diff --git a/tests/phpunit/includes/api/format/ApiFormatTxtTest.php b/tests/phpunit/includes/api/format/ApiFormatTxtTest.php
new file mode 100644
index 00000000..b0a2a960
--- /dev/null
+++ b/tests/phpunit/includes/api/format/ApiFormatTxtTest.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @group API
+ * @covers ApiFormatTxt
+ */
+class ApiFormatTxtTest extends ApiFormatTestBase {
+
+ protected $printerName = 'txt';
+
+ public static function provideGeneralEncoding() {
+ $warning = "\n [warnings] => Array\n (\n [txt] => Array\n (\n" .
+ " [*] => format=txt has been deprecated. Please use format=json instead.\n" .
+ " )\n\n )\n";
+
+ return array(
+ // Basic types
+ array( array( null ), "Array\n({$warning}\n [0] => \n)\n" ),
+ array( array( true ), "Array\n({$warning}\n [0] => \n)\n" ),
+ array( array( false ), "Array\n({$warning}\n)\n" ),
+ array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ "Array\n({$warning}\n [0] => 1\n)\n" ),
+ array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ "Array\n({$warning}\n [0] => \n)\n" ),
+ array( array( 42 ), "Array\n({$warning}\n [0] => 42\n)\n" ),
+ array( array( 42.5 ), "Array\n({$warning}\n [0] => 42.5\n)\n" ),
+ array( array( 1e42 ), "Array\n({$warning}\n [0] => 1.0E+42\n)\n" ),
+ array( array( 'foo' ), "Array\n({$warning}\n [0] => foo\n)\n" ),
+ array( array( 'fóo' ), "Array\n({$warning}\n [0] => fóo\n)\n" ),
+
+ // Arrays and objects
+ array( array( array() ), "Array\n({$warning}\n [0] => Array\n (\n )\n\n)\n" ),
+ array( array( array( 1 ) ), "Array\n({$warning}\n [0] => Array\n (\n [0] => 1\n )\n\n)\n" ),
+ array( array( array( 'x' => 1 ) ), "Array\n({$warning}\n [0] => Array\n (\n [x] => 1\n )\n\n)\n" ),
+ array( array( array( 2 => 1 ) ), "Array\n({$warning}\n [0] => Array\n (\n [2] => 1\n )\n\n)\n" ),
+ array( array( (object)array() ), "Array\n({$warning}\n [0] => Array\n (\n )\n\n)\n" ),
+ array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), "Array\n({$warning}\n [0] => Array\n (\n [0] => 1\n )\n\n)\n" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), "Array\n({$warning}\n [0] => Array\n (\n [0] => 1\n )\n\n)\n" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), "Array\n({$warning}\n [0] => Array\n (\n [x] => 1\n )\n\n)\n" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ "Array\n({$warning}\n [0] => Array\n (\n [0] => Array\n (\n [key] => x\n [*] => 1\n )\n\n )\n\n)\n" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), "Array\n({$warning}\n [0] => Array\n (\n [x] => 1\n )\n\n)\n" ),
+ array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), "Array\n({$warning}\n [0] => Array\n (\n [0] => a\n [1] => b\n )\n\n)\n" ),
+
+ // Content
+ array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ "Array\n({$warning}\n [*] => foo\n)\n" ),
+
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
+ "Array\n({$warning}\n [foo] => Array\n (\n [*] => foo\n )\n\n)\n" ),
+ );
+ }
+
+}
diff --git a/tests/phpunit/includes/api/format/ApiFormatWddxTest.php b/tests/phpunit/includes/api/format/ApiFormatWddxTest.php
index d075f547..07111300 100644
--- a/tests/phpunit/includes/api/format/ApiFormatWddxTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatWddxTest.php
@@ -2,19 +2,79 @@
/**
* @group API
- * @group Database
- * @group medium
* @covers ApiFormatWddx
*/
class ApiFormatWddxTest extends ApiFormatTestBase {
+ protected $printerName = 'wddx';
+
+ public static function provideGeneralEncoding() {
+ if ( ApiFormatWddx::useSlowPrinter() ) {
+ return array(
+ array( array(), 'Fast Wddx printer is unavailable', array( 'SKIP' => true ) )
+ );
+ }
+ return self::provideEncoding();
+ }
+
+ public static function provideEncoding() {
+ $p = '<wddxPacket version=\'1.0\'><header/><data><struct><var name=\'warnings\'><struct><var name=\'wddx\'><struct><var name=\'*\'><string>format=wddx has been deprecated. Please use format=json instead.</string></var></struct></var></struct></var>';
+ $s = '</struct></data></wddxPacket>';
+
+ return array(
+ // Basic types
+ array( array( null ), "{$p}<var name='0'><null/></var>{$s}" ),
+ array( array( true ), "{$p}<var name='0'><string></string></var>{$s}" ),
+ array( array( false ), "{$p}{$s}" ),
+ array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ "{$p}<var name='0'><boolean value='true'/></var>{$s}" ),
+ array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ "{$p}<var name='0'><boolean value='false'/></var>{$s}" ),
+ array( array( 42 ), "{$p}<var name='0'><number>42</number></var>{$s}" ),
+ array( array( 42.5 ), "{$p}<var name='0'><number>42.5</number></var>{$s}" ),
+ array( array( 1e42 ), "{$p}<var name='0'><number>1.0E+42</number></var>{$s}" ),
+ array( array( 'foo' ), "{$p}<var name='0'><string>foo</string></var>{$s}" ),
+ array( array( 'fóo' ), "{$p}<var name='0'><string>fóo</string></var>{$s}" ),
+
+ // Arrays and objects
+ array( array( array() ), "{$p}<var name='0'><array length='0'></array></var>{$s}" ),
+ array( array( array( 1 ) ), "{$p}<var name='0'><array length='1'><number>1</number></array></var>{$s}" ),
+ array( array( array( 'x' => 1 ) ), "{$p}<var name='0'><struct><var name='x'><number>1</number></var></struct></var>{$s}" ),
+ array( array( array( 2 => 1 ) ), "{$p}<var name='0'><struct><var name='2'><number>1</number></var></struct></var>{$s}" ),
+ array( array( (object)array() ), "{$p}<var name='0'><struct></struct></var>{$s}" ),
+ array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), "{$p}<var name='0'><struct><var name='0'><number>1</number></var></struct></var>{$s}" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), "{$p}<var name='0'><array length='1'><number>1</number></array></var>{$s}" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), "{$p}<var name='0'><struct><var name='x'><number>1</number></var></struct></var>{$s}" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ "{$p}<var name='0'><array length='1'><struct><var name='key'><string>x</string></var><var name='*'><number>1</number></var></struct></array></var>{$s}" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), "{$p}<var name='0'><struct><var name='x'><number>1</number></var></struct></var>{$s}" ),
+ array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), "{$p}<var name='0'><array length='2'><string>a</string><string>b</string></array></var>{$s}" ),
+
+ // Content
+ array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ "{$p}<var name='*'><string>foo</string></var>{$s}" ),
+
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
+ "{$p}<var name='foo'><struct><var name='*'><string>foo</string></var></struct></var>{$s}" ),
+ );
+ }
+
/**
- * @requires function wddx_deserialize
+ * @dataProvider provideEncoding
*/
- public function testValidSyntax( ) {
- $data = $this->apiRequest( 'wddx', array( 'action' => 'query', 'meta' => 'siteinfo' ) );
+ 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 = '<?xml version="1.0"?>' . $expect;
+
+ $this->assertSame( $expect, $this->encodeData( $params, $data, 'ApiFormatWddxTest_SlowWddx' ) );
+ }
+}
- $this->assertInternalType( 'array', wddx_deserialize( $data ) );
- $this->assertGreaterThan( 0, count( (array)$data ) );
+class ApiFormatWddxTest_SlowWddx extends ApiFormatWddx {
+ public static function useSlowPrinter() {
+ return true;
}
}
diff --git a/tests/phpunit/includes/api/format/ApiFormatXmlTest.php b/tests/phpunit/includes/api/format/ApiFormatXmlTest.php
new file mode 100644
index 00000000..7babaedb
--- /dev/null
+++ b/tests/phpunit/includes/api/format/ApiFormatXmlTest.php
@@ -0,0 +1,119 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @covers ApiFormatXml
+ */
+class ApiFormatXmlTest extends ApiFormatTestBase {
+
+ protected $printerName = 'xml';
+
+ public static function setUpBeforeClass() {
+ parent::setUpBeforeClass();
+ $page = WikiPage::factory( Title::newFromText( 'MediaWiki:ApiFormatXmlTest.xsl' ) );
+ $page->doEditContent( new WikitextContent(
+ '<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" />'
+ ), 'Summary' );
+ $page = WikiPage::factory( Title::newFromText( 'MediaWiki:ApiFormatXmlTest' ) );
+ $page->doEditContent( new WikitextContent( 'Bogus' ), 'Summary' );
+ $page = WikiPage::factory( Title::newFromText( 'ApiFormatXmlTest' ) );
+ $page->doEditContent( new WikitextContent( 'Bogus' ), 'Summary' );
+ }
+
+ public static function provideGeneralEncoding() {
+ return array(
+ // Basic types
+ array( array( null, 'a' => null ), '<?xml version="1.0"?><api><_v _idx="0" /></api>' ),
+ array( array( true, 'a' => true ), '<?xml version="1.0"?><api a=""><_v _idx="0">true</_v></api>' ),
+ array( array( false, 'a' => false ), '<?xml version="1.0"?><api><_v _idx="0">false</_v></api>' ),
+ array( array( true, 'a' => true, ApiResult::META_BC_BOOLS => array( 0, 'a' ) ),
+ '<?xml version="1.0"?><api a=""><_v _idx="0">1</_v></api>' ),
+ array( array( false, 'a' => false, ApiResult::META_BC_BOOLS => array( 0, 'a' ) ),
+ '<?xml version="1.0"?><api><_v _idx="0"></_v></api>' ),
+ array( array( 42, 'a' => 42 ), '<?xml version="1.0"?><api a="42"><_v _idx="0">42</_v></api>' ),
+ array( array( 42.5, 'a' => 42.5 ), '<?xml version="1.0"?><api a="42.5"><_v _idx="0">42.5</_v></api>' ),
+ array( array( 1e42, 'a' => 1e42 ), '<?xml version="1.0"?><api a="1.0E+42"><_v _idx="0">1.0E+42</_v></api>' ),
+ array( array( 'foo', 'a' => 'foo' ), '<?xml version="1.0"?><api a="foo"><_v _idx="0">foo</_v></api>' ),
+ array( array( 'fóo', 'a' => 'fóo' ), '<?xml version="1.0"?><api a="fóo"><_v _idx="0">fóo</_v></api>' ),
+
+ // Arrays and objects
+ array( array( array() ), '<?xml version="1.0"?><api><_v /></api>' ),
+ array( array( array( 'x' => 1 ) ), '<?xml version="1.0"?><api><_v x="1" /></api>' ),
+ array( array( array( 2 => 1 ) ), '<?xml version="1.0"?><api><_v><_v _idx="2">1</_v></_v></api>' ),
+ array( array( (object)array() ), '<?xml version="1.0"?><api><_v /></api>' ),
+ array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), '<?xml version="1.0"?><api><_v><_v _idx="0">1</_v></_v></api>' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), '<?xml version="1.0"?><api><_v><_v>1</_v></_v></api>' ),
+ array( array( array( 'x' => 1, 'y' => array( 'z' => 1 ), ApiResult::META_TYPE => 'kvp' ) ),
+ '<?xml version="1.0"?><api><_v><_v _name="x" xml:space="preserve">1</_v><_v _name="y"><z xml:space="preserve">1</z></_v></_v></api>' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp', ApiResult::META_INDEXED_TAG_NAME => 'i', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ '<?xml version="1.0"?><api><_v><i key="x" xml:space="preserve">1</i></_v></api>' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ '<?xml version="1.0"?><api><_v><_v key="x" xml:space="preserve">1</_v></_v></api>' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), '<?xml version="1.0"?><api><_v x="1" /></api>' ),
+ array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), '<?xml version="1.0"?><api><_v><_v _idx="0">a</_v><_v _idx="1">b</_v></_v></api>' ),
+
+ // Content
+ array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ '<?xml version="1.0"?><api xml:space="preserve">foo</api>' ),
+
+ // Specified element name
+ array( array( 'foo', 'bar', ApiResult::META_INDEXED_TAG_NAME => 'itn' ),
+ '<?xml version="1.0"?><api><itn>foo</itn><itn>bar</itn></api>' ),
+
+ // Subelements
+ array( array( 'a' => 1, 's' => 1, '_subelements' => array( 's' ) ),
+ '<?xml version="1.0"?><api a="1"><s xml:space="preserve">1</s></api>' ),
+
+ // Content and subelement
+ array( array( 'a' => 1, 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ '<?xml version="1.0"?><api a="1" xml:space="preserve">foo</api>' ),
+ array( array( 's' => array(), 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ '<?xml version="1.0"?><api><s /><content xml:space="preserve">foo</content></api>' ),
+ array(
+ array(
+ 's' => 1,
+ 'content' => 'foo',
+ ApiResult::META_CONTENT => 'content',
+ ApiResult::META_SUBELEMENTS => array( 's' )
+ ),
+ '<?xml version="1.0"?><api><s xml:space="preserve">1</s><content xml:space="preserve">foo</content></api>'
+ ),
+
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
+ '<?xml version="1.0"?><api><foo xml:space="preserve">foo</foo></api>' ),
+
+ // Name mangling
+ array( array( 'foo.bar' => 1 ), '<?xml version="1.0"?><api foo.bar="1" />' ),
+ array( array( '' => 1 ), '<?xml version="1.0"?><api _="1" />' ),
+ array( array( 'foo bar' => 1 ), '<?xml version="1.0"?><api _foo.20.bar="1" />' ),
+ array( array( 'foo:bar' => 1 ), '<?xml version="1.0"?><api _foo.3A.bar="1" />' ),
+ array( array( 'foo%.bar' => 1 ), '<?xml version="1.0"?><api _foo.25..2E.bar="1" />' ),
+ array( array( '4foo' => 1, 'foo4' => 1 ), '<?xml version="1.0"?><api _4foo="1" foo4="1" />' ),
+ array( array( "foo\xe3\x80\x80bar" => 1 ), '<?xml version="1.0"?><api _foo.3000.bar="1" />' ),
+ array( array( 'foo:bar' => 1, ApiResult::META_PRESERVE_KEYS => array( 'foo:bar' ) ),
+ '<?xml version="1.0"?><api foo:bar="1" />' ),
+ array( array( 'a', 'b', ApiResult::META_INDEXED_TAG_NAME => 'foo bar' ),
+ '<?xml version="1.0"?><api><_foo.20.bar>a</_foo.20.bar><_foo.20.bar>b</_foo.20.bar></api>' ),
+
+ // includenamespace param
+ array( array( 'x' => 'foo' ), '<?xml version="1.0"?><api x="foo" xmlns="http://www.mediawiki.org/xml/api/" />',
+ array( 'includexmlnamespace' => 1 ) ),
+
+ // xslt param
+ array( array(), '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Invalid or non-existent stylesheet specified</xml></warnings></api>',
+ array( 'xslt' => 'DoesNotExist' ) ),
+ array( array(), '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Stylesheet should be in the MediaWiki namespace.</xml></warnings></api>',
+ array( 'xslt' => 'ApiFormatXmlTest' ) ),
+ array( array(), '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Stylesheet should have .xsl extension.</xml></warnings></api>',
+ array( 'xslt' => 'MediaWiki:ApiFormatXmlTest' ) ),
+ array( array(),
+ '<?xml version="1.0"?><?xml-stylesheet href="' .
+ htmlspecialchars( Title::newFromText( 'MediaWiki:ApiFormatXmlTest.xsl' )->getLocalURL( 'action=raw' ) ) .
+ '" type="text/xsl" ?><api />',
+ array( 'xslt' => 'MediaWiki:ApiFormatXmlTest.xsl' ) ),
+ );
+ }
+
+}
diff --git a/tests/phpunit/includes/api/query/ApiQueryBasicTest.php b/tests/phpunit/includes/api/query/ApiQueryBasicTest.php
index e486c4f4..fa0e4cb5 100644
--- a/tests/phpunit/includes/api/query/ApiQueryBasicTest.php
+++ b/tests/phpunit/includes/api/query/ApiQueryBasicTest.php
@@ -23,8 +23,6 @@
* @file
*/
-require_once 'ApiQueryTestBase.php';
-
/**
* These tests validate basic functionality of the api query module
*
diff --git a/tests/phpunit/includes/api/query/ApiQueryContinue2Test.php b/tests/phpunit/includes/api/query/ApiQueryContinue2Test.php
index 347cd6f8..cd735223 100644
--- a/tests/phpunit/includes/api/query/ApiQueryContinue2Test.php
+++ b/tests/phpunit/includes/api/query/ApiQueryContinue2Test.php
@@ -18,8 +18,6 @@
* http://www.gnu.org/copyleft/gpl.html
*/
-require_once 'ApiQueryContinueTestBase.php';
-
/**
* @group API
* @group Database
@@ -62,7 +60,8 @@ class ApiQueryContinue2Test extends ApiQueryContinueTestBase {
);
};
// generator + 1 prop + 1 list
- $data = $this->query( $mk( 99, 99, true ), 1, 'g1p', false );
+ $data = $this->query( $mk( 99, 99, true ), 1, 'g1p', false ) +
+ array( 'batchcomplete' => true );
$this->checkC( $data, $mk( 1, 1, true ), 6, 'g1p-11t' );
$this->checkC( $data, $mk( 2, 2, true ), 3, 'g1p-22t' );
$this->checkC( $data, $mk( 1, 1, false ), 6, 'g1p-11f' );
diff --git a/tests/phpunit/includes/api/query/ApiQueryContinueTest.php b/tests/phpunit/includes/api/query/ApiQueryContinueTest.php
index 03797901..d441f4c4 100644
--- a/tests/phpunit/includes/api/query/ApiQueryContinueTest.php
+++ b/tests/phpunit/includes/api/query/ApiQueryContinueTest.php
@@ -18,8 +18,6 @@
* http://www.gnu.org/copyleft/gpl.html
*/
-require_once 'ApiQueryContinueTestBase.php';
-
/**
* These tests validate the new continue functionality of the api query module by
* doing multiple requests with varying parameters, merging the results, and checking
@@ -68,7 +66,8 @@ class ApiQueryContinueTest extends ApiQueryContinueTestBase {
'aplimit' => "$l",
);
};
- $data = $this->query( $mk( 99 ), 1, '1L', false );
+ $data = $this->query( $mk( 99 ), 1, '1L', false ) +
+ array( 'batchcomplete' => true );
// 1 list
$this->checkC( $data, $mk( 1 ), 5, '1L-1' );
@@ -95,7 +94,8 @@ class ApiQueryContinueTest extends ApiQueryContinueTestBase {
);
};
// 2 lists
- $data = $this->query( $mk( 99, 99 ), 1, '2L', false );
+ $data = $this->query( $mk( 99, 99 ), 1, '2L', false ) +
+ array( 'batchcomplete' => true );
$this->checkC( $data, $mk( 1, 1 ), 5, '2L-11' );
$this->checkC( $data, $mk( 2, 2 ), 3, '2L-22' );
$this->checkC( $data, $mk( 3, 3 ), 2, '2L-33' );
@@ -119,7 +119,8 @@ class ApiQueryContinueTest extends ApiQueryContinueTestBase {
);
};
// generator + 1 prop
- $data = $this->query( $mk( 99, 99 ), 1, 'G1P', false );
+ $data = $this->query( $mk( 99, 99 ), 1, 'G1P', false ) +
+ array( 'batchcomplete' => true );
$this->checkC( $data, $mk( 1, 1 ), 11, 'G1P-11' );
$this->checkC( $data, $mk( 2, 2 ), 6, 'G1P-22' );
$this->checkC( $data, $mk( 3, 3 ), 4, 'G1P-33' );
@@ -144,7 +145,8 @@ class ApiQueryContinueTest extends ApiQueryContinueTestBase {
);
};
// generator + 2 props
- $data = $this->query( $mk( 99, 99, 99 ), 1, 'G2P', false );
+ $data = $this->query( $mk( 99, 99, 99 ), 1, 'G2P', false ) +
+ array( 'batchcomplete' => true );
$this->checkC( $data, $mk( 1, 1, 1 ), 16, 'G2P-111' );
$this->checkC( $data, $mk( 2, 2, 2 ), 9, 'G2P-222' );
$this->checkC( $data, $mk( 3, 3, 3 ), 6, 'G2P-333' );
@@ -177,7 +179,8 @@ class ApiQueryContinueTest extends ApiQueryContinueTestBase {
);
};
// generator + 1 prop + 1 list
- $data = $this->query( $mk( 99, 99, 99 ), 1, 'G1P1L', false );
+ $data = $this->query( $mk( 99, 99, 99 ), 1, 'G1P1L', false ) +
+ array( 'batchcomplete' => true );
$this->checkC( $data, $mk( 1, 1, 1 ), 11, 'G1P1L-111' );
$this->checkC( $data, $mk( 2, 2, 2 ), 6, 'G1P1L-222' );
$this->checkC( $data, $mk( 3, 3, 3 ), 4, 'G1P1L-333' );
@@ -214,7 +217,8 @@ class ApiQueryContinueTest extends ApiQueryContinueTestBase {
);
};
// generator + 1 prop + 1 list
- $data = $this->query( $mk( 99, 99, 99, 99, 99 ), 1, 'G2P2L1M', false );
+ $data = $this->query( $mk( 99, 99, 99, 99, 99 ), 1, 'G2P2L1M', false ) +
+ array( 'batchcomplete' => true );
$this->checkC( $data, $mk( 1, 1, 1, 1, 1 ), 16, 'G2P2L1M-11111' );
$this->checkC( $data, $mk( 2, 2, 2, 2, 2 ), 9, 'G2P2L1M-22222' );
$this->checkC( $data, $mk( 3, 3, 3, 3, 3 ), 6, 'G2P2L1M-33333' );
@@ -244,7 +248,8 @@ class ApiQueryContinueTest extends ApiQueryContinueTestBase {
);
};
// generator + 1 prop
- $data = $this->query( $mk( 99, true, 99, true ), 1, 'G=P', false );
+ $data = $this->query( $mk( 99, true, 99, true ), 1, 'G=P', false ) +
+ array( 'batchcomplete' => true );
$this->checkC( $data, $mk( 1, true, 1, true ), 4, 'G=P-1t1t' );
$this->checkC( $data, $mk( 2, true, 2, true ), 2, 'G=P-2t2t' );
@@ -290,7 +295,8 @@ class ApiQueryContinueTest extends ApiQueryContinueTestBase {
);
};
// generator + 1 list
- $data = $this->query( $mk( 99, true, 99, true ), 1, 'G=L', false );
+ $data = $this->query( $mk( 99, true, 99, true ), 1, 'G=L', false ) +
+ array( 'batchcomplete' => true );
$this->checkC( $data, $mk( 1, true, 1, true ), 5, 'G=L-1t1t' );
$this->checkC( $data, $mk( 2, true, 2, true ), 3, 'G=L-2t2t' );
diff --git a/tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php b/tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php
index bce62685..ce2f70de 100644
--- a/tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php
+++ b/tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php
@@ -21,9 +21,6 @@
*
* @file
*/
-
-require_once 'ApiQueryTestBase.php';
-
abstract class ApiQueryContinueTestBase extends ApiQueryTestBase {
/**
@@ -62,6 +59,8 @@ abstract class ApiQueryContinueTestBase extends ApiQueryTestBase {
}
if ( $useContinue && !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 bba22c77..5f061b50 100644
--- a/tests/phpunit/includes/api/query/ApiQueryTest.php
+++ b/tests/phpunit/includes/api/query/ApiQueryTest.php
@@ -7,32 +7,21 @@
* @covers ApiQuery
*/
class ApiQueryTest extends ApiTestCase {
- /**
- * @var array Storage for $wgHooks
- */
- protected $hooks;
-
protected function setUp() {
- global $wgHooks;
-
parent::setUp();
$this->doLogin();
- // Setup en: as interwiki prefix
- $this->hooks = $wgHooks;
- $wgHooks['InterwikiLoadPrefix'][] = function ( $prefix, &$data ) {
- if ( $prefix == 'apiquerytestiw' ) {
- $data = array( 'iw_url' => 'wikipedia' );
- }
- return false;
- };
- }
-
- protected function tearDown() {
- global $wgHooks;
- $wgHooks = $this->hooks;
-
- parent::tearDown();
+ // Setup apiquerytestiw: as interwiki prefix
+ $this->setMwGlobals( 'wgHooks', array(
+ 'InterwikiLoadPrefix' => array(
+ function ( $prefix, &$data ) {
+ if ( $prefix == 'apiquerytestiw' ) {
+ $data = array( 'iw_url' => 'wikipedia' );
+ }
+ return false;
+ }
+ )
+ ) );
}
public function testTitlesGetNormalized() {
@@ -127,4 +116,27 @@ class ApiQueryTest extends ApiTestCase {
array( 'apiquerytestiw:foo', NS_MAIN, null, true ),
);
}
+
+ /**
+ * Test if all classes in the query module manager exists
+ */
+ public function testClassNamesInModuleManager() {
+ global $wgAutoloadLocalClasses, $wgAutoloadClasses;
+
+ // wgAutoloadLocalClasses has precedence, just like in includes/AutoLoader.php
+ $classes = $wgAutoloadLocalClasses + $wgAutoloadClasses;
+
+ $api = new ApiMain(
+ new FauxRequest( array( 'action' => 'query', 'meta' => 'siteinfo' ) )
+ );
+ $queryApi = new ApiQuery( $api, 'query' );
+ $modules = $queryApi->getModuleManager()->getNamesWithClasses();
+ foreach( $modules as $name => $class ) {
+ $this->assertArrayHasKey(
+ $class,
+ $classes,
+ 'Class ' . $class . ' for api module ' . $name . ' not in autoloader (with exact case)'
+ );
+ }
+ }
}
diff --git a/tests/phpunit/includes/api/query/ApiQueryTestBase.php b/tests/phpunit/includes/api/query/ApiQueryTestBase.php
index 56c15b23..dabf72e0 100644
--- a/tests/phpunit/includes/api/query/ApiQueryTestBase.php
+++ b/tests/phpunit/includes/api/query/ApiQueryTestBase.php
@@ -88,19 +88,26 @@ STR;
/**
* Checks that the request's result matches the expected results.
* @param array $values Array is a two element array( request, expected_results )
- * @throws Exception
+ * @param array $session
+ * @param bool $appendModule
+ * @param User $user
*/
- protected function check( $values ) {
+ protected function check( $values, array $session = null,
+ $appendModule = false, User $user = null
+ ) {
list( $req, $exp ) = $this->validateRequestExpectedPair( $values );
if ( !array_key_exists( 'action', $req ) ) {
$req['action'] = 'query';
}
+ if ( !array_key_exists( 'continue', $req ) ) {
+ $req['rawcontinue'] = '1';
+ }
foreach ( $req as &$val ) {
if ( is_array( $val ) ) {
$val = implode( '|', array_unique( $val ) );
}
}
- $result = $this->doApiRequest( $req );
+ $result = $this->doApiRequest( $req, $session, $appendModule, $user );
$this->assertResult( array( 'query' => $exp ), $result[0], $req );
}
@@ -113,9 +120,16 @@ STR;
if ( is_array( $message ) ) {
$message = http_build_query( $message );
}
+
+ // FIXME: once we migrate to phpunit 4.1+, hardcode ComparisonFailure exception use
+ $compEx = 'SebastianBergmann\Comparator\ComparisonFailure';
+ if ( !class_exists( $compEx ) ) {
+ $compEx = 'PHPUnit_Framework_ComparisonFailure';
+ }
+
throw new PHPUnit_Framework_ExpectationFailedException(
$e->getMessage() . "\nRequest: $message",
- new PHPUnit_Framework_ComparisonFailure(
+ new $compEx(
$exp,
$result,
print_r( $exp, true ),
diff --git a/tests/phpunit/includes/cache/GenderCacheTest.php b/tests/phpunit/includes/cache/GenderCacheTest.php
index ce2db5d7..04fb00d9 100644
--- a/tests/phpunit/includes/cache/GenderCacheTest.php
+++ b/tests/phpunit/includes/cache/GenderCacheTest.php
@@ -6,14 +6,10 @@
*/
class GenderCacheTest extends MediaWikiLangTestCase {
- protected function setUp() {
- global $wgDefaultUserOptions;
- parent::setUp();
+ function addDBData() {
//ensure the correct default gender
- $wgDefaultUserOptions['gender'] = 'unknown';
- }
+ $this->mergeMwGlobalArrayValue( 'wgDefaultUserOptions', array( 'gender' => 'unknown' ) );
- function addDBData() {
$user = User::newFromName( 'UTMale' );
if ( $user->getID() == 0 ) {
$user->addToDatabase();
diff --git a/tests/phpunit/includes/cache/LocalisationCacheTest.php b/tests/phpunit/includes/cache/LocalisationCacheTest.php
index fc06a501..a0d308aa 100644
--- a/tests/phpunit/includes/cache/LocalisationCacheTest.php
+++ b/tests/phpunit/includes/cache/LocalisationCacheTest.php
@@ -7,18 +7,32 @@
*/
class LocalisationCacheTest extends MediaWikiTestCase {
protected function setUp() {
- global $IP;
-
parent::setUp();
$this->setMwGlobals( array(
- 'wgMessagesDirs' => array( "$IP/tests/phpunit/data/localisationcache" ),
'wgExtensionMessagesFiles' => array(),
'wgHooks' => array(),
) );
}
+ /**
+ * @return PHPUnit_Framework_MockObject_MockObject|LocalisationCache
+ */
+ protected function getMockLocalisationCache() {
+ global $IP;
+ $lc = $this->getMockBuilder( 'LocalisationCache' )
+ ->setConstructorArgs( array( array( 'store' => 'detect' ) ) )
+ ->setMethods( array( 'getMessagesDirs' ) )
+ ->getMock();
+ $lc->expects( $this->any() )->method( 'getMessagesDirs' )
+ ->will( $this->returnValue(
+ array( "$IP/tests/phpunit/data/localisationcache" )
+ ) );
+
+ return $lc;
+ }
+
public function testPuralRulesFallback() {
- $cache = new LocalisationCache( array( 'store' => 'detect' ) );
+ $cache = $this->getMockLocalisationCache();
$this->assertEquals(
$cache->getItem( 'ar', 'pluralRules' ),
@@ -46,7 +60,7 @@ class LocalisationCacheTest extends MediaWikiTestCase {
}
public function testRecacheFallbacks() {
- $lc = new LocalisationCache( array( 'store' => 'detect' ) );
+ $lc = $this->getMockLocalisationCache();
$lc->recache( 'uk' );
$this->assertEquals(
array(
@@ -60,23 +74,25 @@ class LocalisationCacheTest extends MediaWikiTestCase {
}
public function testRecacheFallbacksWithHooks() {
- global $wgHooks;
-
// Use hook to provide updates for messages. This is what the
// LocalisationUpdate extension does. See bug 68781.
- $wgHooks['LocalisationCacheRecacheFallback'][] = function (
- LocalisationCache $lc,
- $code,
- array &$cache
- ) {
- if ( $code === 'ru' ) {
- $cache['messages']['present-uk'] = 'ru-override';
- $cache['messages']['present-ru'] = 'ru-override';
- $cache['messages']['present-en'] = 'ru-override';
- }
- };
+ $this->mergeMwGlobalArrayValue( 'wgHooks', array(
+ 'LocalisationCacheRecacheFallback' => array(
+ function (
+ LocalisationCache $lc,
+ $code,
+ array &$cache
+ ) {
+ if ( $code === 'ru' ) {
+ $cache['messages']['present-uk'] = 'ru-override';
+ $cache['messages']['present-ru'] = 'ru-override';
+ $cache['messages']['present-en'] = 'ru-override';
+ }
+ }
+ )
+ ) );
- $lc = new LocalisationCache( array( 'store' => 'detect' ) );
+ $lc = $this->getMockLocalisationCache();
$lc->recache( 'uk' );
$this->assertEquals(
array(
diff --git a/tests/phpunit/includes/cache/RedisBloomCacheTest.php b/tests/phpunit/includes/cache/RedisBloomCacheTest.php
deleted file mode 100644
index 3d491e90..00000000
--- a/tests/phpunit/includes/cache/RedisBloomCacheTest.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-/**
- * Test for BloomCacheRedis class.
- *
- * @TODO: some generic base "redis test server conf" for all testing?
- *
- * @covers BloomCacheRedis
- * @group Cache
- */
-class BloomCacheRedisTest extends MediaWikiTestCase {
- private static $suffix;
-
- protected function setUp() {
- parent::setUp();
-
- self::$suffix = self::$suffix ? : mt_rand();
-
- $fcache = BloomCache::get( 'main' );
- if ( $fcache instanceof BloomCacheRedis ) {
- $fcache->delete( "unit-testing-" . self::$suffix );
- } else {
- $this->markTestSkipped( 'The main bloom cache is not redis.' );
- }
- }
-
- public function testBloomCache() {
- $key = "unit-testing-" . self::$suffix;
- $fcache = BloomCache::get( 'main' );
- $count = 1500;
-
- $this->assertTrue( $fcache->delete( $key ), "OK delete of filter '$key'." );
- $this->assertTrue( $fcache->init( $key, $count, .001 ), "OK init of filter '$key'." );
-
- $members = array();
- for ( $i = 0; $i < $count; ++$i ) {
- $members[] = "$i-value-$i";
- }
- $this->assertTrue( $fcache->add( $key, $members ), "Addition of members to '$key' OK." );
-
- for ( $i = 0; $i < $count; ++$i ) {
- $this->assertTrue( $fcache->isHit( $key, "$i-value-$i" ), "Hit on member '$i-value-$i'." );
- }
-
- $falsePositives = array();
- for ( $i = $count; $i < 2 * $count; ++$i ) {
- if ( $fcache->isHit( $key, "value$i" ) ) {
- $falsePositives[] = "value$i";
- }
- }
-
- $eFalsePositives = array(
- 'value1763',
- 'value2245',
- 'value2353',
- 'value2791',
- 'value2898',
- 'value2975'
- );
- $this->assertEquals( $eFalsePositives, $falsePositives, "Correct number of false positives found." );
- }
-
- protected function tearDown() {
- parent::tearDown();
-
- $fcache = BloomCache::get( 'main' );
- if ( $fcache instanceof BloomCacheRedis ) {
- $fcache->delete( "unit-testing-" . self::$suffix );
- }
- }
-}
diff --git a/tests/phpunit/includes/changes/EnhancedChangesListTest.php b/tests/phpunit/includes/changes/EnhancedChangesListTest.php
index 40a11d2d..a14a50d2 100644
--- a/tests/phpunit/includes/changes/EnhancedChangesListTest.php
+++ b/tests/phpunit/includes/changes/EnhancedChangesListTest.php
@@ -5,7 +5,6 @@
*
* @group Database
*
- * @licence GNU GPL v2+
* @author Katie Filbert < aude.wiki@gmail.com >
*/
class EnhancedChangesListTest extends MediaWikiLangTestCase {
@@ -31,7 +30,7 @@ class EnhancedChangesListTest extends MediaWikiLangTestCase {
'mediawiki.special.changeslist',
$styleModules,
'has mediawiki.special.changeslist'
- );
+ );
$this->assertContains(
'mediawiki.special.changeslist.enhanced',
@@ -75,10 +74,10 @@ class EnhancedChangesListTest extends MediaWikiLangTestCase {
$this->assertEquals( '', $html );
}
- /**
- * @todo more tests for actual formatting, this is more of a smoke test
- */
- public function testEndRecentChangesList() {
+ /**
+ * @todo more tests for actual formatting, this is more of a smoke test
+ */
+ public function testEndRecentChangesList() {
$enhancedChangesList = $this->newEnhancedChangesList();
$enhancedChangesList->beginRecentChangesList();
@@ -92,7 +91,7 @@ class EnhancedChangesListTest extends MediaWikiLangTestCase {
preg_match_all( '/td class="mw-enhanced-rc-nested"/', $html, $matches );
$this->assertCount( 2, $matches[0] );
- }
+ }
/**
* @return EnhancedChangesList
diff --git a/tests/phpunit/includes/changes/OldChangesListTest.php b/tests/phpunit/includes/changes/OldChangesListTest.php
index 2ea9f33e..311ad89c 100644
--- a/tests/phpunit/includes/changes/OldChangesListTest.php
+++ b/tests/phpunit/includes/changes/OldChangesListTest.php
@@ -9,7 +9,6 @@
*
* @group Database
*
- * @licence GNU GPL v2+
* @author Katie Filbert < aude.wiki@gmail.com >
*/
class OldChangesListTest extends MediaWikiLangTestCase {
diff --git a/tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php b/tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php
index ee1a4d0e..0b877275 100644
--- a/tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php
+++ b/tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php
@@ -5,7 +5,6 @@
*
* @group Database
*
- * @licence GNU GPL v2+
* @author Katie Filbert < aude.wiki@gmail.com >
*/
class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
diff --git a/tests/phpunit/includes/changes/RecentChangeTest.php b/tests/phpunit/includes/changes/RecentChangeTest.php
index 98903f1e..b3cb7b52 100644
--- a/tests/phpunit/includes/changes/RecentChangeTest.php
+++ b/tests/phpunit/includes/changes/RecentChangeTest.php
@@ -35,6 +35,7 @@ class RecentChangeTest extends MediaWikiTestCase {
* Should cover the following log actions (which are most commonly used by bots):
* - block/block
* - block/unblock
+ * - block/reblock
* - delete/delete
* - delete/restore
* - newusers/create
@@ -46,6 +47,9 @@ class RecentChangeTest extends MediaWikiTestCase {
* - protect/modifyprotect
* - protect/unprotect
* - upload/upload
+ * - merge/merge
+ * - import/upload
+ * - import/interwiki
*
* As well as the following Auto Edit Summaries:
* - blank
@@ -62,9 +66,13 @@ class RecentChangeTest extends MediaWikiTestCase {
# block/block
$this->assertIRCComment(
- $this->context->msg( 'blocklogentry', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ $this->context->msg( 'blocklogentry', 'SomeTitle', 'duration', '(flags)' )->plain()
+ . $sep . $this->user_comment,
'block', 'block',
- array(),
+ array(
+ '5::duration' => 'duration',
+ '6::flags' => 'flags',
+ ),
$this->user_comment
);
# block/unblock
@@ -74,6 +82,17 @@ class RecentChangeTest extends MediaWikiTestCase {
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
+ );
}
/**
@@ -230,6 +249,48 @@ class RecentChangeTest extends MediaWikiTestCase {
}
/**
+ * @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::getIRCActionText
+ */
+ 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
+ );
+
+ # import/interwiki
+ $this->assertIRCComment(
+ $this->context->msg( 'import-logentry-interwiki', 'SomeTitle' )->plain() . $sep . $this->user_comment,
+ 'import', 'interwiki',
+ array(),
+ $this->user_comment
+ );
+ }
+
+ /**
* @todo Emulate these edits somehow and extract
* raw edit summary from RecentChange object
* --
diff --git a/tests/phpunit/includes/changes/TestRecentChangesHelper.php b/tests/phpunit/includes/changes/TestRecentChangesHelper.php
index ad643274..2506087b 100644
--- a/tests/phpunit/includes/changes/TestRecentChangesHelper.php
+++ b/tests/phpunit/includes/changes/TestRecentChangesHelper.php
@@ -3,7 +3,6 @@
/**
* Helper for generating test recent changes entries.
*
- * @licence GNU GPL v2+
* @author Katie Filbert < aude.wiki@gmail.com >
*/
class TestRecentChangesHelper {
diff --git a/tests/phpunit/includes/composer/ComposerVersionNormalizerTest.php b/tests/phpunit/includes/composer/ComposerVersionNormalizerTest.php
index 3f887dc0..2fa11eaf 100644
--- a/tests/phpunit/includes/composer/ComposerVersionNormalizerTest.php
+++ b/tests/phpunit/includes/composer/ComposerVersionNormalizerTest.php
@@ -5,7 +5,6 @@
*
* @group ComposerHooks
*
- * @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
class ComposerVersionNormalizerTest extends PHPUnit_Framework_TestCase {
diff --git a/tests/phpunit/includes/config/GlobalVarConfigTest.php b/tests/phpunit/includes/config/GlobalVarConfigTest.php
index 70b9e684..28068d5e 100644
--- a/tests/phpunit/includes/config/GlobalVarConfigTest.php
+++ b/tests/phpunit/includes/config/GlobalVarConfigTest.php
@@ -87,34 +87,10 @@ class GlobalVarConfigTest extends MediaWikiTestCase {
$this->assertEquals( $config->get( $name ), $expected );
}
- public static function provideSet() {
- return array(
- array( 'Foo', 'wg', 'wgFoo' ),
- array( 'SomethingRandom', 'wg', 'wgSomethingRandom' ),
- array( 'FromAnExtension', 'eg', 'egFromAnExtension' ),
- array( 'NoPrefixHere', '', 'NoPrefixHere' ),
- );
- }
-
private function maybeStashGlobal( $var ) {
if ( array_key_exists( $var, $GLOBALS ) ) {
// Will be reset after this test is over
$this->stashMwGlobals( $var );
}
}
-
- /**
- * @dataProvider provideSet
- * @covers GlobalVarConfig::set
- * @covers GlobalVarConfig::setWithPrefix
- */
- public function testSet( $name, $prefix, $var ) {
- $this->hideDeprecated( 'GlobalVarConfig::set' );
- $this->maybeStashGlobal( $var );
- $config = new GlobalVarConfig( $prefix );
- $random = wfRandomString();
- $config->set( $name, $random );
- $this->assertArrayHasKey( $var, $GLOBALS );
- $this->assertEquals( $random, $GLOBALS[$var] );
- }
}
diff --git a/tests/phpunit/includes/config/HashConfigTest.php b/tests/phpunit/includes/config/HashConfigTest.php
index 3ad3bfbd..06973b09 100644
--- a/tests/phpunit/includes/config/HashConfigTest.php
+++ b/tests/phpunit/includes/config/HashConfigTest.php
@@ -60,4 +60,4 @@ class HashConfigTest extends MediaWikiTestCase {
$conf->set( 'one', '3' );
$this->assertEquals( '3', $conf->get( 'one' ) );
}
-} \ No newline at end of file
+}
diff --git a/tests/phpunit/includes/content/ContentHandlerTest.php b/tests/phpunit/includes/content/ContentHandlerTest.php
index f7449734..988a59ee 100644
--- a/tests/phpunit/includes/content/ContentHandlerTest.php
+++ b/tests/phpunit/includes/content/ContentHandlerTest.php
@@ -2,11 +2,6 @@
/**
* @group ContentHandler
- * @group Database
- *
- * @note Declare that we are using the database, because otherwise we'll fail in
- * the "databaseless" test run. This is because the LinkHolderArray used by the
- * parser needs database access.
*/
class ContentHandlerTest extends MediaWikiTestCase {
@@ -36,6 +31,8 @@ class ContentHandlerTest extends MediaWikiTestCase {
// Reset namespace cache
MWNamespace::getCanonicalNamespaces( true );
$wgContLang->resetNamespaces();
+ // And LinkCache
+ LinkCache::destroySingleton();
}
protected function tearDown() {
@@ -44,6 +41,8 @@ class ContentHandlerTest extends MediaWikiTestCase {
// Reset namespace cache
MWNamespace::getCanonicalNamespaces( true );
$wgContLang->resetNamespaces();
+ // And LinkCache
+ LinkCache::destroySingleton();
parent::tearDown();
}
@@ -83,6 +82,7 @@ class ContentHandlerTest extends MediaWikiTestCase {
*/
public function testGetForTitle( $title, $expectedContentModel ) {
$title = Title::newFromText( $title );
+ LinkCache::singleton()->addBadLinkObj( $title );
$handler = ContentHandler::getForTitle( $title );
$this->assertEquals( $expectedContentModel, $handler->getModelID() );
}
@@ -139,6 +139,7 @@ class ContentHandlerTest extends MediaWikiTestCase {
public function testGetPageLanguage( $title, $expected ) {
if ( is_string( $title ) ) {
$title = Title::newFromText( $title );
+ LinkCache::singleton()->addBadLinkObj( $title );
}
$expected = wfGetLangObj( $expected );
@@ -292,7 +293,7 @@ class ContentHandlerTest extends MediaWikiTestCase {
$expectedModelId, $expectedNativeData, $shouldFail
) {
$title = Title::newFromText( $title );
-
+ LinkCache::singleton()->addBadLinkObj( $title );
try {
$content = ContentHandler::makeContent( $data, $title, $modelId, $format );
@@ -317,6 +318,8 @@ class ContentHandlerTest extends MediaWikiTestCase {
* page.
*/
public function testGetAutosummary() {
+ $this->setMwGlobals( 'wgContLang', Language::factory( 'en' ) );
+
$content = new DummyContentHandlerForTesting( CONTENT_MODEL_WIKITEXT );
$title = Title::newFromText( 'Help:Test' );
// Create a new content object with no content
diff --git a/tests/phpunit/includes/content/JsonContentTest.php b/tests/phpunit/includes/content/JsonContentTest.php
index 77b542f4..cccfe7b1 100644
--- a/tests/phpunit/includes/content/JsonContentTest.php
+++ b/tests/phpunit/includes/content/JsonContentTest.php
@@ -6,48 +6,85 @@
*/
class JsonContentTest extends MediaWikiLangTestCase {
- /**
- * @dataProvider provideValidConstruction
- */
- public function testValidConstruct( $text, $modelId, $isValid, $expected ) {
- $obj = new JsonContent( $text, $modelId );
- $this->assertEquals( $isValid, $obj->isValid() );
- $this->assertEquals( $expected, $obj->getJsonData() );
+ protected function setUp() {
+ parent::setUp();
+
+ $this->setMwGlobals( 'wgWellFormedXml', true );
}
public static function provideValidConstruction() {
return array(
- array( 'foo', CONTENT_MODEL_JSON, false, null ),
- array( FormatJson::encode( array() ), CONTENT_MODEL_JSON, true, array() ),
- array( FormatJson::encode( array( 'foo' ) ), CONTENT_MODEL_JSON, true, array( 'foo' ) ),
+ array( 'foo', false, null ),
+ array( '[]', true, array() ),
+ array( '{}', true, (object)array() ),
+ array( '""', true, '' ),
+ array( '"0"', true, '0' ),
+ array( '"bar"', true, 'bar' ),
+ array( '0', true, '0' ),
+ array( '{ "0": "bar" }', true, (object)array( 'bar' ) ),
);
}
/**
- * @dataProvider provideDataToEncode
+ * @dataProvider provideValidConstruction
*/
- public function testBeautifyUsesFormatJson( $data ) {
- $obj = new JsonContent( FormatJson::encode( $data ) );
- $this->assertEquals( FormatJson::encode( $data, true ), $obj->beautifyJSON() );
+ public function testIsValid( $text, $isValid, $expected ) {
+ $obj = new JsonContent( $text, CONTENT_MODEL_JSON );
+ $this->assertEquals( $isValid, $obj->isValid() );
+ $this->assertEquals( $expected, $obj->getData()->getValue() );
}
public static function provideDataToEncode() {
return array(
- array( array() ),
- array( array( 'foo' ) ),
- array( array( 'foo', 'bar' ) ),
- array( array( 'baz' => 'foo', 'bar' ) ),
- array( array( 'baz' => 1000, 'bar' ) ),
+ array(
+ // Round-trip empty array
+ '[]',
+ '[]',
+ ),
+ array(
+ // Round-trip empty object
+ '{}',
+ '{}',
+ ),
+ array(
+ // Round-trip empty array/object (nested)
+ '{ "foo": {}, "bar": [] }',
+ "{\n \"foo\": {},\n \"bar\": []\n}",
+ ),
+ array(
+ '{ "foo": "bar" }',
+ "{\n \"foo\": \"bar\"\n}",
+ ),
+ array(
+ '{ "foo": 1000 }',
+ "{\n \"foo\": 1000\n}",
+ ),
+ array(
+ '{ "foo": 1000, "0": "bar" }',
+ "{\n \"foo\": 1000,\n \"0\": \"bar\"\n}",
+ ),
);
}
/**
* @dataProvider provideDataToEncode
*/
- public function testPreSaveTransform( $data ) {
- $obj = new JsonContent( FormatJson::encode( $data ) );
- $newObj = $obj->preSaveTransform( $this->getMockTitle(), $this->getMockUser(), $this->getMockParserOptions() );
- $this->assertTrue( $newObj->equals( new JsonContent( FormatJson::encode( $data, true ) ) ) );
+ public function testBeautifyJson( $input, $beautified ) {
+ $obj = new JsonContent( $input );
+ $this->assertEquals( $beautified, $obj->beautifyJSON() );
+ }
+
+ /**
+ * @dataProvider provideDataToEncode
+ */
+ public function testPreSaveTransform( $input, $transformed ) {
+ $obj = new JsonContent( $input );
+ $newObj = $obj->preSaveTransform(
+ $this->getMockTitle(),
+ $this->getMockUser(),
+ $this->getMockParserOptions()
+ );
+ $this->assertTrue( $newObj->equals( new JsonContent( $transformed ) ) );
}
private function getMockTitle() {
@@ -67,48 +104,55 @@ class JsonContentTest extends MediaWikiLangTestCase {
->getMock();
}
- /**
- * @dataProvider provideDataAndParserText
- */
- public function testFillParserOutput( $data, $expected ) {
- $obj = new JsonContent( FormatJson::encode( $data ) );
- $parserOutput = $obj->getParserOutput( $this->getMockTitle(), null, null, true );
- $this->assertInstanceOf( 'ParserOutput', $parserOutput );
- $this->assertEquals( $expected, $parserOutput->getText() );
- }
-
public static function provideDataAndParserText() {
return array(
array(
array(),
- '<table class="mw-json"><tbody></tbody></table>'
+ '<table class="mw-json"><tbody><tr><td>' .
+ '<table class="mw-json"><tbody><tr><td class="mw-json-empty">Empty array</td></tr>'
+ . '</tbody></table></td></tr></tbody></table>'
),
array(
- array( 'foo' ),
- '<table class="mw-json"><tbody><tr><th>0</th><td class="value">&quot;foo&quot;</td></tr></tbody></table>'
+ (object)array(),
+ '<table class="mw-json"><tbody><tr><td class="mw-json-empty">Empty object</td></tr>' .
+ '</tbody></table>'
),
array(
- array( 'foo', 'bar' ),
- '<table class="mw-json"><tbody><tr><th>0</th><td class="value">&quot;foo&quot;</td></tr>' .
- "\n" .
- '<tr><th>1</th><td class="value">&quot;bar&quot;</td></tr></tbody></table>'
+ (object)array( 'foo' ),
+ '<table class="mw-json"><tbody><tr><th>0</th><td class="value">"foo"</td></tr>' .
+ '</tbody></table>'
),
array(
- array( 'baz' => 'foo', 'bar' ),
- '<table class="mw-json"><tbody><tr><th>baz</th><td class="value">&quot;foo&quot;</td></tr>' .
- "\n" .
- '<tr><th>0</th><td class="value">&quot;bar&quot;</td></tr></tbody></table>'
+ (object)array( 'foo', 'bar' ),
+ '<table class="mw-json"><tbody><tr><th>0</th><td class="value">"foo"</td></tr>' .
+ '<tr><th>1</th><td class="value">"bar"</td></tr></tbody></table>'
),
array(
- array( 'baz' => 1000, 'bar' ),
+ (object)array( 'baz' => 'foo', 'bar' ),
+ '<table class="mw-json"><tbody><tr><th>baz</th><td class="value">"foo"</td></tr>' .
+ '<tr><th>0</th><td class="value">"bar"</td></tr></tbody></table>'
+ ),
+ array(
+ (object)array( 'baz' => 1000, 'bar' ),
'<table class="mw-json"><tbody><tr><th>baz</th><td class="value">1000</td></tr>' .
- "\n" .
- '<tr><th>0</th><td class="value">&quot;bar&quot;</td></tr></tbody></table>'
+ '<tr><th>0</th><td class="value">"bar"</td></tr></tbody></table>'
),
array(
- array( '<script>alert("evil!")</script>'),
- '<table class="mw-json"><tbody><tr><th>0</th><td class="value">&quot;&lt;script&gt;alert(&quot;evil!&quot;)&lt;/script&gt;&quot;</td></tr></tbody></table>',
+ (object)array( '<script>alert("evil!")</script>'),
+ '<table class="mw-json"><tbody><tr><th>0</th><td class="value">"' .
+ '&lt;script>alert("evil!")&lt;/script>"' .
+ '</td></tr></tbody></table>',
),
);
}
+
+ /**
+ * @dataProvider provideDataAndParserText
+ */
+ public function testFillParserOutput( $data, $expected ) {
+ $obj = new JsonContent( FormatJson::encode( $data ) );
+ $parserOutput = $obj->getParserOutput( $this->getMockTitle(), null, null, true );
+ $this->assertInstanceOf( 'ParserOutput', $parserOutput );
+ $this->assertEquals( $expected, $parserOutput->getText() );
+ }
}
diff --git a/tests/phpunit/includes/content/TextContentTest.php b/tests/phpunit/includes/content/TextContentTest.php
index 2f811094..dd61f85b 100644
--- a/tests/phpunit/includes/content/TextContentTest.php
+++ b/tests/phpunit/includes/content/TextContentTest.php
@@ -7,11 +7,8 @@
*/
class TextContentTest extends MediaWikiLangTestCase {
protected $context;
- protected $savedContentGetParserOutput;
protected function setUp() {
- global $wgHooks;
-
parent::setUp();
// Anon user
@@ -32,24 +29,8 @@ class TextContentTest extends MediaWikiLangTestCase {
'wgUseTidy' => false,
'wgAlwaysUseTidy' => false,
'wgCapitalLinks' => true,
+ 'wgHooks' => array(), // bypass hook ContentGetParserOutput that force custom rendering
) );
-
- // bypass hooks that force custom rendering
- if ( isset( $wgHooks['ContentGetParserOutput'] ) ) {
- $this->savedContentGetParserOutput = $wgHooks['ContentGetParserOutput'];
- unset( $wgHooks['ContentGetParserOutput'] );
- }
- }
-
- public function teardown() {
- global $wgHooks;
-
- // restore hooks that force custom rendering
- if ( $this->savedContentGetParserOutput !== null ) {
- $wgHooks['ContentGetParserOutput'] = $this->savedContentGetParserOutput;
- }
-
- parent::teardown();
}
public function newContent( $text ) {
diff --git a/tests/phpunit/includes/RequestContextTest.php b/tests/phpunit/includes/context/RequestContextTest.php
index cae0e52e..a9e5be24 100644
--- a/tests/phpunit/includes/RequestContextTest.php
+++ b/tests/phpunit/includes/context/RequestContextTest.php
@@ -88,9 +88,9 @@ class RequestContextTest extends MediaWikiTestCase {
unset( $sc ); // restore previous context
$info = $context->exportSession();
- $this->assertEquals( $oInfo['ip'], $info['ip'], "Correct initial IP address." );
- $this->assertEquals( $oInfo['headers'], $info['headers'], "Correct initial headers." );
- $this->assertEquals( $oInfo['sessionId'], $info['sessionId'], "Correct initial session ID." );
- $this->assertEquals( $oInfo['userId'], $info['userId'], "Correct initial user ID." );
+ $this->assertEquals( $oInfo['ip'], $info['ip'], "Correct restored IP address." );
+ $this->assertEquals( $oInfo['headers'], $info['headers'], "Correct restored headers." );
+ $this->assertEquals( $oInfo['sessionId'], $info['sessionId'], "Correct restored session ID." );
+ $this->assertEquals( $oInfo['userId'], $info['userId'], "Correct restored user ID." );
}
}
diff --git a/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php b/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php
index 55e48d13..b4292a60 100644
--- a/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php
+++ b/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php
@@ -2,7 +2,6 @@
/**
* Holds tests for DatabaseMysqlBase MediaWiki class.
*
- * @section LICENSE
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
diff --git a/tests/phpunit/includes/db/DatabaseSQLTest.php b/tests/phpunit/includes/db/DatabaseSQLTest.php
index 5c2d4b70..b13751f3 100644
--- a/tests/phpunit/includes/db/DatabaseSQLTest.php
+++ b/tests/phpunit/includes/db/DatabaseSQLTest.php
@@ -722,4 +722,84 @@ class DatabaseSQLTest extends MediaWikiTestCase {
$this->database->dropTable( 'non_existing', __METHOD__ )
);
}
+
+ /**
+ * @dataProvider provideMakeList
+ * @covers DatabaseBase::makeList
+ */
+ public function testMakeList( $list, $mode, $sqlText ) {
+ $this->assertEquals( trim( $this->database->makeList(
+ $list, $mode
+ ) ), $sqlText );
+ }
+
+ public static function provideMakeList() {
+ return array(
+ array(
+ array( 'value', 'value2' ),
+ LIST_COMMA,
+ "'value','value2'"
+ ),
+ array(
+ array( 'field', 'field2' ),
+ LIST_NAMES,
+ "field,field2"
+ ),
+ array(
+ array( 'field' => 'value', 'field2' => 'value2' ),
+ LIST_AND,
+ "field = 'value' AND field2 = 'value2'"
+ ),
+ array(
+ array( 'field' => null, "field2 != 'value2'" ),
+ LIST_AND,
+ "field IS NULL AND (field2 != 'value2')"
+ ),
+ array(
+ array( 'field' => array( 'value', null, 'value2' ), 'field2' => 'value2' ),
+ LIST_AND,
+ "(field IN ('value','value2') OR field IS NULL) AND field2 = 'value2'"
+ ),
+ array(
+ array( 'field' => array( null ), 'field2' => null ),
+ LIST_AND,
+ "field IS NULL AND field2 IS NULL"
+ ),
+ array(
+ array( 'field' => 'value', 'field2' => 'value2' ),
+ LIST_OR,
+ "field = 'value' OR field2 = 'value2'"
+ ),
+ array(
+ array( 'field' => 'value', 'field2' => null ),
+ LIST_OR,
+ "field = 'value' OR field2 IS NULL"
+ ),
+ array(
+ array( 'field' => array( 'value', 'value2' ), 'field2' => array( 'value' ) ),
+ LIST_OR,
+ "field IN ('value','value2') OR field2 = 'value'"
+ ),
+ array(
+ array( 'field' => array( null, 'value', null, 'value2' ), "field2 != 'value2'" ),
+ LIST_OR,
+ "(field IN ('value','value2') OR field IS NULL) OR (field2 != 'value2')"
+ ),
+ array(
+ array( 'field' => 'value', 'field2' => 'value2' ),
+ LIST_SET,
+ "field = 'value',field2 = 'value2'"
+ ),
+ array(
+ array( 'field' => 'value', 'field2' => null ),
+ LIST_SET,
+ "field = 'value',field2 = NULL"
+ ),
+ array(
+ array( 'field' => 'value', "field2 != 'value2'" ),
+ LIST_SET,
+ "field = 'value',field2 != 'value2'"
+ ),
+ );
+ }
}
diff --git a/tests/phpunit/includes/db/DatabaseSqliteTest.php b/tests/phpunit/includes/db/DatabaseSqliteTest.php
index 98b4ca04..645baf1f 100644
--- a/tests/phpunit/includes/db/DatabaseSqliteTest.php
+++ b/tests/phpunit/includes/db/DatabaseSqliteTest.php
@@ -1,10 +1,12 @@
<?php
-class MockDatabaseSqlite extends DatabaseSqliteStandalone {
+class MockDatabaseSqlite extends DatabaseSqlite {
private $lastQuery;
- function __construct() {
- parent::__construct( ':memory:' );
+ public static function newInstance( array $p = array() ) {
+ $p['dbFilePath'] = ':memory:';
+
+ return new self( $p );
}
function query( $sql, $fname = '', $tempIgnore = false ) {
@@ -36,7 +38,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
if ( !Sqlite::isPresent() ) {
$this->markTestSkipped( 'No SQLite support detected' );
}
- $this->db = new MockDatabaseSqlite();
+ $this->db = MockDatabaseSqlite::newInstance();
if ( version_compare( $this->db->getServerVersion(), '3.6.0', '<' ) ) {
$this->markTestSkipped( "SQLite at least 3.6 required, {$this->db->getServerVersion()} found" );
}
@@ -89,7 +91,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
*/
public function testAddQuotes( $value, $expected ) {
// check quoting
- $db = new DatabaseSqliteStandalone( ':memory:' );
+ $db = DatabaseSqlite::newStandaloneInstance( ':memory:' );
$this->assertEquals( $expected, $db->addQuotes( $value ), 'string not quoted as expected' );
// ok, quoting works as expected, now try a round trip.
@@ -172,7 +174,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
*/
public function testTableName() {
// @todo Moar!
- $db = new DatabaseSqliteStandalone( ':memory:' );
+ $db = DatabaseSqlite::newStandaloneInstance( ':memory:' );
$this->assertEquals( 'foo', $db->tableName( 'foo' ) );
$this->assertEquals( 'sqlite_master', $db->tableName( 'sqlite_master' ) );
$db->tablePrefix( 'foo' );
@@ -184,7 +186,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
* @covers DatabaseSqlite::duplicateTableStructure
*/
public function testDuplicateTableStructure() {
- $db = new DatabaseSqliteStandalone( ':memory:' );
+ $db = DatabaseSqlite::newStandaloneInstance( ':memory:' );
$db->query( 'CREATE TABLE foo(foo, barfoo)' );
$db->duplicateTableStructure( 'foo', 'bar' );
@@ -208,7 +210,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
* @covers DatabaseSqlite::duplicateTableStructure
*/
public function testDuplicateTableStructureVirtual() {
- $db = new DatabaseSqliteStandalone( ':memory:' );
+ $db = DatabaseSqlite::newStandaloneInstance( ':memory:' );
if ( $db->getFulltextSearchModule() != 'FTS3' ) {
$this->markTestSkipped( 'FTS3 not supported, cannot create virtual tables' );
}
@@ -231,7 +233,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
* @covers DatabaseSqlite::deleteJoin
*/
public function testDeleteJoin() {
- $db = new DatabaseSqliteStandalone( ':memory:' );
+ $db = DatabaseSqlite::newStandaloneInstance( ':memory:' );
$db->query( 'CREATE TABLE a (a_1)', __METHOD__ );
$db->query( 'CREATE TABLE b (b_1, b_2)', __METHOD__ );
$db->insert( 'a', array(
@@ -272,7 +274,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
* @todo Currently only checks list of tables
*/
public function testUpgrades() {
- global $IP, $wgVersion, $wgProfileToDatabase;
+ global $IP, $wgVersion, $wgProfiler;
// Versions tested
$versions = array(
@@ -289,9 +291,20 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
'user_newtalk.user_last_timestamp', // r84185
);
- $currentDB = new DatabaseSqliteStandalone( ':memory:' );
+ $currentDB = DatabaseSqlite::newStandaloneInstance( ':memory:' );
$currentDB->sourceFile( "$IP/maintenance/tables.sql" );
- if ( $wgProfileToDatabase ) {
+
+ $profileToDb = false;
+ if ( isset( $wgProfiler['output'] ) ) {
+ $out = $wgProfiler['output'];
+ if ( $out === 'db' ) {
+ $profileToDb = true;
+ } elseif ( is_array( $out ) && in_array( 'db', $out ) ) {
+ $profileToDb = true;
+ }
+ }
+
+ if ( $profileToDb ) {
$currentDB->sourceFile( "$IP/maintenance/sqlite/archives/patch-profiling.sql" );
}
$currentTables = $this->getTables( $currentDB );
@@ -346,7 +359,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
* @covers DatabaseSqlite::insertId
*/
public function testInsertIdType() {
- $db = new DatabaseSqliteStandalone( ':memory:' );
+ $db = DatabaseSqlite::newStandaloneInstance( ':memory:' );
$databaseCreation = $db->query( 'CREATE TABLE a ( a_1 )', __METHOD__ );
$this->assertInstanceOf( 'ResultWrapper', $databaseCreation, "Database creation" );
@@ -366,7 +379,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
}
global $IP;
- $db = new DatabaseSqliteStandalone( ':memory:' );
+ $db = DatabaseSqlite::newStandaloneInstance( ':memory:' );
$db->sourceFile( "$IP/tests/phpunit/data/db/sqlite/tables-$version.sql" );
$updater = DatabaseUpdater::newForDB( $db, false, $maint );
$updater->doUpdates( array( 'core' ) );
@@ -429,7 +442,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
public function testCaseInsensitiveLike() {
// TODO: Test this for all databases
- $db = new DatabaseSqliteStandalone( ':memory:' );
+ $db = DatabaseSqlite::newStandaloneInstance( ':memory:' );
$res = $db->query( 'SELECT "a" LIKE "A" AS a' );
$row = $res->fetchRow();
$this->assertFalse( (bool)$row['a'] );
@@ -439,7 +452,7 @@ class DatabaseSqliteTest extends MediaWikiTestCase {
* @covers DatabaseSqlite::numFields
*/
public function testNumFields() {
- $db = new DatabaseSqliteStandalone( ':memory:' );
+ $db = DatabaseSqlite::newStandaloneInstance( ':memory:' );
$databaseCreation = $db->query( 'CREATE TABLE a ( a_1 )', __METHOD__ );
$this->assertInstanceOf( 'ResultWrapper', $databaseCreation, "Failed to create table a" );
diff --git a/tests/phpunit/includes/db/LBFactoryTest.php b/tests/phpunit/includes/db/LBFactoryTest.php
index 4c59f474..81d6840b 100644
--- a/tests/phpunit/includes/db/LBFactoryTest.php
+++ b/tests/phpunit/includes/db/LBFactoryTest.php
@@ -2,7 +2,6 @@
/**
* Holds tests for LBFactory abstract MediaWiki class.
*
- * @section LICENSE
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
diff --git a/tests/phpunit/includes/db/ORMRowTest.php b/tests/phpunit/includes/db/ORMRowTest.php
index 447bf219..807bd14e 100644
--- a/tests/phpunit/includes/db/ORMRowTest.php
+++ b/tests/phpunit/includes/db/ORMRowTest.php
@@ -34,7 +34,6 @@
* that hold the first tests in a pending state awaiting access to the database.
* @group medium
*
- * @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
abstract class ORMRowTest extends \MediaWikiTestCase {
diff --git a/tests/phpunit/includes/db/ORMTableTest.php b/tests/phpunit/includes/db/ORMTableTest.php
index 7171ee59..338d931f 100644
--- a/tests/phpunit/includes/db/ORMTableTest.php
+++ b/tests/phpunit/includes/db/ORMTableTest.php
@@ -25,14 +25,12 @@
* @group ORM
* @group Database
*
- * @licence GNU GPL v2+
+ * @covers PageORMTableForTesting
+ *
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
* @author Daniel Kinzler
*/
-/**
- * @covers PageORMTableForTesting
- */
class ORMTableTest extends MediaWikiTestCase {
/**
@@ -99,6 +97,10 @@ class ORMTableTest extends MediaWikiTestCase {
class PageORMTableForTesting extends ORMTable {
+ public function __construct() {
+ $this->fieldPrefix = 'page_';
+ }
+
/**
* @see ORMTable::getName
*
@@ -138,13 +140,4 @@ class PageORMTableForTesting extends ORMTable {
'title' => 'str',
);
}
-
- /**
- * @see ORMTable::getFieldPrefix
- *
- * @return string
- */
- protected function getFieldPrefix() {
- return 'page_';
- }
}
diff --git a/tests/phpunit/includes/db/TestORMRowTest.php b/tests/phpunit/includes/db/TestORMRowTest.php
index c9459c90..04bb9f38 100644
--- a/tests/phpunit/includes/db/TestORMRowTest.php
+++ b/tests/phpunit/includes/db/TestORMRowTest.php
@@ -20,27 +20,23 @@
* http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @since 1.20
- *
* @ingroup Test
- *
- * @group ORM
- *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+
+/**
* The database group has as a side effect that temporal database tables are created. This makes
* it possible to test without poisoning a production database.
- * @group Database
*
* Some of the tests takes more time, and needs therefor longer time before they can be aborted
* as non-functional. The reason why tests are aborted is assumed to be set up of temporal databases
* that hold the first tests in a pending state awaiting access to the database.
- * @group medium
*
- * @licence GNU GPL v2+
- * @author Jeroen De Dauw < jeroendedauw@gmail.com >
- */
-require_once __DIR__ . "/ORMRowTest.php";
-
-/**
+ * @since 1.20
+ *
+ * @group ORM
+ * @group Database
+ * @group medium
* @covers TestORMRow
*/
class TestORMRowTest extends ORMRowTest {
@@ -150,6 +146,10 @@ class TestORMRow extends ORMRow {
class TestORMTable extends ORMTable {
+ public function __construct() {
+ $this->fieldPrefix = 'test_';
+ }
+
/**
* Returns the name of the database table objects of this type are stored in.
*
@@ -204,15 +204,4 @@ class TestORMTable extends ORMTable {
'time' => 'str', // TS_MW
);
}
-
- /**
- * Gets the db field prefix.
- *
- * @since 1.20
- *
- * @return string
- */
- protected function getFieldPrefix() {
- return 'test_';
- }
}
diff --git a/tests/phpunit/includes/debug/MWDebugTest.php b/tests/phpunit/includes/debug/MWDebugTest.php
index 6e41de75..1abb47e7 100644
--- a/tests/phpunit/includes/debug/MWDebugTest.php
+++ b/tests/phpunit/includes/debug/MWDebugTest.php
@@ -96,16 +96,15 @@ class MWDebugTest extends MediaWikiTestCase {
$apiMain = new ApiMain( $context );
$result = new ApiResult( $apiMain );
- $result->setRawMode( true );
MWDebug::appendDebugInfoToApiResult( $context, $result );
$this->assertInstanceOf( 'ApiResult', $result );
- $data = $result->getData();
+ $data = $result->getResultData();
$expectedKeys = array( 'mwVersion', 'phpEngine', 'phpVersion', 'gitRevision', 'gitBranch',
'gitViewUrl', 'time', 'log', 'debugLog', 'queries', 'request', 'memory',
- 'memoryPeak', 'includes', 'profile', '_element' );
+ 'memoryPeak', 'includes', '_element' );
foreach ( $expectedKeys as $expectedKey ) {
$this->assertArrayHasKey( $expectedKey, $data['debuginfo'], "debuginfo has $expectedKey" );
diff --git a/tests/phpunit/includes/debug/logging/LegacyLoggerTest.php b/tests/phpunit/includes/debug/logging/LegacyLoggerTest.php
new file mode 100644
index 00000000..415fa045
--- /dev/null
+++ b/tests/phpunit/includes/debug/logging/LegacyLoggerTest.php
@@ -0,0 +1,122 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+namespace MediaWiki\Logger;
+
+use MediaWikiTestCase;
+use Psr\Log\LogLevel;
+
+class LegacyLoggerTest extends MediaWikiTestCase {
+
+ /**
+ * @covers LegacyLogger::interpolate
+ * @dataProvider provideInterpolate
+ */
+ public function testInterpolate( $message, $context, $expect ) {
+ $this->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/LinksUpdateTest.php b/tests/phpunit/includes/deferred/LinksUpdateTest.php
index 02f6b2ab..02f6b2ab 100644
--- a/tests/phpunit/includes/LinksUpdateTest.php
+++ b/tests/phpunit/includes/deferred/LinksUpdateTest.php
diff --git a/tests/phpunit/includes/search/SearchUpdateTest.php b/tests/phpunit/includes/deferred/SearchUpdateTest.php
index c6275371..90438a04 100644
--- a/tests/phpunit/includes/search/SearchUpdateTest.php
+++ b/tests/phpunit/includes/deferred/SearchUpdateTest.php
@@ -17,7 +17,6 @@ class MockSearch extends SearchEngine {
/**
* @group Search
- * @group Database
*/
class SearchUpdateTest extends MediaWikiTestCase {
@@ -67,9 +66,10 @@ EOT
/**
* @covers SearchUpdate::updateText
- * @todo give this test a real name explaining what is being tested here
+ * Test bug 32712
+ * Test if unicode quotes in article links make its search index empty
*/
- public function testBug32712() {
+ public function testUnicodeLinkSearchIndexError() {
$text = "text „http://example.com“ text";
$result = $this->updateText( $text );
$processed = preg_replace( '/Q/u', 'Q', $result );
diff --git a/tests/phpunit/includes/diff/ArrayDiffFormatterTest.php b/tests/phpunit/includes/diff/ArrayDiffFormatterTest.php
index 188ad3fd..3bea9b31 100644
--- a/tests/phpunit/includes/diff/ArrayDiffFormatterTest.php
+++ b/tests/phpunit/includes/diff/ArrayDiffFormatterTest.php
@@ -1,7 +1,6 @@
<?php
/**
- * @licence GNU GPL v2+
* @author Adam Shorland
*
* @group Diff
diff --git a/tests/phpunit/includes/diff/DiffOpTest.php b/tests/phpunit/includes/diff/DiffOpTest.php
index d89b89fe..cbe05732 100644
--- a/tests/phpunit/includes/diff/DiffOpTest.php
+++ b/tests/phpunit/includes/diff/DiffOpTest.php
@@ -1,10 +1,5 @@
<?php
-
-//Load our FakeDiffOp
-require_once __DIR__ . DIRECTORY_SEPARATOR . 'FakeDiffOp.php';
-
/**
- * @licence GNU GPL v2+
* @author Adam Shorland
*
* @group Diff
diff --git a/tests/phpunit/includes/diff/DiffTest.php b/tests/phpunit/includes/diff/DiffTest.php
index 1911c82a..e0d79157 100644
--- a/tests/phpunit/includes/diff/DiffTest.php
+++ b/tests/phpunit/includes/diff/DiffTest.php
@@ -1,7 +1,6 @@
<?php
/**
- * @licence GNU GPL v2+
* @author Adam Shorland
*
* @group Diff
diff --git a/tests/phpunit/includes/diff/DifferenceEngineTest.php b/tests/phpunit/includes/diff/DifferenceEngineTest.php
index 5474b963..0f599af1 100644
--- a/tests/phpunit/includes/diff/DifferenceEngineTest.php
+++ b/tests/phpunit/includes/diff/DifferenceEngineTest.php
@@ -8,7 +8,6 @@
* @group Database
* @group Diff
*
- * @licence GNU GPL v2+
* @author Katie Filbert < aude.wiki@gmail.com >
*/
class DifferenceEngineTest extends MediaWikiTestCase {
diff --git a/tests/phpunit/includes/exception/BadTitleErrorTest.php b/tests/phpunit/includes/exception/BadTitleErrorTest.php
index 003efd27..500b7e48 100644
--- a/tests/phpunit/includes/exception/BadTitleErrorTest.php
+++ b/tests/phpunit/includes/exception/BadTitleErrorTest.php
@@ -5,23 +5,8 @@
*/
class BadTitleErrorTest extends MediaWikiTestCase {
- protected $wgOut;
-
- protected function setUp() {
- parent::setUp();
- global $wgOut;
- $this->wgOut = clone $wgOut;
- }
-
- protected function tearDown() {
- parent::tearDown();
- global $wgOut;
- $wgOut = $this->wgOut;
- }
-
public function testExceptionSetsStatusCode() {
- global $wgOut;
- $wgOut = $this->getMockWgOut();
+ $this->setMwGlobals( 'wgOut', $this->getMockWgOut() );
try {
throw new BadTitleError();
} catch ( BadTitleError $e ) {
diff --git a/tests/phpunit/includes/exception/ErrorPageErrorTest.php b/tests/phpunit/includes/exception/ErrorPageErrorTest.php
index 13dcf33b..9c4e4a0b 100644
--- a/tests/phpunit/includes/exception/ErrorPageErrorTest.php
+++ b/tests/phpunit/includes/exception/ErrorPageErrorTest.php
@@ -6,20 +6,6 @@
*/
class ErrorPageErrorTest extends MediaWikiTestCase {
- private $wgOut;
-
- protected function setUp() {
- parent::setUp();
- global $wgOut;
- $this->wgOut = clone $wgOut;
- }
-
- protected function tearDown() {
- global $wgOut;
- $wgOut = $this->wgOut;
- parent::tearDown();
- }
-
private function getMockMessage() {
$mockMessage = $this->getMockBuilder( 'Message' )
->disableOriginalConstructor()
@@ -48,20 +34,18 @@ class ErrorPageErrorTest extends MediaWikiTestCase {
$title = 'Foo';
$params = array( 'Baz' );
- global $wgOut;
- $wgOut = $this->getMockBuilder( 'OutputPage' )
+ $mock = $this->getMockBuilder( 'OutputPage' )
->disableOriginalConstructor()
->getMock();
- $wgOut->expects( $this->once() )
+ $mock->expects( $this->once() )
->method( 'showErrorPage' )
->with( $title, $mockMessage, $params );
- $wgOut->expects( $this->once() )
+ $mock->expects( $this->once() )
->method( 'output' );
+ $this->setMwGlobals( 'wgOut', $mock );
$e = new ErrorPageError( $title, $mockMessage, $params );
$e->report();
}
-
-
}
diff --git a/tests/phpunit/includes/exception/MWExceptionHandlerTest.php b/tests/phpunit/includes/exception/MWExceptionHandlerTest.php
index dc5dc6aa..d73f17d9 100644
--- a/tests/phpunit/includes/exception/MWExceptionHandlerTest.php
+++ b/tests/phpunit/includes/exception/MWExceptionHandlerTest.php
@@ -15,7 +15,7 @@ class MWExceptionHandlerTest extends MediaWikiTestCase {
$refvar = 'value';
try {
$array = array( 'a', 'b' );
- $object = new StdClass();
+ $object = new stdClass();
self::helperThrowAnException( $array, $object, $refvar );
} catch ( Exception $e ) {
}
diff --git a/tests/phpunit/includes/exception/ThrottledErrorTest.php b/tests/phpunit/includes/exception/ThrottledErrorTest.php
index bdb143fa..a1cf84bc 100644
--- a/tests/phpunit/includes/exception/ThrottledErrorTest.php
+++ b/tests/phpunit/includes/exception/ThrottledErrorTest.php
@@ -6,23 +6,8 @@
*/
class ThrottledErrorTest extends MediaWikiTestCase {
- protected $wgOut;
-
- protected function setUp() {
- parent::setUp();
- global $wgOut;
- $this->wgOut = clone $wgOut;
- }
-
- protected function tearDown() {
- parent::tearDown();
- global $wgOut;
- $wgOut = $this->wgOut;
- }
-
public function testExceptionSetsStatusCode() {
- global $wgOut;
- $wgOut = $this->getMockWgOut();
+ $this->setMwGlobals( 'wgOut', $this->getMockWgOut() );
try {
throw new ThrottledError();
} catch ( ThrottledError $e ) {
diff --git a/tests/phpunit/includes/ExternalStoreTest.php b/tests/phpunit/includes/externalstore/ExternalStoreTest.php
index 07c2957c..07c2957c 100644
--- a/tests/phpunit/includes/ExternalStoreTest.php
+++ b/tests/phpunit/includes/externalstore/ExternalStoreTest.php
diff --git a/tests/phpunit/includes/filebackend/FileBackendTest.php b/tests/phpunit/includes/filebackend/FileBackendTest.php
index 9558cc7d..bfca75ad 100644
--- a/tests/phpunit/includes/filebackend/FileBackendTest.php
+++ b/tests/phpunit/includes/filebackend/FileBackendTest.php
@@ -13,14 +13,13 @@ class FileBackendTest extends MediaWikiTestCase {
private $multiBackend;
/** @var FSFileBackend */
public $singleBackend;
- private $filesToPrune = array();
private static $backendToUse;
protected function setUp() {
global $wgFileBackends;
parent::setUp();
$uniqueId = time() . '-' . mt_rand();
- $tmpPrefix = wfTempDir() . '/filebackend-unittest-' . $uniqueId;
+ $tmpDir = $this->getNewTempDirectory();
if ( $this->getCliArg( 'use-filebackend' ) ) {
if ( self::$backendToUse ) {
$this->singleBackend = self::$backendToUse;
@@ -51,8 +50,8 @@ class FileBackendTest extends MediaWikiTestCase {
'lockManager' => LockManagerGroup::singleton()->get( 'fsLockManager' ),
'wikiId' => wfWikiID(),
'containerPaths' => array(
- 'unittest-cont1' => "{$tmpPrefix}-localtesting-cont1",
- 'unittest-cont2' => "{$tmpPrefix}-localtesting-cont2" )
+ 'unittest-cont1' => "{$tmpDir}/localtesting-cont1",
+ 'unittest-cont2' => "{$tmpDir}/localtesting-cont2" )
) );
}
$this->multiBackend = new FileBackendMultiWrite( array(
@@ -65,21 +64,20 @@ class FileBackendTest extends MediaWikiTestCase {
'name' => 'localmultitesting1',
'class' => 'FSFileBackend',
'containerPaths' => array(
- 'unittest-cont1' => "{$tmpPrefix}-localtestingmulti1-cont1",
- 'unittest-cont2' => "{$tmpPrefix}-localtestingmulti1-cont2" ),
+ 'unittest-cont1' => "{$tmpDir}/localtestingmulti1-cont1",
+ 'unittest-cont2' => "{$tmpDir}/localtestingmulti1-cont2" ),
'isMultiMaster' => false
),
array(
'name' => 'localmultitesting2',
'class' => 'FSFileBackend',
'containerPaths' => array(
- 'unittest-cont1' => "{$tmpPrefix}-localtestingmulti2-cont1",
- 'unittest-cont2' => "{$tmpPrefix}-localtestingmulti2-cont2" ),
+ 'unittest-cont1' => "{$tmpDir}/localtestingmulti2-cont1",
+ 'unittest-cont2' => "{$tmpDir}/localtestingmulti2-cont2" ),
'isMultiMaster' => true
)
)
) );
- $this->filesToPrune = array();
}
private static function baseStorePath() {
@@ -214,7 +212,7 @@ class FileBackendTest extends MediaWikiTestCase {
* @dataProvider provider_testStore
*/
public function testStore( $op ) {
- $this->filesToPrune[] = $op['src'];
+ $this->addTmpFiles( $op['src'] );
$this->backend = $this->singleBackend;
$this->tearDownFiles();
@@ -224,7 +222,6 @@ class FileBackendTest extends MediaWikiTestCase {
$this->backend = $this->multiBackend;
$this->tearDownFiles();
$this->doTestStore( $op );
- $this->filesToPrune[] = $op['src']; # avoid file leaking
$this->tearDownFiles();
}
@@ -275,27 +272,15 @@ class FileBackendTest extends MediaWikiTestCase {
$tmpName = TempFSFile::factory( "unittests_", 'txt' )->getPath();
$toPath = self::baseStorePath() . '/unittest-cont1/e/fun/obj1.txt';
$op = array( 'op' => 'store', 'src' => $tmpName, 'dst' => $toPath );
- $cases[] = array(
- $op, // operation
- $tmpName, // source
- $toPath, // dest
- );
+ $cases[] = array( $op );
$op2 = $op;
$op2['overwrite'] = true;
- $cases[] = array(
- $op2, // operation
- $tmpName, // source
- $toPath, // dest
- );
+ $cases[] = array( $op2 );
- $op2 = $op;
- $op2['overwriteSame'] = true;
- $cases[] = array(
- $op2, // operation
- $tmpName, // source
- $toPath, // dest
- );
+ $op3 = $op;
+ $op3['overwriteSame'] = true;
+ $cases[] = array( $op3 );
return $cases;
}
@@ -948,18 +933,14 @@ class FileBackendTest extends MediaWikiTestCase {
* @dataProvider provider_testConcatenate
*/
public function testConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus ) {
- $this->filesToPrune[] = $op['dst'];
-
$this->backend = $this->singleBackend;
$this->tearDownFiles();
$this->doTestConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus );
- $this->filesToPrune[] = $op['dst']; # avoid file leaking
$this->tearDownFiles();
$this->backend = $this->multiBackend;
$this->tearDownFiles();
$this->doTestConcatenate( $op, $srcs, $srcsContent, $alreadyExists, $okStatus );
- $this->filesToPrune[] = $op['dst']; # avoid file leaking
$this->tearDownFiles();
}
@@ -983,7 +964,7 @@ class FileBackendTest extends MediaWikiTestCase {
$this->assertGoodStatus( $status,
"Creation of source files succeeded ($backendName)." );
- $dest = $params['dst'];
+ $dest = $params['dst'] = $this->getNewTempFile();
if ( $alreadyExists ) {
$ok = file_put_contents( $dest, 'blah...blah...waahwaah' ) !== false;
$this->assertEquals( true, $ok,
@@ -1029,8 +1010,6 @@ class FileBackendTest extends MediaWikiTestCase {
public static function provider_testConcatenate() {
$cases = array();
- $rand = mt_rand( 0, 2000000000 ) . time();
- $dest = wfTempDir() . "/randomfile!$rand.txt";
$srcs = array(
self::baseStorePath() . '/unittest-cont1/e/file1.txt',
self::baseStorePath() . '/unittest-cont1/e/file2.txt',
@@ -1055,7 +1034,7 @@ class FileBackendTest extends MediaWikiTestCase {
'lkaem;a',
'legma'
);
- $params = array( 'srcs' => $srcs, 'dst' => $dest );
+ $params = array( 'srcs' => $srcs );
$cases[] = array(
$params, // operation
@@ -1499,7 +1478,7 @@ class FileBackendTest extends MediaWikiTestCase {
$url = $this->backend->getFileHttpUrl( array( 'src' => $source ) );
if ( $url !== null ) { // supported
- $data = Http::request( "GET", $url );
+ $data = Http::request( "GET", $url, array(), __METHOD__ );
$this->assertEquals( $content, $data,
"HTTP GET of URL has right contents ($backendName)." );
}
@@ -1761,16 +1740,13 @@ class FileBackendTest extends MediaWikiTestCase {
$fileCContents = 'eigna[ogmewt 3qt g3qg flew[ag';
$tmpNameA = TempFSFile::factory( "unittests_", 'txt' )->getPath();
- file_put_contents( $tmpNameA, $fileAContents );
$tmpNameB = TempFSFile::factory( "unittests_", 'txt' )->getPath();
- file_put_contents( $tmpNameB, $fileBContents );
$tmpNameC = TempFSFile::factory( "unittests_", 'txt' )->getPath();
+ $this->addTmpFiles( array( $tmpNameA, $tmpNameB, $tmpNameC ) );
+ file_put_contents( $tmpNameA, $fileAContents );
+ file_put_contents( $tmpNameB, $fileBContents );
file_put_contents( $tmpNameC, $fileCContents );
- $this->filesToPrune[] = $tmpNameA; # avoid file leaking
- $this->filesToPrune[] = $tmpNameB; # avoid file leaking
- $this->filesToPrune[] = $tmpNameC; # avoid file leaking
-
$fileA = "$base/unittest-cont1/e/a/b/fileA.txt";
$fileB = "$base/unittest-cont1/e/a/b/fileB.txt";
$fileC = "$base/unittest-cont1/e/a/b/fileC.txt";
@@ -2434,16 +2410,10 @@ class FileBackendTest extends MediaWikiTestCase {
}
function tearDownFiles() {
- foreach ( $this->filesToPrune as $file ) {
- if ( is_file( $file ) ) {
- unlink( $file );
- }
- }
$containers = array( 'unittest-cont1', 'unittest-cont2', 'unittest-cont-bad' );
foreach ( $containers as $container ) {
$this->deleteFiles( $container );
}
- $this->filesToPrune = array();
}
private function deleteFiles( $container ) {
diff --git a/tests/phpunit/includes/filerepo/StoreBatchTest.php b/tests/phpunit/includes/filerepo/StoreBatchTest.php
index 9cc2efbf..86bfe123 100644
--- a/tests/phpunit/includes/filerepo/StoreBatchTest.php
+++ b/tests/phpunit/includes/filerepo/StoreBatchTest.php
@@ -16,7 +16,7 @@ class StoreBatchTest extends MediaWikiTestCase {
parent::setUp();
# Forge a FSRepo object to not have to rely on local wiki settings
- $tmpPrefix = wfTempDir() . '/storebatch-test-' . time() . '-' . mt_rand();
+ $tmpPrefix = $this->getNewTempDirectory();
if ( $this->getCliArg( 'use-filebackend' ) ) {
$name = $this->getCliArg( 'use-filebackend' );
$useConfig = array();
@@ -35,10 +35,10 @@ class StoreBatchTest extends MediaWikiTestCase {
'name' => 'local-testing',
'wikiId' => wfWikiID(),
'containerPaths' => array(
- 'unittests-public' => "{$tmpPrefix}-public",
- 'unittests-thumb' => "{$tmpPrefix}-thumb",
- 'unittests-temp' => "{$tmpPrefix}-temp",
- 'unittests-deleted' => "{$tmpPrefix}-deleted",
+ 'unittests-public' => "{$tmpPrefix}/public",
+ 'unittests-thumb' => "{$tmpPrefix}/thumb",
+ 'unittests-temp' => "{$tmpPrefix}/temp",
+ 'unittests-deleted' => "{$tmpPrefix}/deleted",
)
) );
}
@@ -52,13 +52,8 @@ class StoreBatchTest extends MediaWikiTestCase {
}
protected function tearDown() {
- $this->repo->cleanupBatch( $this->createdFiles ); // delete files
- foreach ( $this->createdFiles as $tmp ) { // delete dirs
- $tmp = $this->repo->resolveVirtualUrl( $tmp );
- while ( $tmp = FileBackend::parentStoragePath( $tmp ) ) {
- $this->repo->getBackend()->clean( array( 'dir' => $tmp ) );
- }
- }
+ // Delete files
+ $this->repo->cleanupBatch( $this->createdFiles );
parent::tearDown();
}
diff --git a/tests/phpunit/includes/LocalFileTest.php b/tests/phpunit/includes/filerepo/file/LocalFileTest.php
index 5c5052e4..3c5754bf 100644
--- a/tests/phpunit/includes/LocalFileTest.php
+++ b/tests/phpunit/includes/filerepo/file/LocalFileTest.php
@@ -2,7 +2,6 @@
/**
* These tests should work regardless of $wgCapitalLinks
- * @group Database
* @todo Split tests into providers and test methods
*/
diff --git a/tests/phpunit/includes/installer/DatabaseUpdaterTest.php b/tests/phpunit/includes/installer/DatabaseUpdaterTest.php
new file mode 100644
index 00000000..abff3e68
--- /dev/null
+++ b/tests/phpunit/includes/installer/DatabaseUpdaterTest.php
@@ -0,0 +1,279 @@
+<?php
+
+class DatabaseUpdaterTest extends MediaWikiTestCase {
+
+ public function testSetAppliedUpdates() {
+ $db = new FakeDatabase();
+ $dbu = new FakeDatabaseUpdater( $db );
+ $dbu->setAppliedUpdates( "test", array() );
+ $expected = "updatelist-test-" . time() . "0";
+ $actual = $db->lastInsertData['ul_key'];
+ $this->assertEquals( $expected, $actual, var_export( $db->lastInsertData, true ) );
+ $dbu->setAppliedUpdates( "test", array() );
+ $expected = "updatelist-test-" . time() . "1";
+ $actual = $db->lastInsertData['ul_key'];
+ $this->assertEquals( $expected, $actual, var_export( $db->lastInsertData, true ) );
+ }
+}
+
+class FakeDatabase extends DatabaseBase {
+ public $lastInsertTable;
+ public $lastInsertData;
+
+ function __construct() {
+ }
+
+ function clearFlag( $arg ) {
+ }
+
+ function setFlag( $arg ) {
+ }
+
+ public function insert( $table, $a, $fname = __METHOD__, $options = array() ) {
+ $this->lastInsertTable = $table;
+ $this->lastInsertData = $a;
+ }
+
+ /**
+ * Get the type of the DBMS, as it appears in $wgDBtype.
+ *
+ * @return string
+ */
+ function getType() {
+ // TODO: Implement getType() method.
+ }
+
+ /**
+ * Open a connection to the database. Usually aborts on failure
+ *
+ * @param string $server Database server host
+ * @param string $user Database user name
+ * @param string $password Database user password
+ * @param string $dbName Database name
+ * @return bool
+ * @throws DBConnectionError
+ */
+ function open( $server, $user, $password, $dbName ) {
+ // TODO: Implement open() method.
+ }
+
+ /**
+ * Fetch the next row from the given result object, in object form.
+ * Fields can be retrieved with $row->fieldname, with fields acting like
+ * member variables.
+ * If no more rows are available, false is returned.
+ *
+ * @param ResultWrapper|stdClass $res Object as returned from DatabaseBase::query(), etc.
+ * @return stdClass|bool
+ * @throws DBUnexpectedError Thrown if the database returns an error
+ */
+ function fetchObject( $res ) {
+ // TODO: Implement fetchObject() method.
+ }
+
+ /**
+ * Fetch the next row from the given result object, in associative array
+ * form. Fields are retrieved with $row['fieldname'].
+ * If no more rows are available, false is returned.
+ *
+ * @param ResultWrapper $res Result object as returned from DatabaseBase::query(), etc.
+ * @return array|bool
+ * @throws DBUnexpectedError Thrown if the database returns an error
+ */
+ function fetchRow( $res ) {
+ // TODO: Implement fetchRow() method.
+ }
+
+ /**
+ * Get the number of rows in a result object
+ *
+ * @param mixed $res A SQL result
+ * @return int
+ */
+ function numRows( $res ) {
+ // TODO: Implement numRows() method.
+ }
+
+ /**
+ * Get the number of fields in a result object
+ * @see http://www.php.net/mysql_num_fields
+ *
+ * @param mixed $res A SQL result
+ * @return int
+ */
+ function numFields( $res ) {
+ // TODO: Implement numFields() method.
+ }
+
+ /**
+ * Get a field name in a result object
+ * @see http://www.php.net/mysql_field_name
+ *
+ * @param mixed $res A SQL result
+ * @param int $n
+ * @return string
+ */
+ function fieldName( $res, $n ) {
+ // TODO: Implement fieldName() method.
+ }
+
+ /**
+ * Get the inserted value of an auto-increment row
+ *
+ * The value inserted should be fetched from nextSequenceValue()
+ *
+ * Example:
+ * $id = $dbw->nextSequenceValue( 'page_page_id_seq' );
+ * $dbw->insert( 'page', array( 'page_id' => $id ) );
+ * $id = $dbw->insertId();
+ *
+ * @return int
+ */
+ function insertId() {
+ // TODO: Implement insertId() method.
+ }
+
+ /**
+ * Change the position of the cursor in a result object
+ * @see http://www.php.net/mysql_data_seek
+ *
+ * @param mixed $res A SQL result
+ * @param int $row
+ */
+ function dataSeek( $res, $row ) {
+ // TODO: Implement dataSeek() method.
+ }
+
+ /**
+ * Get the last error number
+ * @see http://www.php.net/mysql_errno
+ *
+ * @return int
+ */
+ function lastErrno() {
+ // TODO: Implement lastErrno() method.
+ }
+
+ /**
+ * Get a description of the last error
+ * @see http://www.php.net/mysql_error
+ *
+ * @return string
+ */
+ function lastError() {
+ // TODO: Implement lastError() method.
+ }
+
+ /**
+ * mysql_fetch_field() wrapper
+ * Returns false if the field doesn't exist
+ *
+ * @param string $table Table name
+ * @param string $field Field name
+ *
+ * @return Field
+ */
+ function fieldInfo( $table, $field ) {
+ // TODO: Implement fieldInfo() method.
+ }
+
+ /**
+ * Get information about an index into an object
+ * @param string $table Table name
+ * @param string $index Index name
+ * @param string $fname Calling function name
+ * @return mixed Database-specific index description class or false if the index does not exist
+ */
+ function indexInfo( $table, $index, $fname = __METHOD__ ) {
+ // TODO: Implement indexInfo() method.
+ }
+
+ /**
+ * Get the number of rows affected by the last write query
+ * @see http://www.php.net/mysql_affected_rows
+ *
+ * @return int
+ */
+ function affectedRows() {
+ // TODO: Implement affectedRows() method.
+ }
+
+ /**
+ * Wrapper for addslashes()
+ *
+ * @param string $s String to be slashed.
+ * @return string Slashed string.
+ */
+ function strencode( $s ) {
+ // TODO: Implement strencode() method.
+ }
+
+ /**
+ * Returns a wikitext link to the DB's website, e.g.,
+ * return "[http://www.mysql.com/ MySQL]";
+ * Should at least contain plain text, if for some reason
+ * your database has no website.
+ *
+ * @return string Wikitext of a link to the server software's web site
+ */
+ function getSoftwareLink() {
+ // TODO: Implement getSoftwareLink() method.
+ }
+
+ /**
+ * A string describing the current software version, like from
+ * mysql_get_server_info().
+ *
+ * @return string Version information from the database server.
+ */
+ function getServerVersion() {
+ // TODO: Implement getServerVersion() method.
+ }
+
+ /**
+ * Closes underlying database connection
+ * @since 1.20
+ * @return bool Whether connection was closed successfully
+ */
+ protected function closeConnection() {
+ // TODO: Implement closeConnection() method.
+ }
+
+ /**
+ * The DBMS-dependent part of query()
+ *
+ * @param string $sql SQL query.
+ * @return ResultWrapper|bool Result object to feed to fetchObject,
+ * fetchRow, ...; or false on failure
+ */
+ protected function doQuery( $sql ) {
+ // TODO: Implement doQuery() method.
+ }
+}
+
+class FakeDatabaseUpdater extends DatabaseUpdater {
+ function __construct( $db ) {
+ $this->db = $db;
+ self::$updateCounter = 0;
+ }
+
+ /**
+ * Get an array of updates to perform on the database. Should return a
+ * multi-dimensional array. The main key is the MediaWiki version (1.12,
+ * 1.13...) with the values being arrays of updates, identical to how
+ * updaters.inc did it (for now)
+ *
+ * @return array
+ */
+ protected function getCoreUpdateList() {
+ return array();
+ }
+
+ public function canUseNewUpdatelog() {
+ return true;
+ }
+
+ public function setAppliedUpdates( $version, $updates = array() ) {
+ parent::setAppliedUpdates( $version, $updates );
+ }
+}
diff --git a/tests/phpunit/includes/installer/InstallDocFormatterTest.php b/tests/phpunit/includes/installer/InstallDocFormatterTest.php
index 064d5185..724f0c88 100644
--- a/tests/phpunit/includes/installer/InstallDocFormatterTest.php
+++ b/tests/phpunit/includes/installer/InstallDocFormatterTest.php
@@ -34,6 +34,21 @@ class InstallDocFormatterTest extends MediaWikiTestCase {
array( ':One indentation', "\tOne indentation", 'Replacing a single \t' ),
array( '::Two indentations', "\t\tTwo indentations", 'Replacing 2 x \t' ),
+ # Transform 'T123' links
+ array(
+ '<span class="config-plainlink">[https://phabricator.wikimedia.org/T123 T123]</span>',
+ 'T123', 'Testing T123 links' ),
+ array(
+ 'bug <span class="config-plainlink">[https://phabricator.wikimedia.org/T123 T123]</span>',
+ 'bug T123', 'Testing bug T123 links' ),
+ array(
+ '(<span class="config-plainlink">[https://phabricator.wikimedia.org/T987654 T987654]</span>)',
+ '(T987654)', 'Testing (T987654) links' ),
+
+ # "Tabc" shouldn't work
+ array( 'Tfoobar', 'Tfoobar', "Don't match T followed by non-digits" ),
+ array( 'T!!fakefake!!', 'T!!fakefake!!', "Don't match T followed by non-digits" ),
+
# Transform 'bug 123' links
array(
'<span class="config-plainlink">[https://bugzilla.wikimedia.org/123 bug 123]</span>',
diff --git a/tests/phpunit/includes/jobqueue/JobQueueTest.php b/tests/phpunit/includes/jobqueue/JobQueueTest.php
index 69e40068..ea1a4f63 100644
--- a/tests/phpunit/includes/jobqueue/JobQueueTest.php
+++ b/tests/phpunit/includes/jobqueue/JobQueueTest.php
@@ -247,8 +247,13 @@ class JobQueueTest extends MediaWikiTestCase {
$this->assertNull( $queue->push( $this->newJob( 0, $root1 ) ), "Push worked ($desc)" );
}
$queue->deduplicateRootJob( $this->newJob( 0, $root1 ) );
- sleep( 1 ); // roo job timestamp will increase
- $root2 = Job::newRootJobParams( "nulljobspam:$id" ); // task ID/timestamp
+
+ $root2 = $root1;
+ # Add a second to UNIX epoch and format back to TS_MW
+ $root2_ts = strtotime( $root2['rootJobTimestamp'] );
+ $root2_ts++;
+ $root2['rootJobTimestamp'] = wfTimestamp( TS_MW, $root2_ts );
+
$this->assertNotEquals( $root1['rootJobTimestamp'], $root2['rootJobTimestamp'],
"Root job signatures have different timestamps." );
for ( $i = 0; $i < 5; ++$i ) {
diff --git a/tests/phpunit/includes/jobqueue/JobTest.php b/tests/phpunit/includes/jobqueue/JobTest.php
new file mode 100644
index 00000000..93069d2e
--- /dev/null
+++ b/tests/phpunit/includes/jobqueue/JobTest.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @author Adam Shorland
+ */
+class JobTest extends MediaWikiTestCase {
+
+ /**
+ * @dataProvider provideTestToString
+ *
+ * @param Job $job
+ * @param string $expected
+ *
+ * @covers Job::toString
+ */
+ public function testToString( $job, $expected ) {
+ $this->assertEquals( $expected, $job->toString() );
+ }
+
+ public function provideTestToString() {
+ $mockToStringObj = $this->getMock( 'stdClass', array( '__toString' ) );
+ $mockToStringObj->expects( $this->any() )
+ ->method( '__toString' )
+ ->will( $this->returnValue( '{STRING_OBJ_VAL}' ) );
+
+ return array(
+ array(
+ $this->getMockJob( false ),
+ 'someCommand '
+ ),
+ array(
+ $this->getMockJob( array( 'key' => 'val' ) ),
+ 'someCommand key=val'
+ ),
+ array(
+ $this->getMockJob( array( 'key' => array( 'inkey' => 'inval' ) ) ),
+ 'someCommand key={"inkey":"inval"}'
+ ),
+ array(
+ $this->getMockJob( array( 'val1' ) ),
+ 'someCommand 0=val1'
+ ),
+ array(
+ $this->getMockJob( array( 'val1', 'val2' ) ),
+ 'someCommand 0=val1 1=val2'
+ ),
+ array(
+ $this->getMockJob( array( new stdClass() ) ),
+ 'someCommand 0=object(stdClass)'
+ ),
+ array(
+ $this->getMockJob( array( $mockToStringObj ) ),
+ 'someCommand 0={STRING_OBJ_VAL}'
+ ),
+ );
+ }
+
+ public function getMockJob( $params ) {
+ $mock = $this->getMockForAbstractClass(
+ 'Job',
+ array( 'someCommand', new Title(), $params ),
+ 'SomeJob'
+ );
+ return $mock;
+ }
+
+}
diff --git a/tests/phpunit/includes/json/FormatJsonTest.php b/tests/phpunit/includes/json/FormatJsonTest.php
index af68ab03..f0ac6acc 100644
--- a/tests/phpunit/includes/json/FormatJsonTest.php
+++ b/tests/phpunit/includes/json/FormatJsonTest.php
@@ -169,12 +169,30 @@ class FormatJsonTest extends MediaWikiTestCase {
$this->assertEquals( $value, $st->getValue() );
}
+ /**
+ * Test data for testParseTryFixing.
+ *
+ * Some PHP interpreters use json-c rather than the JSON.org cannonical
+ * parser to avoid being encumbered by the "shall be used for Good, not
+ * Evil" clause of the JSON.org parser's license. By default, json-c
+ * parses in a non-strict mode which allows trailing commas for array and
+ * object delarations among other things, so our JSON_ERROR_SYNTAX rescue
+ * block is not always triggered. It however isn't lenient in exactly the
+ * same ways as our TRY_FIXING mode, so the assertions in this test are
+ * a bit more complicated than they ideally would be:
+ *
+ * Optional third argument: true if json-c parses the value without
+ * intervention, false otherwise. Defaults to true.
+ *
+ * Optional fourth argument: expected cannonical JSON serialization of
+ * json-c parsed result. Defaults to the second argument's value.
+ */
public static function provideParseTryFixing() {
return array(
- array( "[,]", '[]' ),
- array( "[ , ]", '[]' ),
+ array( "[,]", '[]', false ),
+ array( "[ , ]", '[]', false ),
array( "[ , }", false ),
- array( '[1],', false ),
+ array( '[1],', false, true, '[1]' ),
array( "[1,]", '[1]' ),
array( "[1\n,]", '[1]' ),
array( "[1,\n]", '[1]' ),
@@ -182,24 +200,44 @@ class FormatJsonTest extends MediaWikiTestCase {
array( "[1\n,\n]\n", '[1]' ),
array( '["a,",]', '["a,"]' ),
array( "[[1,]\n,[2,\n],[3\n,]]", '[[1],[2],[3]]' ),
- array( '[[1,],[2,],[3,]]', false ), // I wish we could parse this, but would need quote parsing
- array( '[1,,]', false ),
+ // I wish we could parse this, but would need quote parsing
+ array( '[[1,],[2,],[3,]]', false, true, '[[1],[2],[3]]' ),
+ array( '[1,,]', false, false, '[1]' ),
);
}
/**
* @dataProvider provideParseTryFixing
* @param string $value
- * @param string|bool $expected
+ * @param string|bool $expected Expected result with strict parser
+ * @param bool $jsoncParses Will json-c parse this value without TRY_FIXING?
+ * @param string|bool $expectedJsonc Expected result with lenient parser
+ * if different from the strict expectation
*/
- public function testParseTryFixing( $value, $expected ) {
+ public function testParseTryFixing(
+ $value, $expected,
+ $jsoncParses = true, $expectedJsonc = null
+ ) {
+ // PHP5 results are always expected to have isGood() === false
+ $expectedGoodStatus = false;
+
+ // Check to see if json parser allows trailing commas
+ if ( json_decode( '[1,]' ) !== null ) {
+ // Use json-c specific expected result if provided
+ $expected = ( $expectedJsonc === null ) ? $expected : $expectedJsonc;
+ // If json-c parses the value natively, expect isGood() === true
+ $expectedGoodStatus = $jsoncParses;
+ }
+
$st = FormatJson::parse( $value, FormatJson::TRY_FIXING );
$this->assertType( 'Status', $st );
if ( $expected === false ) {
- $this->assertFalse( $st->isOK() );
+ $this->assertFalse( $st->isOK(), 'Expected isOK() == false' );
} else {
- $this->assertFalse( $st->isGood() );
- $this->assertTrue( $st->isOK() );
+ $this->assertSame( $expectedGoodStatus, $st->isGood(),
+ 'Expected isGood() == ' . ( $expectedGoodStatus ? 'true' : 'false' )
+ );
+ $this->assertTrue( $st->isOK(), 'Expected isOK == true' );
$val = FormatJson::encode( $st->getValue(), false, FormatJson::ALL_OK );
$this->assertEquals( $expected, $val );
}
@@ -222,6 +260,64 @@ class FormatJsonTest extends MediaWikiTestCase {
$this->assertFalse( $st->isOK() );
}
+ public function provideStripComments() {
+ return array(
+ array( '{"a":"b"}', '{"a":"b"}' ),
+ array( "{\"a\":\"b\"}\n", "{\"a\":\"b\"}\n" ),
+ array( '/*c*/{"c":"b"}', '{"c":"b"}' ),
+ array( '{"a":"c"}/*c*/', '{"a":"c"}' ),
+ array( '/*c//d*/{"c":"b"}', '{"c":"b"}' ),
+ array( '{/*c*/"c":"b"}', '{"c":"b"}' ),
+ array( "/*\nc\r\n*/{\"c\":\"b\"}", '{"c":"b"}' ),
+ array( "//c\n{\"c\":\"b\"}", '{"c":"b"}' ),
+ array( "//c\r\n{\"c\":\"b\"}", '{"c":"b"}' ),
+ array( '{"a":"c"}//c', '{"a":"c"}' ),
+ array( "{\"a-c\"://c\n\"b\"}", '{"a-c":"b"}' ),
+ array( '{"/*a":"b"}', '{"/*a":"b"}' ),
+ array( '{"a":"//b"}', '{"a":"//b"}' ),
+ array( '{"a":"b/*c*/"}', '{"a":"b/*c*/"}' ),
+ array( "{\"\\\"/*a\":\"b\"}", "{\"\\\"/*a\":\"b\"}" ),
+ array( '', '' ),
+ array( '/*c', '' ),
+ array( '//c', '' ),
+ array( '"http://example.com"', '"http://example.com"' ),
+ array( "\0", "\0" ),
+ array( '"Blåbærsyltetøy"', '"Blåbærsyltetøy"' ),
+ );
+ }
+
+ /**
+ * @covers FormatJson::stripComments
+ * @dataProvider provideStripComments
+ * @param string $json
+ * @param string $expect
+ */
+ public function testStripComments( $json, $expect ) {
+ $this->assertSame( $expect, FormatJson::stripComments( $json ) );
+ }
+
+ public function provideParseStripComments() {
+ return array(
+ array( '/* blah */true', true ),
+ array( "// blah \ntrue", true ),
+ array( '[ "a" , /* blah */ "b" ]', array( 'a', 'b' ) ),
+ );
+ }
+
+ /**
+ * @covers FormatJson::parse
+ * @covers FormatJson::stripComments
+ * @dataProvider provideParseStripComments
+ * @param string $json
+ * @param mixed $expect
+ */
+ public function testParseStripComments( $json, $expect ) {
+ $st = FormatJson::parse( $json, FormatJson::STRIP_COMMENTS );
+ $this->assertType( 'Status', $st );
+ $this->assertTrue( $st->isGood() );
+ $this->assertEquals( $expect, $st->getValue() );
+ }
+
/**
* Generate a set of test cases for a particular combination of encoder options.
*
diff --git a/tests/phpunit/includes/ArrayUtilsTest.php b/tests/phpunit/includes/libs/ArrayUtilsTest.php
index 7bdb1ca4..b5ea7b72 100644
--- a/tests/phpunit/includes/ArrayUtilsTest.php
+++ b/tests/phpunit/includes/libs/ArrayUtilsTest.php
@@ -5,7 +5,7 @@
* @group Database
*/
-class ArrayUtilsTest extends MediaWikiTestCase {
+class ArrayUtilsTest extends PHPUnit_Framework_TestCase {
private $search;
/**
diff --git a/tests/phpunit/includes/libs/CSSMinTest.php b/tests/phpunit/includes/libs/CSSMinTest.php
index 43c50869..6142f967 100644
--- a/tests/phpunit/includes/libs/CSSMinTest.php
+++ b/tests/phpunit/includes/libs/CSSMinTest.php
@@ -141,15 +141,57 @@ class CSSMinTest extends MediaWikiTestCase {
);
}
+ public static function provideIsRemoteUrl() {
+ return array(
+ array( true, 'http://localhost/w/red.gif?123' ),
+ array( true, 'https://example.org/x.png' ),
+ array( true, '//example.org/x.y.z/image.png' ),
+ array( true, '//localhost/styles.css?query=yes' ),
+ array( true, 'data:image/gif;base64,R0lGODlhAQABAIAAAP8AADAAACwAAAAAAQABAAACAkQBADs=' ),
+ array( false, 'x.gif' ),
+ array( false, '/x.gif' ),
+ array( false, './x.gif' ),
+ array( false, '../x.gif' ),
+ );
+ }
+
+ /**
+ * @dataProvider provideIsRemoteUrl
+ * @cover CSSMin::isRemoteUrl
+ */
+ public function testIsRemoteUrl( $expect, $url ) {
+ $this->assertEquals( CSSMin::isRemoteUrl( $url ), $expect );
+ }
+
+ public static function provideIsLocalUrls() {
+ return array(
+ array( false, 'x.gif' ),
+ array( true, '/x.gif' ),
+ array( false, './x.gif' ),
+ array( false, '../x.gif' ),
+ );
+ }
+
+ /**
+ * @dataProvider provideIsLocalUrls
+ * @cover CSSMin::isLocalUrl
+ */
+ public function testIsLocalUrl( $expect, $url ) {
+ $this->assertEquals( CSSMin::isLocalUrl( $url ), $expect );
+ }
+
public static function provideRemapRemappingCases() {
// red.gif and green.gif are one-pixel 35-byte GIFs.
// large.png is a 35K PNG that should be non-embeddable.
// Full paths start with http://localhost/w/.
// Timestamps in output are replaced with 'timestamp'.
- // data: URIs for red.gif and green.gif
+ // data: URIs for red.gif, green.gif, circle.svg
$red = 'data:image/gif;base64,R0lGODlhAQABAIAAAP8AADAAACwAAAAAAQABAAACAkQBADs=';
$green = 'data:image/gif;base64,R0lGODlhAQABAIAAAACAADAAACwAAAAAAQABAAACAkQBADs=';
+ $svg = 'data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A'
+ . '%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%228%22%20height%3D'
+ . '%228%22%3E%0A%3Ccircle%20cx%3D%224%22%20cy%3D%224%22%20r%3D%222%22%2F%3E%0A%3C%2Fsvg%3E%0A';
return array(
array(
@@ -234,6 +276,11 @@ class CSSMinTest extends MediaWikiTestCase {
"foo { background: url(http://localhost/w/large.png?timestamp); }",
),
array(
+ 'SVG files are embedded without base64 encoding and unnecessary IE 6 and 7 fallback',
+ 'foo { /* @embed */ background: url(circle.svg); }',
+ "foo { background: url($svg); }",
+ ),
+ array(
'Two regular files in one rule',
'foo { background: url(red.gif), url(green.gif); }',
'foo { background: url(http://localhost/w/red.gif?timestamp), '
diff --git a/tests/phpunit/includes/libs/DeferredStringifierTest.php b/tests/phpunit/includes/libs/DeferredStringifierTest.php
new file mode 100644
index 00000000..8b7610ae
--- /dev/null
+++ b/tests/phpunit/includes/libs/DeferredStringifierTest.php
@@ -0,0 +1,50 @@
+<?php
+
+class DeferredStringifierTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * @covers DeferredStringifier
+ * @dataProvider provideToString
+ */
+ public function testToString( $params, $expected ) {
+ $class = new ReflectionClass( 'DeferredStringifier' );
+ $ds = $class->newInstanceArgs( $params );
+ $this->assertEquals( $expected, (string)$ds );
+ }
+
+ public static function provideToString() {
+ return array(
+ // No args
+ array(
+ array(
+ function() {
+ return 'foo';
+ }
+ ),
+ 'foo'
+ ),
+ // Has args
+ array(
+ array(
+ function( $i ) {
+ return $i;
+ },
+ 'bar'
+ ),
+ 'bar'
+ ),
+ );
+ }
+
+ /**
+ * Verify that the callback is not called if
+ * it is never converted to a string
+ */
+ public function testCallbackNotCalled() {
+ $ds = new DeferredStringifier( function() {
+ throw new Exception( 'This should not be reached!' );
+ } );
+ // No exception was thrown
+ $this->assertTrue( true );
+ }
+}
diff --git a/tests/phpunit/includes/libs/GenericArrayObjectTest.php b/tests/phpunit/includes/libs/GenericArrayObjectTest.php
index 4911f73a..315bc7ed 100644
--- a/tests/phpunit/includes/libs/GenericArrayObjectTest.php
+++ b/tests/phpunit/includes/libs/GenericArrayObjectTest.php
@@ -24,10 +24,9 @@
* @ingroup Test
* @group GenericArrayObject
*
- * @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
-abstract class GenericArrayObjectTest extends MediaWikiTestCase {
+abstract class GenericArrayObjectTest extends PHPUnit_Framework_TestCase {
/**
* Returns objects that can serve as elements in the concrete
diff --git a/tests/phpunit/includes/libs/HashRingTest.php b/tests/phpunit/includes/libs/HashRingTest.php
index 68dfea1f..b51eb3f4 100644
--- a/tests/phpunit/includes/libs/HashRingTest.php
+++ b/tests/phpunit/includes/libs/HashRingTest.php
@@ -3,7 +3,7 @@
/**
* @group HashRing
*/
-class HashRingTest extends MediaWikiTestCase {
+class HashRingTest extends PHPUnit_Framework_TestCase {
/**
* @covers HashRing
*/
diff --git a/tests/phpunit/includes/libs/IEUrlExtensionTest.php b/tests/phpunit/includes/libs/IEUrlExtensionTest.php
index b7071230..e96953ee 100644
--- a/tests/phpunit/includes/libs/IEUrlExtensionTest.php
+++ b/tests/phpunit/includes/libs/IEUrlExtensionTest.php
@@ -5,7 +5,7 @@
* @todo tests below for findIE6Extension should be split into...
* ...a dataprovider and test method.
*/
-class IEUrlExtensionTest extends MediaWikiTestCase {
+class IEUrlExtensionTest extends PHPUnit_Framework_TestCase {
/**
* @covers IEUrlExtension::findIE6Extension
*/
diff --git a/tests/phpunit/includes/libs/IPSetTest.php b/tests/phpunit/includes/libs/IPSetTest.php
index d4e5214a..5bbacef4 100644
--- a/tests/phpunit/includes/libs/IPSetTest.php
+++ b/tests/phpunit/includes/libs/IPSetTest.php
@@ -3,7 +3,7 @@
/**
* @group IPSet
*/
-class IPSetTest extends MediaWikiTestCase {
+class IPSetTest extends PHPUnit_Framework_TestCase {
/**
* Provides test cases for IPSetTest::testIPSet
*
diff --git a/tests/phpunit/includes/libs/JavaScriptMinifierTest.php b/tests/phpunit/includes/libs/JavaScriptMinifierTest.php
index c8795b2e..149a28c1 100644
--- a/tests/phpunit/includes/libs/JavaScriptMinifierTest.php
+++ b/tests/phpunit/includes/libs/JavaScriptMinifierTest.php
@@ -1,6 +1,6 @@
<?php
-class JavaScriptMinifierTest extends MediaWikiTestCase {
+class JavaScriptMinifierTest extends PHPUnit_Framework_TestCase {
public static function provideCases() {
return array(
@@ -164,7 +164,7 @@ class JavaScriptMinifierTest extends MediaWikiTestCase {
);
}
- public static function provideBug32548() {
+ public static function provideExponentLineBreaking() {
return array(
array(
// This one gets interpreted all together by the prior code;
@@ -183,14 +183,13 @@ class JavaScriptMinifierTest extends MediaWikiTestCase {
}
/**
- * @dataProvider provideBug32548
+ * @dataProvider provideExponentLineBreaking
* @covers JavaScriptMinifier::minify
- * @todo give this test a real name explaining what is being tested here
*/
- public function testBug32548Exponent( $num ) {
+ public function testExponentLineBreaking( $num ) {
// Long line breaking was being incorrectly done between the base and
// exponent part of a number, causing a syntax error. The line should
- // instead break at the start of the number.
+ // instead break at the start of the number. (T34548)
$prefix = 'var longVarName' . str_repeat( '_', 973 ) . '=';
$suffix = ',shortVarName=0;';
diff --git a/tests/phpunit/includes/libs/MWMessagePackTest.php b/tests/phpunit/includes/libs/MWMessagePackTest.php
index f80f78df..ec145836 100644
--- a/tests/phpunit/includes/libs/MWMessagePackTest.php
+++ b/tests/phpunit/includes/libs/MWMessagePackTest.php
@@ -3,7 +3,7 @@
* PHP Unit tests for MWMessagePack
* @covers MWMessagePack
*/
-class MWMessagePackTest extends MediaWikiTestCase {
+class MWMessagePackTest extends PHPUnit_Framework_TestCase {
/**
* Provides test cases for MWMessagePackTest::testMessagePack
diff --git a/tests/phpunit/includes/libs/ObjectFactoryTest.php b/tests/phpunit/includes/libs/ObjectFactoryTest.php
new file mode 100644
index 00000000..92207325
--- /dev/null
+++ b/tests/phpunit/includes/libs/ObjectFactoryTest.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+class ObjectFactoryTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * @covers ObjectFactory::getObjectFromSpec
+ */
+ public function testClosureExpansionDisabled() {
+ $obj = ObjectFactory::getObjectFromSpec( array(
+ 'class' => 'ObjectFactoryTest_Fixture',
+ 'args' => array( function (){ return 'unwrapped'; }, ),
+ 'closure_expansion' => false,
+ ) );
+ $this->assertInstanceOf( 'Closure', $obj->args[0] );
+ $this->assertSame( 'unwrapped', $obj->args[0]() );
+ }
+
+ /**
+ * @covers ObjectFactory::getObjectFromSpec
+ */
+ public function testClosureExpansionEnabled() {
+ $obj = ObjectFactory::getObjectFromSpec( array(
+ 'class' => 'ObjectFactoryTest_Fixture',
+ 'args' => array( function (){ return 'unwrapped'; }, ),
+ 'closure_expansion' => true,
+ ) );
+ $this->assertInternalType( 'string', $obj->args[0] );
+ $this->assertSame( 'unwrapped', $obj->args[0] );
+
+ $obj = ObjectFactory::getObjectFromSpec( array(
+ 'class' => 'ObjectFactoryTest_Fixture',
+ 'args' => array( function (){ return 'unwrapped'; }, ),
+ ) );
+ $this->assertInternalType( 'string', $obj->args[0] );
+ $this->assertSame( 'unwrapped', $obj->args[0] );
+ }
+}
+
+class ObjectFactoryTest_Fixture {
+ public $args;
+ public function __construct( /*...*/ ) { $this->args = func_get_args(); }
+}
diff --git a/tests/phpunit/includes/libs/ProcessCacheLRUTest.php b/tests/phpunit/includes/libs/ProcessCacheLRUTest.php
index 1a8a1e56..43001979 100644
--- a/tests/phpunit/includes/libs/ProcessCacheLRUTest.php
+++ b/tests/phpunit/includes/libs/ProcessCacheLRUTest.php
@@ -9,20 +9,20 @@
*
* @group Cache
*/
-class ProcessCacheLRUTest extends MediaWikiTestCase {
+class ProcessCacheLRUTest extends PHPUnit_Framework_TestCase {
/**
* Helper to verify emptiness of a cache object.
* Compare against an array so we get the cache content difference.
*/
- function assertCacheEmpty( $cache, $msg = 'Cache should be empty' ) {
+ protected function assertCacheEmpty( $cache, $msg = 'Cache should be empty' ) {
$this->assertAttributeEquals( array(), 'cache', $cache, $msg );
}
/**
* Helper to fill a cache object passed by reference
*/
- function fillCache( &$cache, $numEntries ) {
+ protected function fillCache( &$cache, $numEntries ) {
// Fill cache with three values
for ( $i = 1; $i <= $numEntries; $i++ ) {
$cache->set( "cache-key-$i", "prop-$i", "value-$i" );
@@ -33,17 +33,17 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
* Generates an array of what would be expected in cache for a given cache
* size and a number of entries filled in sequentially
*/
- function getExpectedCache( $cacheMaxEntries, $entryToFill ) {
+ protected function getExpectedCache( $cacheMaxEntries, $entryToFill ) {
$expected = array();
if ( $entryToFill === 0 ) {
- # The cache is empty!
+ // The cache is empty!
return array();
} elseif ( $entryToFill <= $cacheMaxEntries ) {
- # Cache is not fully filled
+ // Cache is not fully filled
$firstKey = 1;
} else {
- # Cache overflowed
+ // Cache overflowed
$firstKey = 1 + $entryToFill - $cacheMaxEntries;
}
@@ -62,13 +62,16 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
public function testPhpUnitArrayEquality() {
$one = array( 'A' => 1, 'B' => 2 );
$two = array( 'B' => 2, 'A' => 1 );
- $this->assertEquals( $one, $two ); // ==
- $this->assertNotSame( $one, $two ); // ===
+ // ==
+ $this->assertEquals( $one, $two );
+ // ===
+ $this->assertNotSame( $one, $two );
}
/**
* @dataProvider provideInvalidConstructorArg
* @expectedException UnexpectedValueException
+ * @covers ProcessCacheLRU::__construct
*/
public function testConstructorGivenInvalidValue( $maxSize ) {
new ProcessCacheLRUTestable( $maxSize );
@@ -88,6 +91,11 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
);
}
+ /**
+ * @covers ProcessCacheLRU::get
+ * @covers ProcessCacheLRU::set
+ * @covers ProcessCacheLRU::het
+ */
public function testAddAndGetAKey() {
$oneCache = new ProcessCacheLRUTestable( 1 );
$this->assertCacheEmpty( $oneCache );
@@ -99,6 +107,10 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
$this->assertEquals( 'value1', $oneCache->get( 'cache-key', 'prop1' ) );
}
+ /**
+ * @covers ProcessCacheLRU::set
+ * @covers ProcessCacheLRU::get
+ */
public function testDeleteOldKey() {
$oneCache = new ProcessCacheLRUTestable( 1 );
$this->assertCacheEmpty( $oneCache );
@@ -113,6 +125,7 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
* a sequence of always different cache-keys. Meant to verify we correclty
* delete the older key.
*
+ * @covers ProcessCacheLRU::set
* @dataProvider provideCacheFilling
* @param int $cacheMaxEntries Maximum entry the created cache will hold
* @param int $entryToFill Number of entries to insert in the created cache.
@@ -136,14 +149,18 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
return array(
array( 1, 0 ),
array( 1, 1 ),
- array( 1, 2 ), # overflow
- array( 5, 33 ), # overflow
+ // overflow
+ array( 1, 2 ),
+ // overflow
+ array( 5, 33 ),
);
}
/**
* Create a cache with only one remaining entry then update
* the first inserted entry. Should bump it to the top.
+ *
+ * @covers ProcessCacheLRU::set
*/
public function testReplaceExistingKeyShouldBumpEntryToTop() {
$maxEntries = 3;
@@ -164,6 +181,11 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
);
}
+ /**
+ * @covers ProcessCacheLRU::get
+ * @covers ProcessCacheLRU::set
+ * @covers ProcessCacheLRU::het
+ */
public function testRecentlyAccessedKeyStickIn() {
$cache = new ProcessCacheLRUTestable( 2 );
$cache->set( 'first', 'prop1', 'value1' );
@@ -182,6 +204,9 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
* filled entry.
* Given a cache having 1,2,3 as key, updating 2 should bump 2 to
* the top of the queue with the new value: 1,3,2* (* = updated).
+ *
+ * @covers ProcessCacheLRU::set
+ * @covers ProcessCacheLRU::get
*/
public function testReplaceExistingKeyInAFullCacheShouldBumpToTop() {
$maxEntries = 3;
@@ -204,6 +229,9 @@ class ProcessCacheLRUTest extends MediaWikiTestCase {
);
}
+ /**
+ * @covers ProcessCacheLRU::set
+ */
public function testBumpExistingKeyToTop() {
$cache = new ProcessCacheLRUTestable( 3 );
$this->fillCache( $cache, 3 );
diff --git a/tests/phpunit/includes/libs/RunningStatTest.php b/tests/phpunit/includes/libs/RunningStatTest.php
index dc5db82c..edfaf162 100644
--- a/tests/phpunit/includes/libs/RunningStatTest.php
+++ b/tests/phpunit/includes/libs/RunningStatTest.php
@@ -3,7 +3,7 @@
* PHP Unit tests for RunningStat class.
* @covers RunningStat
*/
-class RunningStatTest extends MediaWikiTestCase {
+class RunningStatTest extends PHPUnit_Framework_TestCase {
public $points = array(
49.7168, 74.3804, 7.0115, 96.5769, 34.9458,
diff --git a/tests/phpunit/includes/utils/StringUtilsTest.php b/tests/phpunit/includes/libs/StringUtilsTest.php
index 0fdb8e15..7c24fae6 100644
--- a/tests/phpunit/includes/utils/StringUtilsTest.php
+++ b/tests/phpunit/includes/libs/StringUtilsTest.php
@@ -1,6 +1,6 @@
<?php
-class StringUtilsTest extends MediaWikiTestCase {
+class StringUtilsTest extends PHPUnit_Framework_TestCase {
/**
* This tests StringUtils::isUtf8 whenever we have the mbstring extension
diff --git a/tests/phpunit/includes/libs/XhprofTest.php b/tests/phpunit/includes/libs/XhprofTest.php
new file mode 100644
index 00000000..2440fc08
--- /dev/null
+++ b/tests/phpunit/includes/libs/XhprofTest.php
@@ -0,0 +1,320 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * @uses Xhprof
+ * @uses AutoLoader
+ * @author Bryan Davis <bd808@wikimedia.org>
+ * @copyright © 2014 Bryan Davis and Wikimedia Foundation.
+ * @since 1.25
+ */
+class XhprofTest extends PHPUnit_Framework_TestCase {
+
+ public function setUp() {
+ if ( !function_exists( 'xhprof_enable' ) ) {
+ $this->markTestSkipped( 'No xhprof support detected.' );
+ }
+ }
+
+ /**
+ * @covers Xhprof::splitKey
+ * @dataProvider provideSplitKey
+ */
+ public function testSplitKey( $key, $expect ) {
+ $this->assertSame( $expect, Xhprof::splitKey( $key ) );
+ }
+
+ public function provideSplitKey() {
+ return array(
+ array( 'main()', array( null, 'main()' ) ),
+ array( 'foo==>bar', array( 'foo', 'bar' ) ),
+ array( 'bar@1==>bar@2', array( 'bar@1', 'bar@2' ) ),
+ array( 'foo==>bar==>baz', array( 'foo', 'bar==>baz' ) ),
+ array( '==>bar', array( '', 'bar' ) ),
+ array( '', array( null, '' ) ),
+ );
+ }
+
+ /**
+ * @covers Xhprof::__construct
+ * @covers Xhprof::stop
+ * @covers Xhprof::getRawData
+ * @dataProvider provideRawData
+ */
+ public function testRawData( $flags, $keys ) {
+ $xhprof = new Xhprof( array( 'flags' => $flags ) );
+ $raw = $xhprof->getRawData();
+ $this->assertArrayHasKey( 'main()', $raw );
+ foreach ( $keys as $key ) {
+ $this->assertArrayHasKey( $key, $raw['main()'] );
+ }
+ }
+
+ public function provideRawData() {
+ $tests = array(
+ array( 0, array( 'ct', 'wt' ) ),
+ );
+
+ if ( defined( 'XHPROF_FLAGS_CPU' ) && defined( 'XHPROF_FLAGS_CPU' ) ) {
+ $tests[] = array( XHPROF_FLAGS_MEMORY, array(
+ 'ct', 'wt', 'mu', 'pmu',
+ ) );
+ $tests[] = array( XHPROF_FLAGS_CPU, array(
+ 'ct', 'wt', 'cpu',
+ ) );
+ $tests[] = array( XHPROF_FLAGS_MEMORY | XHPROF_FLAGS_CPU, array(
+ 'ct', 'wt', 'mu', 'pmu', 'cpu',
+ ) );
+ }
+
+ return $tests;
+ }
+
+ /**
+ * @covers Xhprof::pruneData
+ */
+ public function testInclude() {
+ $xhprof = $this->getXhprofFixture( array(
+ 'include' => array( 'main()' ),
+ ) );
+ $raw = $xhprof->getRawData();
+ $this->assertArrayHasKey( 'main()', $raw );
+ $this->assertArrayHasKey( 'main()==>foo', $raw );
+ $this->assertArrayHasKey( 'main()==>xhprof_disable', $raw );
+ $this->assertSame( 3, count( $raw ) );
+ }
+
+ /**
+ * Validate the structure of data returned by
+ * Xhprof::getInclusiveMetrics(). This acts as a guard against unexpected
+ * structural changes to the returned data in lieu of using a more heavy
+ * weight typed response object.
+ *
+ * @covers Xhprof::getInclusiveMetrics
+ */
+ public function testInclusiveMetricsStructure() {
+ $metricStruct = array(
+ 'ct' => 'int',
+ 'wt' => 'array',
+ 'cpu' => 'array',
+ 'mu' => 'array',
+ 'pmu' => 'array',
+ );
+ $statStruct = array(
+ 'total' => 'numeric',
+ 'min' => 'numeric',
+ 'mean' => 'numeric',
+ 'max' => 'numeric',
+ 'variance' => 'numeric',
+ 'percent' => 'numeric',
+ );
+
+ $xhprof = $this->getXhprofFixture();
+ $metrics = $xhprof->getInclusiveMetrics();
+
+ foreach ( $metrics as $name => $metric ) {
+ $this->assertArrayStructure( $metricStruct, $metric );
+
+ foreach ( $metricStruct as $key => $type ) {
+ if ( $type === 'array' ) {
+ $this->assertArrayStructure( $statStruct, $metric[$key] );
+ if ( $name === 'main()' ) {
+ $this->assertEquals( 100, $metric[$key]['percent'] );
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Validate the structure of data returned by
+ * Xhprof::getCompleteMetrics(). This acts as a guard against unexpected
+ * structural changes to the returned data in lieu of using a more heavy
+ * weight typed response object.
+ *
+ * @covers Xhprof::getCompleteMetrics
+ */
+ public function testCompleteMetricsStructure() {
+ $metricStruct = array(
+ 'ct' => 'int',
+ 'wt' => 'array',
+ 'cpu' => 'array',
+ 'mu' => 'array',
+ 'pmu' => 'array',
+ 'calls' => 'array',
+ 'subcalls' => 'array',
+ );
+ $statsMetrics = array( 'wt', 'cpu', 'mu', 'pmu' );
+ $statStruct = array(
+ 'total' => 'numeric',
+ 'min' => 'numeric',
+ 'mean' => 'numeric',
+ 'max' => 'numeric',
+ 'variance' => 'numeric',
+ 'percent' => 'numeric',
+ 'exclusive' => 'numeric',
+ );
+
+ $xhprof = $this->getXhprofFixture();
+ $metrics = $xhprof->getCompleteMetrics();
+
+ foreach ( $metrics as $name => $metric ) {
+ $this->assertArrayStructure( $metricStruct, $metric, $name );
+
+ foreach ( $metricStruct as $key => $type ) {
+ if ( in_array( $key, $statsMetrics ) ) {
+ $this->assertArrayStructure(
+ $statStruct, $metric[$key], $key
+ );
+ $this->assertLessThanOrEqual(
+ $metric[$key]['total'], $metric[$key]['exclusive']
+ );
+ }
+ }
+ }
+ }
+
+ /**
+ * @covers Xhprof::getCallers
+ * @covers Xhprof::getCallees
+ * @uses Xhprof
+ */
+ public function testEdges() {
+ $xhprof = $this->getXhprofFixture();
+ $this->assertSame( array(), $xhprof->getCallers( 'main()' ) );
+ $this->assertSame( array( 'foo', 'xhprof_disable' ),
+ $xhprof->getCallees( 'main()' )
+ );
+ $this->assertSame( array( 'main()' ),
+ $xhprof->getCallers( 'foo' )
+ );
+ $this->assertSame( array(), $xhprof->getCallees( 'strlen' ) );
+ }
+
+ /**
+ * @covers Xhprof::getCriticalPath
+ * @uses Xhprof
+ */
+ public function testCriticalPath() {
+ $xhprof = $this->getXhprofFixture();
+ $path = $xhprof->getCriticalPath();
+
+ $last = null;
+ foreach ( $path as $key => $value ) {
+ list( $func, $call ) = Xhprof::splitKey( $key );
+ $this->assertSame( $last, $func );
+ $last = $call;
+ }
+ $this->assertSame( $last, 'bar@1' );
+ }
+
+ /**
+ * Get an Xhprof instance that has been primed with a set of known testing
+ * data. Tests for the Xhprof class should laregly be concerned with
+ * evaluating the manipulations of the data collected by xhprof rather
+ * than the data collection process itself.
+ *
+ * The returned Xhprof instance primed will be with a data set created by
+ * running this trivial program using the PECL xhprof implementation:
+ * @code
+ * function bar( $x ) {
+ * if ( $x > 0 ) {
+ * bar($x - 1);
+ * }
+ * }
+ * function foo() {
+ * for ( $idx = 0; $idx < 2; $idx++ ) {
+ * bar( $idx );
+ * $x = strlen( 'abc' );
+ * }
+ * }
+ * xhprof_enable( XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY );
+ * foo();
+ * $x = xhprof_disable();
+ * var_export( $x );
+ * @endcode
+ *
+ * @return Xhprof
+ */
+ protected function getXhprofFixture( array $opts = array() ) {
+ $xhprof = new Xhprof( $opts );
+ $xhprof->loadRawData( array (
+ 'foo==>bar' => array (
+ 'ct' => 2,
+ 'wt' => 57,
+ 'cpu' => 92,
+ 'mu' => 1896,
+ 'pmu' => 0,
+ ),
+ 'foo==>strlen' => array (
+ 'ct' => 2,
+ 'wt' => 21,
+ 'cpu' => 141,
+ 'mu' => 752,
+ 'pmu' => 0,
+ ),
+ 'bar==>bar@1' => array (
+ 'ct' => 1,
+ 'wt' => 18,
+ 'cpu' => 19,
+ 'mu' => 752,
+ 'pmu' => 0,
+ ),
+ 'main()==>foo' => array (
+ 'ct' => 1,
+ 'wt' => 304,
+ 'cpu' => 307,
+ 'mu' => 4008,
+ 'pmu' => 0,
+ ),
+ 'main()==>xhprof_disable' => array (
+ 'ct' => 1,
+ 'wt' => 8,
+ 'cpu' => 10,
+ 'mu' => 768,
+ 'pmu' => 392,
+ ),
+ 'main()' => array (
+ 'ct' => 1,
+ 'wt' => 353,
+ 'cpu' => 351,
+ 'mu' => 6112,
+ 'pmu' => 1424,
+ ),
+ ) );
+ return $xhprof;
+ }
+
+ /**
+ * Assert that the given array has the described structure.
+ *
+ * @param array $struct Array of key => type mappings
+ * @param array $actual Array to check
+ * @param string $label
+ */
+ protected function assertArrayStructure( $struct, $actual, $label = null ) {
+ $this->assertInternalType( 'array', $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/XmlTypeCheckTest.php b/tests/phpunit/includes/libs/XmlTypeCheckTest.php
index 6ad97fd4..f0ba934e 100644
--- a/tests/phpunit/includes/XmlTypeCheckTest.php
+++ b/tests/phpunit/includes/libs/XmlTypeCheckTest.php
@@ -5,7 +5,7 @@
* @group Xml
* @covers XMLTypeCheck
*/
-class XmlTypeCheckTest extends MediaWikiTestCase {
+class XmlTypeCheckTest extends PHPUnit_Framework_TestCase {
const WELL_FORMED_XML = "<root><child /></root>";
const MAL_FORMED_XML = "<root><child /></error>";
const XML_WITH_PIH = '<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="/w/index.php"?><svg><child /></svg>';
diff --git a/tests/phpunit/includes/libs/composer/ComposerJsonTest.php b/tests/phpunit/includes/libs/composer/ComposerJsonTest.php
new file mode 100644
index 00000000..0c58b65a
--- /dev/null
+++ b/tests/phpunit/includes/libs/composer/ComposerJsonTest.php
@@ -0,0 +1,57 @@
+<?php
+
+class ComposerJsonTest extends MediaWikiTestCase {
+
+ private $json, $json2;
+
+ public function setUp() {
+ parent::setUp();
+ global $IP;
+ $this->json = "$IP/tests/phpunit/data/composer/composer.json";
+ $this->json2 = "$IP/tests/phpunit/data/composer/new-composer.json";
+ }
+
+ public static function provideGetHash() {
+ return array(
+ array( 'json', 'cc6e7fc565b246cb30b0cac103a2b31e' ),
+ array( 'json2', '19921dd1fc457f1b00561da932432001' ),
+ );
+ }
+
+ /**
+ * @dataProvider provideGetHash
+ * @covers ComposerJson::getHash
+ */
+ public function testIsHashUpToDate( $file, $expected ) {
+ $json = new ComposerJson( $this->$file );
+ $this->assertEquals( $expected, $json->getHash() );
+ }
+
+ /**
+ * @covers ComposerJson::getRequiredDependencies
+ */
+ public function testGetRequiredDependencies() {
+ $json = new ComposerJson( $this->json );
+ $this->assertArrayEquals( array(
+ 'cdb/cdb' => '1.0.0',
+ 'cssjanus/cssjanus' => '1.1.1',
+ 'leafo/lessphp' => '0.5.0',
+ 'psr/log' => '1.0.0',
+ ), $json->getRequiredDependencies(), false, true );
+ }
+
+ public static function provideNormalizeVersion() {
+ return array(
+ array( 'v1.0.0', '1.0.0' ),
+ array( '0.0.5', '0.0.5' ),
+ );
+ }
+
+ /**
+ * @dataProvider provideNormalizeVersion
+ * @covers ComposerJson::normalizeVersion
+ */
+ public function testNormalizeVersion( $input, $expected ) {
+ $this->assertEquals( $expected, ComposerJson::normalizeVersion( $input ) );
+ }
+}
diff --git a/tests/phpunit/includes/libs/composer/ComposerLockTest.php b/tests/phpunit/includes/libs/composer/ComposerLockTest.php
new file mode 100644
index 00000000..b5fd5f6e
--- /dev/null
+++ b/tests/phpunit/includes/libs/composer/ComposerLockTest.php
@@ -0,0 +1,62 @@
+<?php
+
+class ComposerLockTest extends MediaWikiTestCase {
+
+ private $lock;
+
+ public function setUp() {
+ parent::setUp();
+ global $IP;
+ $this->lock = "$IP/tests/phpunit/data/composer/composer.lock";
+ }
+
+ /**
+ * @covers ComposerLock::getHash
+ */
+ public function testGetHash() {
+ $lock = new ComposerLock( $this->lock );
+ $this->assertEquals( 'a3bb80b0ac4c4a31e52574d48c032923', $lock->getHash() );
+ }
+
+ /**
+ * @covers ComposerLock::getInstalledDependencies
+ */
+ public function testGetInstalledDependencies() {
+ $lock = new ComposerLock( $this->lock );
+ $this->assertArrayEquals( array(
+ 'wikimedia/cdb' => array(
+ 'version' => '1.0.1',
+ 'type' => 'library',
+ ),
+ 'cssjanus/cssjanus' => array(
+ 'version' => '1.1.1',
+ 'type' => 'library',
+ ),
+ 'leafo/lessphp' => array(
+ 'version' => '0.5.0',
+ 'type' => 'library',
+ ),
+ 'psr/log' => array(
+ 'version' => '1.0.0',
+ 'type' => 'library',
+ ),
+ 'oojs/oojs-ui' => array(
+ 'version' => '0.6.0',
+ 'type' => 'library',
+ ),
+ 'composer/installers' => array(
+ 'version' => '1.0.19',
+ 'type' => 'composer-installer',
+ ),
+ 'mediawiki/translate' => array(
+ 'version' => '2014.12',
+ 'type' => 'mediawiki-extension',
+ ),
+ 'mediawiki/universal-language-selector' => array(
+ 'version' => '2014.12',
+ 'type' => 'mediawiki-extension',
+ ),
+ ), $lock->getInstalledDependencies(), false, true );
+ }
+
+}
diff --git a/tests/phpunit/includes/logging/LogFormatterTest.php b/tests/phpunit/includes/logging/LogFormatterTest.php
index 6210d098..515990e6 100644
--- a/tests/phpunit/includes/logging/LogFormatterTest.php
+++ b/tests/phpunit/includes/logging/LogFormatterTest.php
@@ -239,4 +239,57 @@ class LogFormatterTest extends MediaWikiLangTestCase {
$this->assertEquals( $comment, $formatter->getComment() );
}
+
+ /**
+ * @dataProvider provideApiParamFormatting
+ * @covers LogFormatter::formatParametersForApi
+ * @covers LogFormatter::formatParameterValueForApi
+ */
+ public function testApiParamFormatting( $key, $value, $expected ) {
+ $entry = $this->newLogEntry( 'param', array( $key => $value ) );
+ $formatter = LogFormatter::newFromEntry( $entry );
+ $formatter->setContext( $this->context );
+
+ ApiResult::setIndexedTagName( $expected, 'param' );
+ ApiResult::setArrayType( $expected, 'assoc' );
+
+ $this->assertEquals( $expected, $formatter->formatParametersForApi() );
+ }
+
+ public static function provideApiParamFormatting() {
+ return array(
+ array( 0, 'value', array( 'value' ) ),
+ array( 'named', 'value', array( 'named' => 'value' ) ),
+ array( '::key', 'value', array( 'key' => 'value' ) ),
+ array( '4::key', 'value', array( 'key' => 'value' ) ),
+ array( '4:raw:key', 'value', array( 'key' => 'value' ) ),
+ array( '4:plain:key', 'value', array( 'key' => 'value' ) ),
+ array( '4:bool:key', '1', array( 'key' => true ) ),
+ array( '4:bool:key', '0', array( 'key' => false ) ),
+ array( '4:number:key', '123', array( 'key' => 123 ) ),
+ array( '4:number:key', '123.5', array( 'key' => 123.5 ) ),
+ array( '4:array:key', array(), array( 'key' => array( ApiResult::META_TYPE => 'array' ) ) ),
+ array( '4:assoc:key', array(), array( 'key' => array( ApiResult::META_TYPE => 'assoc' ) ) ),
+ array( '4:kvp:key', array(), array( 'key' => array( ApiResult::META_TYPE => 'kvp' ) ) ),
+ array( '4:timestamp:key', '20150102030405', array( 'key' => '2015-01-02T03:04:05Z' ) ),
+ array( '4:msg:key', 'parentheses', array(
+ 'key_key' => 'parentheses',
+ 'key_text' => wfMessage( 'parentheses' )->text(),
+ ) ),
+ array( '4:msg-content:key', 'parentheses', array(
+ 'key_key' => 'parentheses',
+ 'key_text' => wfMessage( 'parentheses' )->inContentLanguage()->text(),
+ ) ),
+ array( '4:title:key', 'project:foo', array(
+ 'key_ns' => NS_PROJECT,
+ 'key_title' => Title::newFromText( 'project:foo' )->getFullText(),
+ ) ),
+ array( '4:title-link:key', 'project:foo', array(
+ 'key_ns' => NS_PROJECT,
+ 'key_title' => Title::newFromText( 'project:foo' )->getFullText(),
+ ) ),
+ array( '4:user:key', 'foo', array( 'key' => 'Foo' ) ),
+ array( '4:user-link:key', 'foo', array( 'key' => 'Foo' ) ),
+ );
+ }
}
diff --git a/tests/phpunit/includes/mail/MailAddressTest.php b/tests/phpunit/includes/mail/MailAddressTest.php
index 2d078120..18d2acdf 100644
--- a/tests/phpunit/includes/mail/MailAddressTest.php
+++ b/tests/phpunit/includes/mail/MailAddressTest.php
@@ -14,6 +14,9 @@ class MailAddressTest extends MediaWikiTestCase {
* @covers MailAddress::newFromUser
*/
public function testNewFromUser() {
+ if ( wfIsWindows() ) {
+ $this->markTestSkipped( 'This test only works on non-Windows platforms' );
+ }
$user = $this->getMock( 'User' );
$user->expects( $this->any() )->method( 'getName' )->will( $this->returnValue( 'UserName' ) );
$user->expects( $this->any() )->method( 'getEmail' )->will( $this->returnValue( 'foo@bar.baz' ) );
@@ -49,6 +52,7 @@ class MailAddressTest extends MediaWikiTestCase {
array( false, 'foo@bar.baz', 'AUserName', 'Some real name', 'AUserName <foo@bar.baz>' ),
array( false, 'foo@bar.baz', '', '', 'foo@bar.baz' ),
array( true, 'foo@bar.baz', '', '', 'foo@bar.baz' ),
+ array( true, '', '', '', '' ),
);
}
@@ -59,5 +63,4 @@ class MailAddressTest extends MediaWikiTestCase {
$ma = new MailAddress( 'some@email.com', 'UserName', 'A real name' );
$this->assertEquals( $ma->toString(), (string)$ma );
}
-
-} \ No newline at end of file
+}
diff --git a/tests/phpunit/includes/media/BitmapScalingTest.php b/tests/phpunit/includes/media/BitmapScalingTest.php
index 1972c969..e4415ece 100644
--- a/tests/phpunit/includes/media/BitmapScalingTest.php
+++ b/tests/phpunit/includes/media/BitmapScalingTest.php
@@ -113,7 +113,7 @@ class BitmapScalingTest extends MediaWikiTestCase {
$file = new FakeDimensionFile( array( 4000, 4000 ) );
$handler = new BitmapHandler;
$params = array( 'width' => '3700' ); // Still bigger than max size.
- $this->assertEquals( 'TransformParameterError',
+ $this->assertEquals( 'TransformTooBigImageAreaError',
get_class( $handler->doTransform( $file, 'dummy path', '', $params ) ) );
}
@@ -125,7 +125,7 @@ class BitmapScalingTest extends MediaWikiTestCase {
$file->mustRender = true;
$handler = new BitmapHandler;
$params = array( 'width' => '5000' ); // Still bigger than max size.
- $this->assertEquals( 'TransformParameterError',
+ $this->assertEquals( 'TransformTooBigImageAreaError',
get_class( $handler->doTransform( $file, 'dummy path', '', $params ) ) );
}
diff --git a/tests/phpunit/includes/media/FormatMetadataTest.php b/tests/phpunit/includes/media/FormatMetadataTest.php
index 002e2cb9..54758f94 100644
--- a/tests/phpunit/includes/media/FormatMetadataTest.php
+++ b/tests/phpunit/includes/media/FormatMetadataTest.php
@@ -68,4 +68,36 @@ class FormatMetadataTest extends MediaWikiMediaTestCase {
// TODO: more test cases
);
}
+
+ /**
+ * @param mixed $input
+ * @param mixed $output
+ * @dataProvider provideResolveMultivalueValue
+ * @covers FormatMetadata::resolveMultivalueValue
+ */
+ public function testResolveMultivalueValue( $input, $output ) {
+ $formatMetadata = new FormatMetadata();
+ $class = new ReflectionClass( 'FormatMetadata' );
+ $method = $class->getMethod( 'resolveMultivalueValue' );
+ $method->setAccessible( true );
+ $actualInput = $method->invoke( $formatMetadata, $input );
+ $this->assertEquals( $output, $actualInput );
+ }
+
+ public function provideResolveMultivalueValue() {
+ return array(
+ 'nonArray' => array( 'foo', 'foo' ),
+ 'multiValue' => array( array( 'first', 'second', 'third', '_type' => 'ol' ), 'first' ),
+ 'noType' => array( array( 'first', 'second', 'third' ), 'first' ),
+ 'typeFirst' => array( array( '_type' => 'ol', 'first', 'second', 'third' ), 'first' ),
+ 'multilang' => array(
+ array( 'en' => 'first', 'de' => 'Erste', '_type' => 'lang' ),
+ array( 'en' => 'first', 'de' => 'Erste', '_type' => 'lang' ),
+ ),
+ 'multilang-multivalue' => array(
+ array( 'en' => array( 'first', 'second' ), 'de' => array( 'Erste', 'Zweite' ), '_type' => 'lang' ),
+ array( 'en' => 'first', 'de' => 'Erste', '_type' => 'lang' ),
+ ),
+ );
+ }
}
diff --git a/tests/phpunit/includes/media/MediaHandlerTest.php b/tests/phpunit/includes/media/MediaHandlerTest.php
index d8cfcc45..78ea9530 100644
--- a/tests/phpunit/includes/media/MediaHandlerTest.php
+++ b/tests/phpunit/includes/media/MediaHandlerTest.php
@@ -7,50 +7,62 @@ class MediaHandlerTest extends MediaWikiTestCase {
/**
* @covers MediaHandler::fitBoxWidth
- * @todo split into a dataprovider and test method
+ *
+ * @dataProvider provideTestFitBoxWidth
*/
- public function testFitBoxWidth() {
- $vals = array(
- array(
- 'width' => 50,
- 'height' => 50,
- 'tests' => array(
+ public function testFitBoxWidth( $width, $height, $max, $expected ) {
+ $y = round( $expected * $height / $width );
+ $result = MediaHandler::fitBoxWidth( $width, $height, $max );
+ $y2 = round( $result * $height / $width );
+ $this->assertEquals( $expected,
+ $result,
+ "($width, $height, $max) wanted: {$expected}x$y, got: {z$result}x$y2" );
+ }
+
+ public static function provideTestFitBoxWidth() {
+ return array_merge(
+ static::generateTestFitBoxWidthData( 50, 50, array(
50 => 50,
17 => 17,
- 18 => 18 ) ),
- array(
- 'width' => 366,
- 'height' => 300,
- 'tests' => array(
+ 18 => 18 )
+ ),
+ static::generateTestFitBoxWidthData( 366, 300, array(
50 => 61,
17 => 21,
- 18 => 22 ) ),
- array(
- 'width' => 300,
- 'height' => 366,
- 'tests' => array(
+ 18 => 22 )
+ ),
+ static::generateTestFitBoxWidthData( 300, 366, array(
50 => 41,
17 => 14,
- 18 => 15 ) ),
- array(
- 'width' => 100,
- 'height' => 400,
- 'tests' => array(
+ 18 => 15 )
+ ),
+ static::generateTestFitBoxWidthData( 100, 400, array(
50 => 12,
17 => 4,
- 18 => 4 ) ) );
- foreach ( $vals as $row ) {
- $tests = $row['tests'];
- $height = $row['height'];
- $width = $row['width'];
- foreach ( $tests as $max => $expected ) {
- $y = round( $expected * $height / $width );
- $result = MediaHandler::fitBoxWidth( $width, $height, $max );
- $y2 = round( $result * $height / $width );
- $this->assertEquals( $expected,
- $result,
- "($width, $height, $max) wanted: {$expected}x$y, got: {$result}x$y2" );
- }
+ 18 => 4 )
+ )
+ );
+ }
+
+ /**
+ * Generate single test cases by combining the dimensions and tests contents
+ *
+ * It creates:
+ * [$width, $height, $max, $expected],
+ * [$width, $height, $max2, $expected2], ...
+ * out of parameters:
+ * $width, $height, { $max => $expected, $max2 => $expected2, ... }
+ *
+ * @param $width int
+ * @param $height int
+ * @param $tests array associative array of $max => $expected values
+ * @return array
+ */
+ private static function generateTestFitBoxWidthData( $width, $height, $tests ) {
+ $result = array();
+ foreach ( $tests as $max => $expected ) {
+ $result[] = array( $width, $height, $max, $expected );
}
+ return $result;
}
}
diff --git a/tests/phpunit/includes/media/SVGMetadataExtractorTest.php b/tests/phpunit/includes/media/SVGMetadataExtractorTest.php
index ab33d1c2..0241aec4 100644
--- a/tests/phpunit/includes/media/SVGMetadataExtractorTest.php
+++ b/tests/phpunit/includes/media/SVGMetadataExtractorTest.php
@@ -6,11 +6,6 @@
*/
class SVGMetadataExtractorTest extends MediaWikiTestCase {
- protected function setUp() {
- parent::setUp();
- AutoLoader::loadClass( 'SVGMetadataExtractorTest' );
- }
-
/**
* @dataProvider provideSvgFiles
*/
diff --git a/tests/phpunit/includes/normal/CleanUpTest.php b/tests/phpunit/includes/normal/CleanUpTest.php
deleted file mode 100644
index f4b469b8..00000000
--- a/tests/phpunit/includes/normal/CleanUpTest.php
+++ /dev/null
@@ -1,409 +0,0 @@
-<?php
-/**
- * Tests for UtfNormal::cleanUp() function.
- *
- * Copyright © 2004 Brion Vibber <brion@pobox.com>
- * https://www.mediawiki.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * Additional tests for UtfNormal::cleanUp() function, inclusion
- * regression checks for known problems.
- * Requires PHPUnit.
- *
- * @ingroup UtfNormal
- * @group Large
- *
- * @todo covers tags, will be UtfNormal::cleanUp once the below is resolved
- * @todo split me into test methods and providers per the below comment
- *
- * We ignore code coverage for this test suite until they are rewritten
- * to use data providers (bug 46561).
- * @codeCoverageIgnore
- */
-class CleanUpTest extends MediaWikiTestCase {
- /** @todo document */
- public function testAscii() {
- $text = 'This is plain ASCII text.';
- $this->assertEquals( $text, UtfNormal::cleanUp( $text ) );
- }
-
- /** @todo document */
- public function testNull() {
- $text = "a \x00 null";
- $expect = "a \xef\xbf\xbd null";
- $this->assertEquals(
- bin2hex( $expect ),
- bin2hex( UtfNormal::cleanUp( $text ) ) );
- }
-
- /** @todo document */
- public function testLatin() {
- $text = "L'\xc3\xa9cole";
- $this->assertEquals( $text, UtfNormal::cleanUp( $text ) );
- }
-
- /** @todo document */
- public function testLatinNormal() {
- $text = "L'e\xcc\x81cole";
- $expect = "L'\xc3\xa9cole";
- $this->assertEquals( $expect, UtfNormal::cleanUp( $text ) );
- }
-
- /**
- * This test is *very* expensive!
- * @todo document
- */
- function XtestAllChars() {
- $rep = UTF8_REPLACEMENT;
- for ( $i = 0x0; $i < UNICODE_MAX; $i++ ) {
- $char = codepointToUtf8( $i );
- $clean = UtfNormal::cleanUp( $char );
- $x = sprintf( "%04X", $i );
-
- if ( $i % 0x1000 == 0 ) {
- echo "U+$x\n";
- }
-
- if ( $i == 0x0009 ||
- $i == 0x000a ||
- $i == 0x000d ||
- ( $i > 0x001f && $i < UNICODE_SURROGATE_FIRST ) ||
- ( $i > UNICODE_SURROGATE_LAST && $i < 0xfffe ) ||
- ( $i > 0xffff && $i <= UNICODE_MAX )
- ) {
- if ( isset( UtfNormal::$utfCanonicalComp[$char] )
- || isset( UtfNormal::$utfCanonicalDecomp[$char] )
- ) {
- $comp = UtfNormal::NFC( $char );
- $this->assertEquals(
- bin2hex( $comp ),
- bin2hex( $clean ),
- "U+$x should be decomposed" );
- } else {
- $this->assertEquals(
- bin2hex( $char ),
- bin2hex( $clean ),
- "U+$x should be intact" );
- }
- } else {
- $this->assertEquals( bin2hex( $rep ), bin2hex( $clean ), $x );
- }
- }
- }
-
- /** @todo document */
- public static function provideAllBytes() {
- return array(
- array( '', '' ),
- array( 'x', '' ),
- array( '', 'x' ),
- array( 'x', 'x' ),
- );
- }
-
- /**
- * @dataProvider provideAllBytes
- * @todo document
- */
- function testBytes( $head, $tail ) {
- for ( $i = 0x0; $i < 256; $i++ ) {
- $char = $head . chr( $i ) . $tail;
- $clean = UtfNormal::cleanUp( $char );
- $x = sprintf( "%02X", $i );
-
- if ( $i == 0x0009 ||
- $i == 0x000a ||
- $i == 0x000d ||
- ( $i > 0x001f && $i < 0x80 )
- ) {
- $this->assertEquals(
- bin2hex( $char ),
- bin2hex( $clean ),
- "ASCII byte $x should be intact" );
- if ( $char != $clean ) {
- return;
- }
- } else {
- $norm = $head . UTF8_REPLACEMENT . $tail;
- $this->assertEquals(
- bin2hex( $norm ),
- bin2hex( $clean ),
- "Forbidden byte $x should be rejected" );
- if ( $norm != $clean ) {
- return;
- }
- }
- }
- }
-
- /**
- * @dataProvider provideAllBytes
- * @todo document
- */
- function testDoubleBytes( $head, $tail ) {
- for ( $first = 0xc0; $first < 0x100; $first += 2 ) {
- for ( $second = 0x80; $second < 0x100; $second += 2 ) {
- $char = $head . chr( $first ) . chr( $second ) . $tail;
- $clean = UtfNormal::cleanUp( $char );
- $x = sprintf( "%02X,%02X", $first, $second );
- if ( $first > 0xc1 &&
- $first < 0xe0 &&
- $second < 0xc0
- ) {
- $norm = UtfNormal::NFC( $char );
- $this->assertEquals(
- bin2hex( $norm ),
- bin2hex( $clean ),
- "Pair $x should be intact" );
- if ( $norm != $clean ) {
- return;
- }
- } elseif ( $first > 0xfd || $second > 0xbf ) {
- # fe and ff are not legal head bytes -- expect two replacement chars
- $norm = $head . UTF8_REPLACEMENT . UTF8_REPLACEMENT . $tail;
- $this->assertEquals(
- bin2hex( $norm ),
- bin2hex( $clean ),
- "Forbidden pair $x should be rejected" );
- if ( $norm != $clean ) {
- return;
- }
- } else {
- $norm = $head . UTF8_REPLACEMENT . $tail;
- $this->assertEquals(
- bin2hex( $norm ),
- bin2hex( $clean ),
- "Forbidden pair $x should be rejected" );
- if ( $norm != $clean ) {
- return;
- }
- }
- }
- }
- }
-
- /**
- * @dataProvider provideAllBytes
- * @todo document
- */
- function testTripleBytes( $head, $tail ) {
- for ( $first = 0xc0; $first < 0x100; $first += 2 ) {
- for ( $second = 0x80; $second < 0x100; $second += 2 ) {
- #for( $third = 0x80; $third < 0x100; $third++ ) {
- for ( $third = 0x80; $third < 0x81; $third++ ) {
- $char = $head . chr( $first ) . chr( $second ) . chr( $third ) . $tail;
- $clean = UtfNormal::cleanUp( $char );
- $x = sprintf( "%02X,%02X,%02X", $first, $second, $third );
-
- if ( $first >= 0xe0 &&
- $first < 0xf0 &&
- $second < 0xc0 &&
- $third < 0xc0
- ) {
- if ( $first == 0xe0 && $second < 0xa0 ) {
- $this->assertEquals(
- bin2hex( $head . UTF8_REPLACEMENT . $tail ),
- bin2hex( $clean ),
- "Overlong triplet $x should be rejected" );
- } elseif ( $first == 0xed &&
- ( chr( $first ) . chr( $second ) . chr( $third ) ) >= UTF8_SURROGATE_FIRST
- ) {
- $this->assertEquals(
- bin2hex( $head . UTF8_REPLACEMENT . $tail ),
- bin2hex( $clean ),
- "Surrogate triplet $x should be rejected" );
- } else {
- $this->assertEquals(
- bin2hex( UtfNormal::NFC( $char ) ),
- bin2hex( $clean ),
- "Triplet $x should be intact" );
- }
- } elseif ( $first > 0xc1 && $first < 0xe0 && $second < 0xc0 ) {
- $this->assertEquals(
- bin2hex( UtfNormal::NFC( $head . chr( $first ) .
- chr( $second ) ) . UTF8_REPLACEMENT . $tail ),
- bin2hex( $clean ),
- "Valid 2-byte $x + broken tail" );
- } elseif ( $second > 0xc1 && $second < 0xe0 && $third < 0xc0 ) {
- $this->assertEquals(
- bin2hex( $head . UTF8_REPLACEMENT .
- UtfNormal::NFC( chr( $second ) . chr( $third ) . $tail ) ),
- bin2hex( $clean ),
- "Broken head + valid 2-byte $x" );
- } elseif ( ( $first > 0xfd || $second > 0xfd ) &&
- ( ( $second > 0xbf && $third > 0xbf ) ||
- ( $second < 0xc0 && $third < 0xc0 ) ||
- ( $second > 0xfd ) ||
- ( $third > 0xfd ) )
- ) {
- # fe and ff are not legal head bytes -- expect three replacement chars
- $this->assertEquals(
- bin2hex( $head . UTF8_REPLACEMENT . UTF8_REPLACEMENT . UTF8_REPLACEMENT . $tail ),
- bin2hex( $clean ),
- "Forbidden triplet $x should be rejected" );
- } elseif ( $first > 0xc2 && $second < 0xc0 && $third < 0xc0 ) {
- $this->assertEquals(
- bin2hex( $head . UTF8_REPLACEMENT . $tail ),
- bin2hex( $clean ),
- "Forbidden triplet $x should be rejected" );
- } else {
- $this->assertEquals(
- bin2hex( $head . UTF8_REPLACEMENT . UTF8_REPLACEMENT . $tail ),
- bin2hex( $clean ),
- "Forbidden triplet $x should be rejected" );
- }
- }
- }
- }
- }
-
- /** @todo document */
- public function testChunkRegression() {
- # Check for regression against a chunking bug
- $text = "\x46\x55\xb8" .
- "\xdc\x96" .
- "\xee" .
- "\xe7" .
- "\x44" .
- "\xaa" .
- "\x2f\x25";
- $expect = "\x46\x55\xef\xbf\xbd" .
- "\xdc\x96" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\x44" .
- "\xef\xbf\xbd" .
- "\x2f\x25";
-
- $this->assertEquals(
- bin2hex( $expect ),
- bin2hex( UtfNormal::cleanUp( $text ) ) );
- }
-
- /** @todo document */
- public function testInterposeRegression() {
- $text = "\x4e\x30" .
- "\xb1" . # bad tail
- "\x3a" .
- "\x92" . # bad tail
- "\x62\x3a" .
- "\x84" . # bad tail
- "\x43" .
- "\xc6" . # bad head
- "\x3f" .
- "\x92" . # bad tail
- "\xad" . # bad tail
- "\x7d" .
- "\xd9\x95";
-
- $expect = "\x4e\x30" .
- "\xef\xbf\xbd" .
- "\x3a" .
- "\xef\xbf\xbd" .
- "\x62\x3a" .
- "\xef\xbf\xbd" .
- "\x43" .
- "\xef\xbf\xbd" .
- "\x3f" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\x7d" .
- "\xd9\x95";
-
- $this->assertEquals(
- bin2hex( $expect ),
- bin2hex( UtfNormal::cleanUp( $text ) ) );
- }
-
- /** @todo document */
- public function testOverlongRegression() {
- $text = "\x67" .
- "\x1a" . # forbidden ascii
- "\xea" . # bad head
- "\xc1\xa6" . # overlong sequence
- "\xad" . # bad tail
- "\x1c" . # forbidden ascii
- "\xb0" . # bad tail
- "\x3c" .
- "\x9e"; # bad tail
- $expect = "\x67" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\x3c" .
- "\xef\xbf\xbd";
- $this->assertEquals(
- bin2hex( $expect ),
- bin2hex( UtfNormal::cleanUp( $text ) ) );
- }
-
- /** @todo document */
- public function testSurrogateRegression() {
- $text = "\xed\xb4\x96" . # surrogate 0xDD16
- "\x83" . # bad tail
- "\xb4" . # bad tail
- "\xac"; # bad head
- $expect = "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd";
- $this->assertEquals(
- bin2hex( $expect ),
- bin2hex( UtfNormal::cleanUp( $text ) ) );
- }
-
- /** @todo document */
- public function testBomRegression() {
- $text = "\xef\xbf\xbe" . # U+FFFE, illegal char
- "\xb2" . # bad tail
- "\xef" . # bad head
- "\x59";
- $expect = "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\xef\xbf\xbd" .
- "\x59";
- $this->assertEquals(
- bin2hex( $expect ),
- bin2hex( UtfNormal::cleanUp( $text ) ) );
- }
-
- /** @todo document */
- public function testForbiddenRegression() {
- $text = "\xef\xbf\xbf"; # U+FFFF, illegal char
- $expect = "\xef\xbf\xbd";
- $this->assertEquals(
- bin2hex( $expect ),
- bin2hex( UtfNormal::cleanUp( $text ) ) );
- }
-
- /** @todo document */
- public function testHangulRegression() {
- $text = "\xed\x9c\xaf" . # Hangul char
- "\xe1\x87\x81"; # followed by another final jamo
- $expect = $text; # Should *not* change.
- $this->assertEquals(
- bin2hex( $expect ),
- bin2hex( UtfNormal::cleanUp( $text ) ) );
- }
-}
diff --git a/tests/phpunit/includes/objectcache/BagOStuffTest.php b/tests/phpunit/includes/objectcache/BagOStuffTest.php
index 987b6e64..4516bb4e 100644
--- a/tests/phpunit/includes/objectcache/BagOStuffTest.php
+++ b/tests/phpunit/includes/objectcache/BagOStuffTest.php
@@ -1,8 +1,6 @@
<?php
/**
- * This class will test BagOStuff.
- *
- * @author Matthias Mullie <mmullie@wikimedia.org>
+ * @author Matthias Mullie <mmullie@wikimedia.org>
*/
class BagOStuffTest extends MediaWikiTestCase {
private $cache;
@@ -23,6 +21,10 @@ class BagOStuffTest extends MediaWikiTestCase {
$this->cache->delete( wfMemcKey( 'test' ) );
}
+ /**
+ * @covers BagOStuff::merge
+ * @covers BagOStuff::mergeViaLock
+ */
public function testMerge() {
$key = wfMemcKey( 'test' );
@@ -100,6 +102,9 @@ class BagOStuffTest extends MediaWikiTestCase {
}
}
+ /**
+ * @covers BagOStuff::add
+ */
public function testAdd() {
$key = wfMemcKey( 'test' );
$this->assertTrue( $this->cache->add( $key, 'test' ) );
@@ -125,6 +130,9 @@ class BagOStuffTest extends MediaWikiTestCase {
$this->assertEquals( $expectedValue, $actualValue, 'Value should be 1 after incrementing' );
}
+ /**
+ * @covers BagOStuff::getMulti
+ */
public function testGetMulti() {
$value1 = array( 'this' => 'is', 'a' => 'test' );
$value2 = array( 'this' => 'is', 'another' => 'test' );
diff --git a/tests/phpunit/includes/ArticleTablesTest.php b/tests/phpunit/includes/page/ArticleTablesTest.php
index 9f2b7a05..9f2b7a05 100644
--- a/tests/phpunit/includes/ArticleTablesTest.php
+++ b/tests/phpunit/includes/page/ArticleTablesTest.php
diff --git a/tests/phpunit/includes/ArticleTest.php b/tests/phpunit/includes/page/ArticleTest.php
index ae069eaf..ae069eaf 100644
--- a/tests/phpunit/includes/ArticleTest.php
+++ b/tests/phpunit/includes/page/ArticleTest.php
diff --git a/tests/phpunit/includes/ImagePage404Test.php b/tests/phpunit/includes/page/ImagePage404Test.php
index 197a2b32..197a2b32 100644
--- a/tests/phpunit/includes/ImagePage404Test.php
+++ b/tests/phpunit/includes/page/ImagePage404Test.php
diff --git a/tests/phpunit/includes/ImagePageTest.php b/tests/phpunit/includes/page/ImagePageTest.php
index 3c255b5f..3c255b5f 100644
--- a/tests/phpunit/includes/ImagePageTest.php
+++ b/tests/phpunit/includes/page/ImagePageTest.php
diff --git a/tests/phpunit/includes/WikiPageTest.php b/tests/phpunit/includes/page/WikiPageTest.php
index 7f7945b8..c011e9a9 100644
--- a/tests/phpunit/includes/WikiPageTest.php
+++ b/tests/phpunit/includes/page/WikiPageTest.php
@@ -55,8 +55,8 @@ class WikiPageTest extends MediaWikiLangTestCase {
}
/**
- * @param Title $title
- * @param string $model
+ * @param Title|string $title
+ * @param string|null $model
* @return WikiPage
*/
protected function newPage( $title, $model = null ) {
diff --git a/tests/phpunit/includes/WikiPageTestContentHandlerUseDB.php b/tests/phpunit/includes/page/WikiPageTestContentHandlerUseDB.php
index 3db76280..3db76280 100644
--- a/tests/phpunit/includes/WikiPageTestContentHandlerUseDB.php
+++ b/tests/phpunit/includes/page/WikiPageTestContentHandlerUseDB.php
diff --git a/tests/phpunit/includes/parser/NewParserTest.php b/tests/phpunit/includes/parser/NewParserTest.php
index 0df52f5e..91aad10c 100644
--- a/tests/phpunit/includes/parser/NewParserTest.php
+++ b/tests/phpunit/includes/parser/NewParserTest.php
@@ -124,7 +124,7 @@ class NewParserTest extends MediaWikiTestCase {
$tmpGlobals['wgFileExtensions'][] = 'svg';
$tmpGlobals['wgSVGConverter'] = 'rsvg';
$tmpGlobals['wgSVGConverters']['rsvg'] =
- '$path/rsvg-convert -w $width -h $height $input -o $output';
+ '$path/rsvg-convert -w $width -h $height -o $output $input';
if ( $GLOBALS['wgStyleDirectory'] === false ) {
$tmpGlobals['wgStyleDirectory'] = "$IP/skins";
@@ -160,9 +160,6 @@ class NewParserTest extends MediaWikiTestCase {
$this->djVuSupport = new DjVuSupport();
// Tidy support
$this->tidySupport = new TidySupport();
- // We always set 'wgUseTidy' to false when parsing, but certain
- // test-running modes still use tidy if available, so ensure
- // that the tidy-related options are all set to their defaults.
$tmpGlobals['wgUseTidy'] = false;
$tmpGlobals['wgAlwaysUseTidy'] = false;
$tmpGlobals['wgDebugTidy'] = false;
@@ -419,6 +416,7 @@ class NewParserTest extends MediaWikiTestCase {
'wgMathDirectory' => $uploadDir . '/math',
'wgDefaultLanguageVariant' => $variant,
'wgLinkHolderBatchSize' => $linkHolderBatchSize,
+ 'wgUseTidy' => isset( $opts['tidy'] ),
);
if ( $config ) {
@@ -434,7 +432,7 @@ class NewParserTest extends MediaWikiTestCase {
$this->savedGlobals = array();
/** @since 1.20 */
- wfRunHooks( 'ParserTestGlobals', array( &$settings ) );
+ Hooks::run( 'ParserTestGlobals', array( &$settings ) );
$langObj = Language::factory( $lang );
$settings['wgContLang'] = $langObj;
@@ -480,16 +478,16 @@ class NewParserTest extends MediaWikiTestCase {
*/
protected function getUploadDir() {
if ( $this->keepUploads ) {
+ // Don't use getNewTempDirectory() as this is meant to persist
$dir = wfTempDir() . '/mwParser-images';
if ( is_dir( $dir ) ) {
return $dir;
}
} else {
- $dir = wfTempDir() . "/mwParser-" . mt_rand() . "-images";
+ $dir = $this->getNewTempDirectory();
}
- // wfDebug( "Creating upload directory $dir\n" );
if ( file_exists( $dir ) ) {
wfDebug( "Already exists!\n" );
@@ -727,12 +725,21 @@ class NewParserTest extends MediaWikiTestCase {
. "Current configuration is:\n\$wgTexvc = '$wgTexvc'" );
}
}
+
if ( isset( $opts['djvu'] ) ) {
if ( !$this->djVuSupport->isEnabled() ) {
$this->markTestSkipped( "SKIPPED: djvu binaries do not exist or are not executable.\n" );
}
}
+ if ( isset( $opts['tidy'] ) ) {
+ if ( !$this->tidySupport->isEnabled() ) {
+ $this->markTestSkipped( "SKIPPED: tidy extension is not installed.\n" );
+ } else {
+ $options->setTidy( true );
+ }
+ }
+
if ( isset( $opts['pst'] ) ) {
$out = $parser->preSaveTransform( $input, $title, $user, $options );
} elseif ( isset( $opts['msg'] ) ) {
@@ -753,12 +760,7 @@ class NewParserTest extends MediaWikiTestCase {
$output->setTOCEnabled( !isset( $opts['notoc'] ) );
$out = $output->getText();
if ( isset( $opts['tidy'] ) ) {
- if ( !$this->tidySupport->isEnabled() ) {
- $this->markTestSkipped( "SKIPPED: tidy extension is not installed.\n" );
- } else {
- $out = MWTidy::tidy( $out );
- $out = preg_replace( '/\s+$/', '', $out );
- }
+ $out = preg_replace( '/\s+$/', '', $out );
}
if ( isset( $opts['showtitle'] ) ) {
@@ -769,6 +771,14 @@ class NewParserTest extends MediaWikiTestCase {
$out = "$title\n$out";
}
+ if ( isset( $opts['showindicators'] ) ) {
+ $indicators = '';
+ foreach ( $output->getIndicators() as $id => $content ) {
+ $indicators .= "$id=$content\n";
+ }
+ $out = $indicators . $out;
+ }
+
if ( isset( $opts['ill'] ) ) {
$out = implode( ' ', $output->getLanguageLinks() );
} elseif ( isset( $opts['cat'] ) ) {
@@ -939,7 +949,7 @@ class NewParserTest extends MediaWikiTestCase {
$class = $wgParserConf['class'];
$parser = new $class( array( 'preprocessorClass' => $preprocessor ) + $wgParserConf );
- wfRunHooks( 'ParserTestParser', array( &$parser ) );
+ Hooks::run( 'ParserTestParser', array( &$parser ) );
return $parser;
}
diff --git a/tests/phpunit/includes/parser/ParserOutputTest.php b/tests/phpunit/includes/parser/ParserOutputTest.php
index c024cee5..e660e096 100644
--- a/tests/phpunit/includes/parser/ParserOutputTest.php
+++ b/tests/phpunit/includes/parser/ParserOutputTest.php
@@ -1,5 +1,9 @@
<?php
+/**
+ * @group Database
+ * ^--- trigger DB shadowing because we are using Title magic
+ */
class ParserOutputTest extends MediaWikiTestCase {
public static function provideIsLinkInternal() {
@@ -84,4 +88,5 @@ class ParserOutputTest extends MediaWikiTestCase {
$this->assertEquals( $po->getProperty( 'foo' ), false );
$this->assertArrayNotHasKey( 'foo', $properties );
}
+
}
diff --git a/tests/phpunit/includes/parser/TagHooksTest.php b/tests/phpunit/includes/parser/TagHooksTest.php
index e3c4cc84..251da471 100644
--- a/tests/phpunit/includes/parser/TagHooksTest.php
+++ b/tests/phpunit/includes/parser/TagHooksTest.php
@@ -89,7 +89,7 @@ class TagHookTest extends MediaWikiTestCase {
global $wgParserConf, $wgContLang;
$parser = new Parser( $wgParserConf );
- $parser->setFunctionTagHook( $tag, array( $this, 'functionTagCallback' ), SFH_OBJECT_ARGS );
+ $parser->setFunctionTagHook( $tag, array( $this, 'functionTagCallback' ), Parser::SFH_OBJECT_ARGS );
$parser->parse(
"Foo<$tag>Bar</$tag>Baz",
Title::newFromText( 'Test' ),
diff --git a/tests/phpunit/includes/PasswordTest.php b/tests/phpunit/includes/password/PasswordTest.php
index ceb794b5..5ad8aca6 100644
--- a/tests/phpunit/includes/PasswordTest.php
+++ b/tests/phpunit/includes/password/PasswordTest.php
@@ -30,4 +30,10 @@ class PasswordTest extends MediaWikiTestCase {
$this->assertFalse( $invalid1->equals( $invalid2 ) );
}
+
+ public function testInvalidPlaintext() {
+ $invalid = User::getPasswordFactory()->newFromPlaintext( null );
+
+ $this->assertInstanceOf( 'InvalidPassword', $invalid );
+ }
}
diff --git a/tests/phpunit/includes/password/PasswordTestCase.php b/tests/phpunit/includes/password/PasswordTestCase.php
index ef16f1c4..9a142cbc 100644
--- a/tests/phpunit/includes/password/PasswordTestCase.php
+++ b/tests/phpunit/includes/password/PasswordTestCase.php
@@ -49,10 +49,13 @@ abstract class PasswordTestCase extends MediaWikiTestCase {
* An array of tests in the form of (bool, string, string), where the first
* element is whether the second parameter (a password hash) and the third
* parameter (a password) should match.
- *
* @return array
+ * @throws MWException
+ * @abstract
*/
- abstract public static function providePasswordTests();
+ public static function providePasswordTests() {
+ throw new MWException( "Not implemented" );
+ }
/**
* @dataProvider providePasswordTests
diff --git a/tests/phpunit/includes/registration/ExtensionProcessorTest.php b/tests/phpunit/includes/registration/ExtensionProcessorTest.php
new file mode 100644
index 00000000..8715711f
--- /dev/null
+++ b/tests/phpunit/includes/registration/ExtensionProcessorTest.php
@@ -0,0 +1,374 @@
+<?php
+
+class ExtensionProcessorTest extends MediaWikiTestCase {
+
+ private $dir;
+
+ public function setUp() {
+ parent::setUp();
+ $this->dir = __DIR__ . '/FooBar/extension.json';
+ }
+
+ /**
+ * 'name' is absolutely required
+ *
+ * @var array
+ */
+ static $default = array(
+ 'name' => 'FooBar',
+ );
+
+ /**
+ * @covers ExtensionProcessor::extractInfo
+ */
+ public function testExtractInfo() {
+ // Test that attributes that begin with @ are ignored
+ $processor = new ExtensionProcessor();
+ $processor->extractInfo( $this->dir, self::$default + array(
+ '@metadata' => array( 'foobarbaz' ),
+ 'AnAttribute' => array( 'omg' ),
+ 'AutoloadClasses' => array( 'FooBar' => 'includes/FooBar.php' ),
+ ) );
+
+ $extracted = $processor->getExtractedInfo();
+ $attributes = $extracted['attributes'];
+ $this->assertArrayHasKey( 'AnAttribute', $attributes );
+ $this->assertArrayNotHasKey( '@metadata', $attributes );
+ $this->assertArrayNotHasKey( 'AutoloadClasses', $attributes );
+ }
+
+ public static function provideRegisterHooks() {
+ return array(
+ // No hooks
+ array(
+ array(),
+ self::$default,
+ array(),
+ ),
+ // No current hooks, adding one for "FooBaz"
+ array(
+ array(),
+ array( 'Hooks' => array( 'FooBaz' => 'FooBazCallback' ) ) + self::$default,
+ array( 'FooBaz' => array( 'FooBazCallback' ) ),
+ ),
+ // Hook for "FooBaz", adding another one
+ array(
+ array( 'FooBaz' => array( 'PriorCallback' ) ),
+ array( 'Hooks' => array( 'FooBaz' => 'FooBazCallback' ) ) + self::$default,
+ array( 'FooBaz' => array( 'PriorCallback', 'FooBazCallback' ) ),
+ ),
+ // Hook for "BarBaz", adding one for "FooBaz"
+ array(
+ array( 'BarBaz' => array( 'BarBazCallback' ) ),
+ array( 'Hooks' => array( 'FooBaz' => 'FooBazCallback' ) ) + self::$default,
+ array(
+ 'BarBaz' => array( 'BarBazCallback' ),
+ 'FooBaz' => array( 'FooBazCallback' ),
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @covers ExtensionProcessor::extractHooks
+ * @dataProvider provideRegisterHooks
+ */
+ public function testRegisterHooks( $pre, $info, $expected ) {
+ $processor = new MockExtensionProcessor( array( 'wgHooks' => $pre ) );
+ $processor->extractInfo( $this->dir, $info );
+ $extracted = $processor->getExtractedInfo();
+ $this->assertEquals( $expected, $extracted['globals']['wgHooks'] );
+ }
+
+ /**
+ * @covers ExtensionProcessor::extractConfig
+ */
+ public function testExtractConfig() {
+ $processor = new ExtensionProcessor;
+ $info = array(
+ 'config' => array(
+ 'Bar' => 'somevalue',
+ 'Foo' => 10,
+ '@IGNORED' => 'yes',
+ ),
+ ) + self::$default;
+ $processor->extractInfo( $this->dir, $info );
+ $extracted = $processor->getExtractedInfo();
+ $this->assertEquals( 'somevalue', $extracted['globals']['wgBar'] );
+ $this->assertEquals( 10, $extracted['globals']['wgFoo'] );
+ $this->assertArrayNotHasKey( 'wg@IGNORED', $extracted['globals'] );
+ }
+
+ public static function provideExtracttExtensionMessagesFiles() {
+ $dir = __DIR__ . '/FooBar/';
+ return array(
+ array(
+ array( 'ExtensionMessagesFiles' => array( 'FooBarAlias' => 'FooBar.alias.php' ) ),
+ array( 'wgExtensionMessagesFiles' => array( 'FooBarAlias' => $dir . 'FooBar.alias.php' ) )
+ ),
+ array(
+ array(
+ 'ExtensionMessagesFiles' => array(
+ 'FooBarAlias' => 'FooBar.alias.php',
+ 'FooBarMagic' => 'FooBar.magic.i18n.php',
+ ),
+ ),
+ array(
+ 'wgExtensionMessagesFiles' => array(
+ 'FooBarAlias' => $dir . 'FooBar.alias.php',
+ 'FooBarMagic' => $dir . 'FooBar.magic.i18n.php',
+ ),
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @covers ExtensionProcessor::extracttExtensionMessagesFiles
+ * @dataProvider provideExtracttExtensionMessagesFiles
+ */
+ public function testExtracttExtensionMessagesFiles( $input, $expected ) {
+ $processor = new ExtensionProcessor();
+ $processor->extractInfo( $this->dir, $input + self::$default );
+ $out = $processor->getExtractedInfo();
+ foreach ( $expected as $key => $value ) {
+ $this->assertEquals( $value, $out['globals'][$key] );
+ }
+ }
+
+
+ public static function provideExtractMessagesDirs() {
+ $dir = __DIR__ . '/FooBar/';
+ return array(
+ array(
+ array( 'MessagesDirs' => array( 'VisualEditor' => 'i18n' ) ),
+ array( 'wgMessagesDirs' => array( 'VisualEditor' => array( $dir . 'i18n' ) ) )
+ ),
+ array(
+ array( 'MessagesDirs' => array( 'VisualEditor' => array( 'i18n', 'foobar' ) ) ),
+ array( 'wgMessagesDirs' => array( 'VisualEditor' => array( $dir . 'i18n', $dir . 'foobar' ) ) )
+ ),
+ );
+ }
+
+ /**
+ * @covers ExtensionProcessor::extractMessagesDirs
+ * @dataProvider provideExtractMessagesDirs
+ */
+ public function testExtractMessagesDirs( $input, $expected ) {
+ $processor = new ExtensionProcessor();
+ $processor->extractInfo( $this->dir, $input + self::$default );
+ $out = $processor->getExtractedInfo();
+ foreach ( $expected as $key => $value ) {
+ $this->assertEquals( $value, $out['globals'][$key] );
+ }
+ }
+
+ /**
+ * @covers ExtensionProcessor::extractResourceLoaderModules
+ * @dataProvider provideExtractResourceLoaderModules
+ */
+ public function testExtractResourceLoaderModules( $input, $expected ) {
+ $processor = new ExtensionProcessor();
+ $processor->extractInfo( $this->dir, $input + self::$default );
+ $out = $processor->getExtractedInfo();
+ foreach ( $expected as $key => $value ) {
+ $this->assertEquals( $value, $out['globals'][$key] );
+ }
+ }
+
+ public static function provideExtractResourceLoaderModules() {
+ $dir = __DIR__ . '/FooBar/';
+ return array(
+ // Generic module with localBasePath/remoteExtPath specified
+ array(
+ // Input
+ array(
+ 'ResourceModules' => array(
+ 'test.foo' => array(
+ 'styles' => 'foobar.js',
+ 'localBasePath' => '',
+ 'remoteExtPath' => 'FooBar',
+ ),
+ ),
+ ),
+ // Expected
+ array(
+ 'wgResourceModules' => array(
+ 'test.foo' => array(
+ 'styles' => 'foobar.js',
+ 'localBasePath' => $dir,
+ 'remoteExtPath' => 'FooBar',
+ ),
+ ),
+ ),
+ ),
+ // ResourceFileModulePaths specified:
+ array(
+ // Input
+ array(
+ 'ResourceFileModulePaths' => array(
+ 'localBasePath' => '',
+ 'remoteExtPath' => 'FooBar',
+ ),
+ 'ResourceModules' => array(
+ // No paths
+ 'test.foo' => array(
+ 'styles' => 'foo.js',
+ ),
+ // Different paths set
+ 'test.bar' => array(
+ 'styles' => 'bar.js',
+ 'localBasePath' => 'subdir',
+ 'remoteExtPath' => 'FooBar/subdir',
+ ),
+ // Custom class with no paths set
+ 'test.class' => array(
+ 'class' => 'FooBarModule',
+ 'extra' => 'argument',
+ ),
+ // Custom class with a localBasePath
+ 'test.class.with.path' => array(
+ 'class' => 'FooBarPathModule',
+ 'extra' => 'argument',
+ 'localBasePath' => '',
+ )
+ ),
+ ),
+ // Expected
+ array(
+ 'wgResourceModules' => array(
+ 'test.foo' => array(
+ 'styles' => 'foo.js',
+ 'localBasePath' => $dir,
+ 'remoteExtPath' => 'FooBar',
+ ),
+ 'test.bar' => array(
+ 'styles' => 'bar.js',
+ 'localBasePath' => $dir . 'subdir',
+ 'remoteExtPath' => 'FooBar/subdir',
+ ),
+ 'test.class' => array(
+ 'class' => 'FooBarModule',
+ 'extra' => 'argument',
+ 'localBasePath' => $dir,
+ 'remoteExtPath' => 'FooBar',
+ ),
+ 'test.class.with.path' => array(
+ 'class' => 'FooBarPathModule',
+ 'extra' => 'argument',
+ 'localBasePath' => $dir,
+ 'remoteExtPath' => 'FooBar',
+ )
+ ),
+ ),
+ ),
+ // ResourceModuleSkinStyles with file module paths
+ array(
+ // Input
+ array(
+ 'ResourceFileModulePaths' => array(
+ 'localBasePath' => '',
+ 'remoteSkinPath' => 'FooBar',
+ ),
+ 'ResourceModuleSkinStyles' => array(
+ 'foobar' => array(
+ 'test.foo' => 'foo.css',
+ )
+ ),
+ ),
+ // Expected
+ array(
+ 'wgResourceModuleSkinStyles' => array(
+ 'foobar' => array(
+ 'test.foo' => 'foo.css',
+ 'localBasePath' => $dir,
+ 'remoteSkinPath' => 'FooBar',
+ ),
+ ),
+ ),
+ ),
+ // ResourceModuleSkinStyles with file module paths and an override
+ array(
+ // Input
+ array(
+ 'ResourceFileModulePaths' => array(
+ 'localBasePath' => '',
+ 'remoteSkinPath' => 'FooBar',
+ ),
+ 'ResourceModuleSkinStyles' => array(
+ 'foobar' => array(
+ 'test.foo' => 'foo.css',
+ 'remoteSkinPath' => 'BarFoo'
+ ),
+ ),
+ ),
+ // Expected
+ array(
+ 'wgResourceModuleSkinStyles' => array(
+ 'foobar' => array(
+ 'test.foo' => 'foo.css',
+ 'localBasePath' => $dir,
+ 'remoteSkinPath' => 'BarFoo',
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ public static function provideSetToGlobal() {
+ return array(
+ array(
+ array( 'wgAPIModules', 'wgAvailableRights' ),
+ array(),
+ array(
+ 'APIModules' => array( 'foobar' => 'ApiFooBar' ),
+ 'AvailableRights' => array( 'foobar', 'unfoobar' ),
+ ),
+ array(
+ 'wgAPIModules' => array( 'foobar' => 'ApiFooBar' ),
+ 'wgAvailableRights' => array( 'foobar', 'unfoobar' ),
+ ),
+ ),
+ array(
+ array( 'wgAPIModules', 'wgAvailableRights' ),
+ array(
+ 'wgAPIModules' => array( 'barbaz' => 'ApiBarBaz' ),
+ 'wgAvailableRights' => array( 'barbaz' )
+ ),
+ array(
+ 'APIModules' => array( 'foobar' => 'ApiFooBar' ),
+ 'AvailableRights' => array( 'foobar', 'unfoobar' ),
+ ),
+ array(
+ 'wgAPIModules' => array( 'barbaz' => 'ApiBarBaz', 'foobar' => 'ApiFooBar' ),
+ 'wgAvailableRights' => array( 'barbaz', 'foobar', 'unfoobar' ),
+ ),
+ ),
+ array(
+ array( 'wgGroupPermissions' ),
+ array(
+ 'wgGroupPermissions' => array( 'sysop' => array( 'delete' ) ),
+ ),
+ array(
+ 'GroupPermissions' => array( 'sysop' => array( 'undelete' ), 'user' => array( 'edit' ) ),
+ ),
+ array(
+ 'wgGroupPermissions' => array( 'sysop' => array( 'delete', 'undelete' ), 'user' => array( 'edit' ) ),
+ )
+ )
+ );
+ }
+}
+
+
+/**
+ * Allow overriding the default value of $this->globals
+ * so we can test merging
+ */
+class MockExtensionProcessor extends ExtensionProcessor {
+ public function __construct( $globals = array() ) {
+ $this->globals = $globals + $this->globals;
+ }
+}
diff --git a/tests/phpunit/includes/registration/ExtensionRegistryTest.php b/tests/phpunit/includes/registration/ExtensionRegistryTest.php
new file mode 100644
index 00000000..1b24628c
--- /dev/null
+++ b/tests/phpunit/includes/registration/ExtensionRegistryTest.php
@@ -0,0 +1,195 @@
+<?php
+
+class ExtensionRegistryTest extends MediaWikiTestCase {
+
+ /**
+ * @covers ExtensionRegistry::exportExtractedData
+ * @dataProvider provideExportExtractedDataGlobals
+ */
+ public function testExportExtractedDataGlobals( $desc, $before, $globals, $expected ) {
+ // Set globals for test
+ if ( $before ) {
+ foreach ( $before as $key => $value ) {
+ // mw prefixed globals does not exist normally
+ if ( substr( $key, 0, 2 ) == 'mw' ) {
+ $GLOBALS[$key] = $value;
+ } else {
+ $this->setMwGlobals( $key, $value );
+ }
+ }
+ }
+
+ $info = array(
+ 'globals' => $globals,
+ 'callbacks' => array(),
+ 'defines' => array(),
+ 'credits' => array(),
+ 'attributes' => array(),
+ );
+ $registry = new ExtensionRegistry();
+ $class = new ReflectionClass( 'ExtensionRegistry' );
+ $method = $class->getMethod( 'exportExtractedData' );
+ $method->setAccessible( true );
+ $method->invokeArgs( $registry, array( $info ) );
+ foreach ( $expected as $name => $value ) {
+ $this->assertArrayHasKey( $name, $GLOBALS, $desc );
+ $this->assertEquals( $value, $GLOBALS[$name], $desc );
+ }
+
+ // Remove mw prefixed globals
+ if ( $before ) {
+ foreach ( $before as $key => $value ) {
+ if ( substr( $key, 0, 2 ) == 'mw' ) {
+ unset( $GLOBALS[$key] );
+ }
+ }
+ }
+ }
+
+ public static function provideExportExtractedDataGlobals() {
+ // "mwtest" prefix used instead of "$wg" to avoid potential conflicts
+ return array(
+ array(
+ 'Simple non-array values',
+ array(
+ 'mwtestFooBarConfig' => true,
+ 'mwtestFooBarConfig2' => 'string',
+ ),
+ array(
+ 'mwtestFooBarDefault' => 1234,
+ 'mwtestFooBarConfig' => false,
+ ),
+ array(
+ 'mwtestFooBarConfig' => true,
+ 'mwtestFooBarConfig2' => 'string',
+ 'mwtestFooBarDefault' => 1234,
+ ),
+ ),
+ array(
+ 'No global already set, simple array',
+ null,
+ array(
+ 'mwtestDefaultOptions' => array(
+ 'foobar' => true,
+ )
+ ),
+ array(
+ 'mwtestDefaultOptions' => array(
+ 'foobar' => true,
+ )
+ ),
+ ),
+ array(
+ 'Global already set, simple array',
+ array(
+ 'mwtestDefaultOptions' => array(
+ 'foobar' => true,
+ 'foo' => 'string'
+ ),
+ ),
+ array(
+ 'mwtestDefaultOptions' => array(
+ 'barbaz' => 12345,
+ 'foobar' => false,
+ ),
+ ),
+ array(
+ 'mwtestDefaultOptions' => array(
+ 'barbaz' => 12345,
+ 'foo' => 'string',
+ 'foobar' => true,
+ ),
+ )
+ ),
+ array(
+ 'No global already set, $wgHooks',
+ array(
+ 'wgHooks' => array(),
+ ),
+ array(
+ 'wgHooks' => array(
+ 'FooBarEvent' => array(
+ 'FooBarClass::onFooBarEvent'
+ ),
+ ),
+ ),
+ array(
+ 'wgHooks' => array(
+ 'FooBarEvent' => array(
+ 'FooBarClass::onFooBarEvent'
+ ),
+ ),
+ ),
+ ),
+ array(
+ 'Global already set, $wgHooks',
+ array(
+ 'wgHooks' => array(
+ 'FooBarEvent' => array(
+ 'FooBarClass::onFooBarEvent'
+ ),
+ 'BazBarEvent' => array(
+ 'FooBarClass::onBazBarEvent',
+ ),
+ ),
+ ),
+ array(
+ 'wgHooks' => array(
+ 'FooBarEvent' => array(
+ 'BazBarClass::onFooBarEvent',
+ ),
+ ),
+ ),
+ array(
+ 'wgHooks' => array(
+ 'FooBarEvent' => array(
+ 'FooBarClass::onFooBarEvent',
+ 'BazBarClass::onFooBarEvent',
+ ),
+ 'BazBarEvent' => array(
+ 'FooBarClass::onBazBarEvent',
+ ),
+ ),
+ ),
+ ),
+ array(
+ 'Global already set, $wgGroupPermissions',
+ array(
+ 'wgGroupPermissions' => array(
+ 'sysop' => array(
+ 'something' => true,
+ ),
+ 'user' => array(
+ 'somethingtwo' => true,
+ )
+ ),
+ ),
+ array(
+ 'wgGroupPermissions' => array(
+ 'customgroup' => array(
+ 'right' => true,
+ ),
+ 'user' => array(
+ 'right' => true,
+ 'somethingtwo' => false,
+ )
+ ),
+ ),
+ array(
+ 'wgGroupPermissions' => array(
+ 'customgroup' => array(
+ 'right' => true,
+ ),
+ 'sysop' => array(
+ 'something' => true,
+ ),
+ 'user' => array(
+ 'somethingtwo' => true,
+ 'right' => true,
+ )
+ ),
+ ),
+ )
+ );
+ }
+}
diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php
new file mode 100644
index 00000000..122995a5
--- /dev/null
+++ b/tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php
@@ -0,0 +1,247 @@
+<?php
+
+/**
+ * @group ResourceLoader
+ */
+class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
+
+ protected function setUp() {
+ parent::setUp();
+
+ // The return value of the closure shouldn't matter since this test should
+ // never call it
+ SkinFactory::getDefaultInstance()->register(
+ 'fakeskin',
+ 'FakeSkin',
+ function () {
+ }
+ );
+ }
+
+ private static function getModules() {
+ $base = array(
+ 'localBasePath' => realpath( dirname( __FILE__ ) ),
+ );
+
+ return array(
+ 'noTemplateModule' => array(),
+
+ 'htmlTemplateModule' => $base + array(
+ 'templates' => array(
+ 'templates/template.html',
+ 'templates/template2.html',
+ )
+ ),
+
+ 'aliasedHtmlTemplateModule' => $base + array(
+ 'templates' => array(
+ 'foo.html' => 'templates/template.html',
+ 'bar.html' => 'templates/template2.html',
+ )
+ ),
+
+ 'templateModuleHandlebars' => $base + array(
+ 'templates' => array(
+ 'templates/template_awesome.handlebars',
+ ),
+ ),
+
+ 'aliasFooFromBar' => $base + array(
+ 'templates' => array(
+ 'foo.foo' => 'templates/template.bar',
+ ),
+ ),
+ );
+ }
+
+ public static function providerTemplateDependencies() {
+ $modules = self::getModules();
+
+ return array(
+ array(
+ $modules['noTemplateModule'],
+ array(),
+ ),
+ array(
+ $modules['htmlTemplateModule'],
+ array(
+ 'mediawiki.template',
+ ),
+ ),
+ array(
+ $modules['templateModuleHandlebars'],
+ array(
+ 'mediawiki.template',
+ 'mediawiki.template.handlebars',
+ ),
+ ),
+ array(
+ $modules['aliasFooFromBar'],
+ array(
+ 'mediawiki.template',
+ 'mediawiki.template.foo',
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider providerTemplateDependencies
+ * @covers ResourceLoaderFileModule::__construct
+ * @covers ResourceLoaderFileModule::getDependencies
+ */
+ public function testTemplateDependencies( $module, $expected ) {
+ $rl = new ResourceLoaderFileModule( $module );
+ $this->assertEquals( $rl->getDependencies(), $expected );
+ }
+
+ /**
+ * @covers ResourceLoaderFileModule::getAllStyleFiles
+ * @covers ResourceLoaderFileModule::getAllSkinStyleFiles
+ * @covers ResourceLoaderFileModule::getSkinStyleFiles
+ */
+ public function testGetAllSkinStyleFiles() {
+ $baseParams = array(
+ 'scripts' => array(
+ 'foo.js',
+ 'bar.js',
+ ),
+ 'styles' => array(
+ 'foo.css',
+ 'bar.css' => array( 'media' => 'print' ),
+ 'screen.less' => array( 'media' => 'screen' ),
+ 'screen-query.css' => array( 'media' => 'screen and (min-width: 400px)' ),
+ ),
+ 'skinStyles' => array(
+ 'default' => 'quux-fallback.less',
+ 'fakeskin' => array(
+ 'baz-vector.css',
+ 'quux-vector.less',
+ ),
+ ),
+ 'messages' => array(
+ 'hello',
+ 'world',
+ ),
+ );
+
+ $module = new ResourceLoaderFileModule( $baseParams );
+
+ $this->assertEquals(
+ array(
+ 'foo.css',
+ 'baz-vector.css',
+ 'quux-vector.less',
+ 'quux-fallback.less',
+ 'bar.css',
+ 'screen.less',
+ 'screen-query.css',
+ ),
+ array_map( 'basename', $module->getAllStyleFiles() )
+ );
+ }
+
+ /**
+ * Strip @noflip annotations from CSS code.
+ * @param string $css
+ * @return string
+ */
+ private static function stripNoflip( $css ) {
+ return str_replace( '/*@noflip*/ ', '', $css );
+ }
+
+ /**
+ * What happens when you mix @embed and @noflip?
+ * This really is an integration test, but oh well.
+ *
+ * @covers ResourceLoaderFileModule::getStyles
+ * @covers ResourceLoaderFileModule::getStyleFiles
+ */
+ public function testMixedCssAnnotations( ) {
+ $basePath = __DIR__ . '/../../data/css';
+ $testModule = new ResourceLoaderFileModule( array(
+ 'localBasePath' => $basePath,
+ 'styles' => array( 'test.css' ),
+ ) );
+ $expectedModule = new ResourceLoaderFileModule( array(
+ 'localBasePath' => $basePath,
+ 'styles' => array( 'expected.css' ),
+ ) );
+
+ $contextLtr = $this->getResourceLoaderContext( 'en', 'ltr' );
+ $contextRtl = $this->getResourceLoaderContext( 'he', 'rtl' );
+
+ // Since we want to compare the effect of @noflip+@embed against the effect of just @embed, and
+ // the @noflip annotations are always preserved, we need to strip them first.
+ $this->assertEquals(
+ $expectedModule->getStyles( $contextLtr ),
+ self::stripNoflip( $testModule->getStyles( $contextLtr ) ),
+ "/*@noflip*/ with /*@embed*/ gives correct results in LTR mode"
+ );
+ $this->assertEquals(
+ $expectedModule->getStyles( $contextLtr ),
+ self::stripNoflip( $testModule->getStyles( $contextRtl ) ),
+ "/*@noflip*/ with /*@embed*/ gives correct results in RTL mode"
+ );
+ }
+
+ public static function providerGetTemplates() {
+ $modules = self::getModules();
+
+ return array(
+ array(
+ $modules['noTemplateModule'],
+ array(),
+ ),
+ array(
+ $modules['templateModuleHandlebars'],
+ array(
+ 'templates/template_awesome.handlebars' => "wow\n",
+ ),
+ ),
+ array(
+ $modules['htmlTemplateModule'],
+ array(
+ 'templates/template.html' => "<strong>hello</strong>\n",
+ 'templates/template2.html' => "<div>goodbye</div>\n",
+ ),
+ ),
+ array(
+ $modules['aliasedHtmlTemplateModule'],
+ array(
+ 'foo.html' => "<strong>hello</strong>\n",
+ 'bar.html' => "<div>goodbye</div>\n",
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider providerGetTemplates
+ * @covers ResourceLoaderFileModule::getTemplates
+ */
+ public function testGetTemplates( $module, $expected ) {
+ $rl = new ResourceLoaderFileModule( $module );
+
+ $this->assertEquals( $rl->getTemplates(), $expected );
+ }
+
+ public static function providerGetModifiedTime() {
+ $modules = self::getModules();
+
+ return array(
+ // Check the default value when no templates present in module is 1
+ array( $modules['noTemplateModule'], 1 ),
+ );
+ }
+
+ /**
+ * @dataProvider providerGetModifiedTime
+ * @covers ResourceLoaderFileModule::getModifiedTime
+ */
+ public function testGetModifiedTime( $module, $expected ) {
+ $rl = new ResourceLoaderFileModule( $module );
+ $ts = $rl->getModifiedTime( $this->getResourceLoaderContext() );
+ $this->assertEquals( $ts, $expected );
+ }
+}
diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderImageModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderImageModuleTest.php
new file mode 100644
index 00000000..d0bc210b
--- /dev/null
+++ b/tests/phpunit/includes/resourceloader/ResourceLoaderImageModuleTest.php
@@ -0,0 +1,162 @@
+<?php
+
+/**
+ * @group ResourceLoader
+ */
+class ResourceLoaderImageModuleTest extends ResourceLoaderTestCase {
+
+ public static $commonImageData = array(
+ 'add' => 'add.gif',
+ 'remove' => array(
+ 'file' => 'remove.svg',
+ 'variants' => array( 'destructive' ),
+ ),
+ 'next' => array(
+ 'file' => array(
+ 'ltr' => 'next.svg',
+ 'rtl' => 'prev.svg'
+ ),
+ ),
+ 'help' => array(
+ 'file' => array(
+ 'ltr' => 'help-ltr.svg',
+ 'rtl' => 'help-rtl.svg',
+ 'lang' => array(
+ 'he' => 'help-ltr.svg',
+ )
+ ),
+ ),
+ 'bold' => array(
+ 'file' => array(
+ 'default' => 'bold-a.svg',
+ 'lang' => array(
+ 'en' => 'bold-b.svg',
+ 'ar,de' => 'bold-f.svg',
+ )
+ ),
+ )
+ );
+
+ public static $commonImageVariants = array(
+ 'invert' => array(
+ 'color' => '#FFFFFF',
+ 'global' => true,
+ ),
+ 'primary' => array(
+ 'color' => '#598AD1',
+ ),
+ 'constructive' => array(
+ 'color' => '#00C697',
+ ),
+ 'destructive' => array(
+ 'color' => '#E81915',
+ ),
+ );
+
+ public static function providerGetModules() {
+ return array(
+ array(
+ array(
+ 'class' => 'ResourceLoaderImageModule',
+ 'prefix' => 'oo-ui-icon',
+ 'variants' => self::$commonImageVariants,
+ 'images' => self::$commonImageData,
+ ),
+ '.oo-ui-icon-add {
+ ...
+}
+.oo-ui-icon-add-invert {
+ ...
+}
+.oo-ui-icon-remove {
+ ...
+}
+.oo-ui-icon-remove-invert {
+ ...
+}
+.oo-ui-icon-remove-destructive {
+ ...
+}
+.oo-ui-icon-next {
+ ...
+}
+.oo-ui-icon-next-invert {
+ ...
+}
+.oo-ui-icon-help {
+ ...
+}
+.oo-ui-icon-help-invert {
+ ...
+}
+.oo-ui-icon-bold {
+ ...
+}
+.oo-ui-icon-bold-invert {
+ ...
+}',
+ ),
+ array(
+ array(
+ 'class' => 'ResourceLoaderImageModule',
+ 'selectorWithoutVariant' => '.mw-ui-icon-{name}:after, .mw-ui-icon-{name}:before',
+ 'selectorWithVariant' => '.mw-ui-icon-{name}-{variant}:after, .mw-ui-icon-{name}-{variant}:before',
+ 'variants' => self::$commonImageVariants,
+ 'images' => self::$commonImageData,
+ ),
+ '.mw-ui-icon-add:after, .mw-ui-icon-add:before {
+ ...
+}
+.mw-ui-icon-add-invert:after, .mw-ui-icon-add-invert:before {
+ ...
+}
+.mw-ui-icon-remove:after, .mw-ui-icon-remove:before {
+ ...
+}
+.mw-ui-icon-remove-invert:after, .mw-ui-icon-remove-invert:before {
+ ...
+}
+.mw-ui-icon-remove-destructive:after, .mw-ui-icon-remove-destructive:before {
+ ...
+}
+.mw-ui-icon-next:after, .mw-ui-icon-next:before {
+ ...
+}
+.mw-ui-icon-next-invert:after, .mw-ui-icon-next-invert:before {
+ ...
+}
+.mw-ui-icon-help:after, .mw-ui-icon-help:before {
+ ...
+}
+.mw-ui-icon-help-invert:after, .mw-ui-icon-help-invert:before {
+ ...
+}
+.mw-ui-icon-bold:after, .mw-ui-icon-bold:before {
+ ...
+}
+.mw-ui-icon-bold-invert:after, .mw-ui-icon-bold-invert:before {
+ ...
+}',
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider providerGetModules
+ * @covers ResourceLoaderImageModule::getStyles
+ */
+ public function testGetStyles( $module, $expected ) {
+ $module = new ResourceLoaderImageModuleTestable( $module, __DIR__ . '/../../data/resourceloader' );
+ $styles = $module->getStyles( $this->getResourceLoaderContext() );
+ $this->assertEquals( $expected, $styles['all'] );
+ }
+}
+
+class ResourceLoaderImageModuleTestable extends ResourceLoaderImageModule {
+ /**
+ * Replace with a stub to make test cases easier to write.
+ */
+ protected function getCssDeclarations( $primary, $fallback ) {
+ return array( '...' );
+ }
+}
diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderImageTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderImageTest.php
new file mode 100644
index 00000000..758cfe19
--- /dev/null
+++ b/tests/phpunit/includes/resourceloader/ResourceLoaderImageTest.php
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * @group ResourceLoader
+ */
+class ResourceLoaderImageTest extends ResourceLoaderTestCase {
+
+ protected $imagesPath;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->imagesPath = __DIR__ . '/../../data/resourceloader';
+ }
+
+ protected function getTestImage( $name ) {
+ $options = ResourceLoaderImageModuleTest::$commonImageData[$name];
+ $fileDescriptor = is_string( $options ) ? $options : $options['file'];
+ $allowedVariants = is_array( $options ) && isset( $options['variants'] ) ? $options['variants'] : array();
+ $variants = array_fill_keys( $allowedVariants, array( 'color' => 'red' ) );
+ return new ResourceLoaderImageTestable( $name, 'test', $fileDescriptor, $this->imagesPath, $variants );
+ }
+
+ public static function provideGetPath() {
+ return array(
+ array( 'add', 'en', 'add.gif' ),
+ array( 'add', 'he', 'add.gif' ),
+ array( 'remove', 'en', 'remove.svg' ),
+ array( 'remove', 'he', 'remove.svg' ),
+ array( 'next', 'en', 'next.svg' ),
+ array( 'next', 'he', 'prev.svg' ),
+ array( 'help', 'en', 'help-ltr.svg' ),
+ array( 'help', 'ar', 'help-rtl.svg' ),
+ array( 'help', 'he', 'help-ltr.svg' ),
+ array( 'bold', 'en', 'bold-b.svg' ),
+ array( 'bold', 'de', 'bold-f.svg' ),
+ array( 'bold', 'ar', 'bold-f.svg' ),
+ array( 'bold', 'fr', 'bold-a.svg' ),
+ array( 'bold', 'he', 'bold-a.svg' ),
+ );
+ }
+
+ /**
+ * @covers ResourceLoaderImage::getPath
+ * @dataProvider provideGetPath
+ */
+ public function testGetPath( $imageName, $languageCode, $path ) {
+ static $dirMap = array(
+ 'en' => 'ltr',
+ 'de' => 'ltr',
+ 'fr' => 'ltr',
+ 'he' => 'rtl',
+ 'ar' => 'rtl',
+ );
+ static $contexts = array();
+
+ $image = $this->getTestImage( $imageName );
+ $context = $this->getResourceLoaderContext( $languageCode, $dirMap[$languageCode] );
+
+ $this->assertEquals( $image->getPath( $context ), $this->imagesPath . '/' . $path );
+ }
+
+ /**
+ * @covers ResourceLoaderImage::getExtension
+ * @covers ResourceLoaderImage::getMimeType
+ */
+ public function testGetExtension() {
+ $image = $this->getTestImage( 'remove' );
+ $this->assertEquals( $image->getExtension(), 'svg' );
+ $this->assertEquals( $image->getExtension( 'original' ), 'svg' );
+ $this->assertEquals( $image->getExtension( 'rasterized' ), 'png' );
+ $image = $this->getTestImage( 'add' );
+ $this->assertEquals( $image->getExtension(), 'gif' );
+ $this->assertEquals( $image->getExtension( 'original' ), 'gif' );
+ $this->assertEquals( $image->getExtension( 'rasterized' ), 'gif' );
+ }
+
+ /**
+ * @covers ResourceLoaderImage::getImageData
+ * @covers ResourceLoaderImage::variantize
+ * @covers ResourceLoaderImage::massageSvgPathdata
+ */
+ public function testGetImageData() {
+ $context = $this->getResourceLoaderContext( 'en', 'ltr' );
+
+ $image = $this->getTestImage( 'remove' );
+ $data = file_get_contents( $this->imagesPath . '/remove.svg' );
+ $dataConstructive = file_get_contents( $this->imagesPath . '/remove_variantize.svg' );
+ $this->assertEquals( $image->getImageData( $context, null, 'original' ), $data );
+ $this->assertEquals( $image->getImageData( $context, 'destructive', 'original' ), $dataConstructive );
+ // Stub, since we don't know if we even have a SVG handler, much less what exactly it'll output
+ $this->assertEquals( $image->getImageData( $context, null, 'rasterized' ), 'RASTERIZESTUB' );
+
+ $image = $this->getTestImage( 'add' );
+ $data = file_get_contents( $this->imagesPath . '/add.gif' );
+ $this->assertEquals( $image->getImageData( $context, null, 'original' ), $data );
+ $this->assertEquals( $image->getImageData( $context, null, 'rasterized' ), $data );
+ }
+
+ /**
+ * @covers ResourceLoaderImage::massageSvgPathdata
+ */
+ public function testMassageSvgPathdata() {
+ $image = $this->getTestImage( 'next' );
+ $data = file_get_contents( $this->imagesPath . '/next.svg' );
+ $dataMassaged = file_get_contents( $this->imagesPath . '/next_massage.svg' );
+ $this->assertEquals( $image->massageSvgPathdata( $data ), $dataMassaged );
+ }
+}
+
+class ResourceLoaderImageTestable extends ResourceLoaderImage {
+ // Make some protected methods public
+ public function getPath( ResourceLoaderContext $context ) {
+ return parent::getPath( $context );
+ }
+ public function massageSvgPathdata( $svg ) {
+ return parent::massageSvgPathdata( $svg );
+ }
+ // Stub, since we don't know if we even have a SVG handler, much less what exactly it'll output
+ public function rasterize( $svg ) {
+ return 'RASTERIZESTUB';
+ }
+}
diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php
index b0edaaf7..6d1ed4e0 100644
--- a/tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php
+++ b/tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php
@@ -2,71 +2,12 @@
class ResourceLoaderModuleTest extends ResourceLoaderTestCase {
- protected function setUp() {
- parent::setUp();
-
- // The return value of the closure shouldn't matter since this test should
- // never call it
- SkinFactory::getDefaultInstance()->register(
- 'fakeskin',
- 'FakeSkin',
- function () {
- }
- );
- }
-
- /**
- * @covers ResourceLoaderFileModule::getAllSkinStyleFiles
- */
- public function testGetAllSkinStyleFiles() {
- $context = self::getResourceLoaderContext();
-
- $baseParams = array(
- 'scripts' => array(
- 'foo.js',
- 'bar.js',
- ),
- 'styles' => array(
- 'foo.css',
- 'bar.css' => array( 'media' => 'print' ),
- 'screen.less' => array( 'media' => 'screen' ),
- 'screen-query.css' => array( 'media' => 'screen and (min-width: 400px)' ),
- ),
- 'skinStyles' => array(
- 'default' => 'quux-fallback.less',
- 'fakeskin' => array(
- 'baz-vector.css',
- 'quux-vector.less',
- ),
- ),
- 'messages' => array(
- 'hello',
- 'world',
- ),
- );
-
- $module = new ResourceLoaderFileModule( $baseParams );
-
- $this->assertEquals(
- array(
- 'foo.css',
- 'baz-vector.css',
- 'quux-vector.less',
- 'quux-fallback.less',
- 'bar.css',
- 'screen.less',
- 'screen-query.css',
- ),
- array_map( 'basename', $module->getAllStyleFiles() )
- );
- }
-
/**
* @covers ResourceLoaderModule::getDefinitionSummary
* @covers ResourceLoaderFileModule::getDefinitionSummary
*/
public function testDefinitionSummary() {
- $context = self::getResourceLoaderContext();
+ $context = $this->getResourceLoaderContext();
$baseParams = array(
'scripts' => array( 'foo.js', 'bar.js' ),
diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderStartupModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php
index a1893873..7f3506cc 100644
--- a/tests/phpunit/includes/resourceloader/ResourceLoaderStartupModuleTest.php
+++ b/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php
@@ -1,6 +1,6 @@
<?php
-class ResourceLoaderStartupModuleTest extends ResourceLoaderTestCase {
+class ResourceLoaderStartUpModuleTest extends ResourceLoaderTestCase {
public static function provideGetModuleRegistrations() {
return array(
@@ -23,7 +23,7 @@ mw.loader.addSource( {
} );mw.loader.register( [
[
"test.blank",
- "1388534400"
+ 1388534400
]
] );',
) ),
@@ -40,17 +40,17 @@ mw.loader.addSource( {
} );mw.loader.register( [
[
"test.blank",
- "1388534400"
+ 1388534400
],
[
"test.group.foo",
- "1388534400",
+ 1388534400,
[],
"x-foo"
],
[
"test.group.bar",
- "1388534400",
+ 1388534400,
[],
"x-bar"
]
@@ -68,7 +68,7 @@ mw.loader.addSource( {
} );mw.loader.register( [
[
"test.blank",
- "1388534400"
+ 1388534400
]
] );'
) ),
@@ -90,7 +90,7 @@ mw.loader.addSource( {
} );mw.loader.register( [
[
"test.blank",
- "1388534400",
+ 1388534400,
[],
null,
"example"
@@ -115,8 +115,8 @@ mw.loader.addSource( {
'test.z.foo' => new ResourceLoaderTestModule( array(
'dependencies' => array(
'test.x.core',
- 'test.x.polyfil',
- 'test.y.polyfil',
+ 'test.x.polyfill',
+ 'test.y.polyfill',
),
) ),
),
@@ -126,31 +126,31 @@ mw.loader.addSource( {
} );mw.loader.register( [
[
"test.x.core",
- "1388534400"
+ 1388534400
],
[
"test.x.polyfill",
- "1388534400",
+ 1388534400,
[],
null,
- "local",
+ null,
"return true;"
],
[
"test.y.polyfill",
- "1388534400",
+ 1388534400,
[],
null,
- "local",
+ null,
"return !!( window.JSON \u0026\u0026 JSON.parse \u0026\u0026 JSON.stringify);"
],
[
"test.z.foo",
- "1388534400",
+ 1388534400,
[
- "test.x.core",
- "test.x.polyfil",
- "test.y.polyfil"
+ 0,
+ 1,
+ 2
]
]
] );',
@@ -222,63 +222,63 @@ mw.loader.addSource( {
} );mw.loader.register( [
[
"test.blank",
- "1388534400"
+ 1388534400
],
[
"test.x.core",
- "1388534400"
+ 1388534400
],
[
"test.x.util",
- "1388534400",
+ 1388534400,
[
- "test.x.core"
+ 1
]
],
[
"test.x.foo",
- "1388534400",
+ 1388534400,
[
- "test.x.core"
+ 1
]
],
[
"test.x.bar",
- "1388534400",
+ 1388534400,
[
- "test.x.util"
+ 2
]
],
[
"test.x.quux",
- "1388534400",
+ 1388534400,
[
- "test.x.foo",
- "test.x.bar",
+ 3,
+ 4,
"test.x.unknown"
]
],
[
"test.group.foo.1",
- "1388534400",
+ 1388534400,
[],
"x-foo"
],
[
"test.group.foo.2",
- "1388534400",
+ 1388534400,
[],
"x-foo"
],
[
"test.group.bar.1",
- "1388534400",
+ 1388534400,
[],
"x-bar"
],
[
"test.group.bar.2",
- "1388534400",
+ 1388534400,
[],
"x-bar",
"example"
@@ -290,7 +290,7 @@ mw.loader.addSource( {
/**
* @dataProvider provideGetModuleRegistrations
- * @covers ResourceLoaderStartupModule::optimizeDependencies
+ * @covers ResourceLoaderStartUpModule::compileUnresolvedDependencies
* @covers ResourceLoaderStartUpModule::getModuleRegistrations
* @covers ResourceLoader::makeLoaderSourcesScript
* @covers ResourceLoader::makeLoaderRegisterScript
@@ -300,7 +300,7 @@ mw.loader.addSource( {
$this->setMwGlobals( 'wgResourceLoaderSources', $case['sources'] );
}
- $context = self::getResourceLoaderContext();
+ $context = $this->getResourceLoaderContext();
$rl = $context->getResourceLoader();
$rl->register( $case['modules'] );
@@ -337,15 +337,15 @@ mw.loader.addSource( {
public function testRegistrationsMinified( $modules ) {
$this->setMwGlobals( 'wgResourceLoaderDebug', false );
- $context = self::getResourceLoaderContext();
+ $context = $this->getResourceLoaderContext();
$rl = $context->getResourceLoader();
$rl->register( $modules );
$module = new ResourceLoaderStartUpModule();
$this->assertEquals(
'mw.loader.addSource({"local":"/w/load.php"});'
. 'mw.loader.register(['
-. '["test.blank","1388534400"],'
-. '["test.min","1388534400",["test.blank"],null,"local",'
+. '["test.blank",1388534400],'
+. '["test.min",1388534400,[0],null,null,'
. '"return!!(window.JSON\u0026\u0026JSON.parse\u0026\u0026JSON.stringify);"'
. ']]);',
$module->getModuleRegistrations( $context ),
@@ -357,7 +357,7 @@ mw.loader.addSource( {
* @dataProvider provideRegistrations
*/
public function testRegistrationsUnminified( $modules ) {
- $context = self::getResourceLoaderContext();
+ $context = $this->getResourceLoaderContext();
$rl = $context->getResourceLoader();
$rl->register( $modules );
$module = new ResourceLoaderStartUpModule();
@@ -367,16 +367,16 @@ mw.loader.addSource( {
} );mw.loader.register( [
[
"test.blank",
- "1388534400"
+ 1388534400
],
[
"test.min",
- "1388534400",
+ 1388534400,
[
- "test.blank"
+ 0
],
null,
- "local",
+ null,
"return !!( window.JSON \u0026\u0026 JSON.parse \u0026\u0026 JSON.stringify);"
]
] );',
diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
index f19f6886..ca7307ec 100644
--- a/tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
+++ b/tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
@@ -2,13 +2,9 @@
class ResourceLoaderTest extends ResourceLoaderTestCase {
- protected static $resourceLoaderRegisterModulesHook;
-
protected function setUp() {
parent::setUp();
- // $wgResourceLoaderLESSFunctions, $wgResourceLoaderLESSImportPaths; $wgResourceLoaderLESSVars;
-
$this->setMwGlobals( array(
'wgResourceLoaderLESSFunctions' => array(
'test-sum' => function ( $frame, $less ) {
@@ -30,35 +26,33 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
) );
}
- /* Hook Methods */
-
- /**
- * ResourceLoaderRegisterModules hook
- */
- public static function resourceLoaderRegisterModules( &$resourceLoader ) {
- self::$resourceLoaderRegisterModulesHook = true;
-
- return true;
- }
-
- /* Provider Methods */
public static function provideValidModules() {
return array(
array( 'TEST.validModule1', new ResourceLoaderTestModule() ),
);
}
- /* Test Methods */
-
/**
* Ensures that the ResourceLoaderRegisterModules hook is called when a new
* ResourceLoader object is constructed.
* @covers ResourceLoader::__construct
*/
public function testCreatingNewResourceLoaderCallsRegistrationHook() {
- self::$resourceLoaderRegisterModulesHook = false;
+ $resourceLoaderRegisterModulesHook = false;
+
+ $this->setMwGlobals( 'wgHooks', array(
+ 'ResourceLoaderRegisterModules' => array(
+ function ( &$resourceLoader ) use ( &$resourceLoaderRegisterModulesHook ) {
+ $resourceLoaderRegisterModulesHook = true;
+ }
+ )
+ ) );
+
$resourceLoader = new ResourceLoader();
- $this->assertTrue( self::$resourceLoaderRegisterModulesHook );
+ $this->assertTrue(
+ $resourceLoaderRegisterModulesHook,
+ 'Hook ResourceLoaderRegisterModules called'
+ );
return $resourceLoader;
}
@@ -80,7 +74,7 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
* @covers ResourceLoaderFileModule::compileLessFile
*/
public function testLessFileCompilation() {
- $context = self::getResourceLoaderContext();
+ $context = $this->getResourceLoaderContext();
$basePath = __DIR__ . '/../../data/less/module';
$module = new ResourceLoaderFileModule( array(
'localBasePath' => $basePath,
@@ -96,43 +90,11 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
* @param string $css
* @return string
*/
- private function stripNoflip( $css ) {
+ private static function stripNoflip( $css ) {
return str_replace( '/*@noflip*/ ', '', $css );
}
/**
- * What happens when you mix @embed and @noflip?
- * This really is an integration test, but oh well.
- */
- public function testMixedCssAnnotations( ) {
- $basePath = __DIR__ . '/../../data/css';
- $testModule = new ResourceLoaderFileModule( array(
- 'localBasePath' => $basePath,
- 'styles' => array( 'test.css' ),
- ) );
- $expectedModule = new ResourceLoaderFileModule( array(
- 'localBasePath' => $basePath,
- 'styles' => array( 'expected.css' ),
- ) );
-
- $contextLtr = self::getResourceLoaderContext( 'en' );
- $contextRtl = self::getResourceLoaderContext( 'he' );
-
- // Since we want to compare the effect of @noflip+@embed against the effect of just @embed, and
- // the @noflip annotations are always preserved, we need to strip them first.
- $this->assertEquals(
- $expectedModule->getStyles( $contextLtr ),
- $this->stripNoflip( $testModule->getStyles( $contextLtr ) ),
- "/*@noflip*/ with /*@embed*/ gives correct results in LTR mode"
- );
- $this->assertEquals(
- $expectedModule->getStyles( $contextLtr ),
- $this->stripNoflip( $testModule->getStyles( $contextRtl ) ),
- "/*@noflip*/ with /*@embed*/ gives correct results in RTL mode"
- );
- }
-
- /**
* @dataProvider providePackedModules
* @covers ResourceLoader::makePackedModulesString
*/
@@ -193,6 +155,7 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
/**
* @dataProvider provideAddSource
* @covers ResourceLoader::addSource
+ * @covers ResourceLoader::getSources
*/
public function testAddSource( $name, $info, $expected ) {
$rl = new ResourceLoader;
@@ -223,6 +186,106 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
);
}
+ public static function provideLoaderImplement() {
+ return array(
+ array( array(
+ 'title' => 'Implement scripts, styles and messages',
+
+ 'name' => 'test.example',
+ 'scripts' => 'mw.example();',
+ 'styles' => array( 'css' => array( '.mw-example {}' ) ),
+ 'messages' => array( 'example' => '' ),
+ 'templates' => array(),
+
+ 'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery ) {
+mw.example();
+}, {
+ "css": [
+ ".mw-example {}"
+ ]
+}, {
+ "example": ""
+} );',
+ ) ),
+ array( array(
+ 'title' => 'Implement scripts',
+
+ 'name' => 'test.example',
+ 'scripts' => 'mw.example();',
+ 'styles' => array(),
+ 'messages' => new XmlJsCode( '{}' ),
+ 'templates' => array(),
+ 'title' => 'scripts, styles and messags',
+
+ 'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery ) {
+mw.example();
+} );',
+ ) ),
+ array( array(
+ 'title' => 'Implement styles',
+
+ 'name' => 'test.example',
+ 'scripts' => array(),
+ 'styles' => array( 'css' => array( '.mw-example {}' ) ),
+ 'messages' => new XmlJsCode( '{}' ),
+ 'templates' => array(),
+
+ 'expected' => 'mw.loader.implement( "test.example", [], {
+ "css": [
+ ".mw-example {}"
+ ]
+} );',
+ ) ),
+ array( array(
+ 'title' => 'Implement scripts and messages',
+
+ 'name' => 'test.example',
+ 'scripts' => 'mw.example();',
+ 'styles' => array(),
+ 'messages' => array( 'example' => '' ),
+ 'templates' => array(),
+
+ 'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery ) {
+mw.example();
+}, {}, {
+ "example": ""
+} );',
+ ) ),
+ array( array(
+ 'title' => 'Implement scripts and templates',
+
+ 'name' => 'test.example',
+ 'scripts' => 'mw.example();',
+ 'styles' => array(),
+ 'messages' => new XmlJsCode( '{}' ),
+ 'templates' => array( 'example.html' => '' ),
+
+ 'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery ) {
+mw.example();
+}, {}, {}, {
+ "example.html": ""
+} );',
+ ) ),
+ );
+ }
+
+ /**
+ * @dataProvider provideLoaderImplement
+ * @covers ResourceLoader::makeLoaderImplementScript
+ */
+ public function testMakeLoaderImplementScript( $case ) {
+ $this->assertEquals(
+ $case['expected'],
+ ResourceLoader::makeLoaderImplementScript(
+ $case['name'],
+ $case['scripts'],
+ $case['styles'],
+ $case['messages'],
+ $case['templates']
+ )
+ );
+ }
+
/**
* @covers ResourceLoader::getLoadScript
*/
@@ -242,8 +305,14 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
$this->assertTrue( true );
}
}
-}
-/* Hooks */
-global $wgHooks;
-$wgHooks['ResourceLoaderRegisterModules'][] = 'ResourceLoaderTest::resourceLoaderRegisterModules';
+ /**
+ * @covers ResourceLoader::isModuleRegistered
+ */
+ public function testIsModuleRegistered() {
+ $rl = new ResourceLoader();
+ $rl->register( 'test.module', new ResourceLoaderTestModule() );
+ $this->assertTrue( $rl->isModuleRegistered( 'test.module' ) );
+ $this->assertFalse( $rl->isModuleRegistered( 'test.modulenotregistered' ) );
+ }
+}
diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php
index 9dc18050..93a3ebba 100644
--- a/tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php
+++ b/tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php
@@ -3,11 +3,93 @@
class ResourceLoaderWikiModuleTest extends ResourceLoaderTestCase {
/**
+ * @covers ResourceLoaderWikiModule::__construct
+ * @dataProvider provideConstructor
+ */
+ public function testConstructor( $params ) {
+ $module = new ResourceLoaderWikiModule( $params );
+ $this->assertInstanceOf( 'ResourceLoaderWikiModule', $module );
+ }
+
+ public static function provideConstructor() {
+ return array(
+ // Nothing
+ array( null ),
+ array( array() ),
+ // Unrecognized settings
+ array( array( 'foo' => 'baz' ) ),
+ // Real settings
+ array( array( 'scripts' => array( 'MediaWiki:Common.js' ) ) ),
+ );
+ }
+
+ /**
+ * @dataProvider provideGetPages
+ * @covers ResourceLoaderWikiModule::getPages
+ */
+ public function testGetPages( $params, Config $config, $expected ) {
+ $module = new ResourceLoaderWikiModule( $params );
+ $module->setConfig( $config );
+
+ // Use getDefinitionSummary because getPages is protected
+ $summary = $module->getDefinitionSummary( ResourceLoaderContext::newDummyContext() );
+ $this->assertEquals(
+ $expected,
+ $summary['pages']
+ );
+ }
+
+ public static function provideGetPages() {
+ $settings = array(
+ 'UseSiteJs' => true,
+ 'UseSiteCss' => true,
+ );
+
+ $params = array(
+ 'styles' => array( 'MediaWiki:Common.css' ),
+ 'scripts' => array( 'MediaWiki:Common.js' ),
+ );
+
+ return array(
+ array( array(), new HashConfig( $settings ), array() ),
+ array( $params, new HashConfig( $settings ), array(
+ 'MediaWiki:Common.js' => array( 'type' => 'script' ),
+ 'MediaWiki:Common.css' => array( 'type' => 'style' )
+ ) ),
+ array( $params, new HashConfig( array( 'UseSiteCss' => false ) + $settings ), array(
+ 'MediaWiki:Common.js' => array( 'type' => 'script' ),
+ ) ),
+ array( $params, new HashConfig( array( 'UseSiteJs' => false ) + $settings ), array(
+ 'MediaWiki:Common.css' => array( 'type' => 'style' ),
+ ) ),
+ array( $params, new HashConfig( array( 'UseSiteJs' => false, 'UseSiteCss' => false ) ), array() ),
+ );
+ }
+
+ /**
+ * @covers ResourceLoaderWikiModule::getGroup
+ * @dataProvider provideGetGroup
+ */
+ public function testGetGroup( $params, $expected ) {
+ $module = new ResourceLoaderWikiModule( $params );
+ $this->assertEquals( $expected, $module->getGroup() );
+ }
+
+ public static function provideGetGroup() {
+ return array(
+ // No group specified
+ array( array(), null ),
+ // A random group
+ array( array( 'group' => 'foobar' ), 'foobar' ),
+ );
+ }
+
+ /**
* @covers ResourceLoaderWikiModule::isKnownEmpty
* @dataProvider provideIsKnownEmpty
*/
public function testIsKnownEmpty( $titleInfo, $group, $expected ) {
- $module = $this->getMockBuilder( 'ResourceLoaderWikiModuleTestModule' )
+ $module = $this->getMockBuilder( 'ResourceLoaderWikiModule' )
->setMethods( array( 'getTitleInfo', 'getGroup' ) )
->getMock();
$module->expects( $this->any() )
diff --git a/tests/phpunit/includes/resourceloader/templates/template.html b/tests/phpunit/includes/resourceloader/templates/template.html
new file mode 100644
index 00000000..1f6a7d22
--- /dev/null
+++ b/tests/phpunit/includes/resourceloader/templates/template.html
@@ -0,0 +1 @@
+<strong>hello</strong>
diff --git a/tests/phpunit/includes/resourceloader/templates/template2.html b/tests/phpunit/includes/resourceloader/templates/template2.html
new file mode 100644
index 00000000..a322f67d
--- /dev/null
+++ b/tests/phpunit/includes/resourceloader/templates/template2.html
@@ -0,0 +1 @@
+<div>goodbye</div>
diff --git a/tests/phpunit/includes/resourceloader/templates/template_awesome.handlebars b/tests/phpunit/includes/resourceloader/templates/template_awesome.handlebars
new file mode 100644
index 00000000..5f5c07d5
--- /dev/null
+++ b/tests/phpunit/includes/resourceloader/templates/template_awesome.handlebars
@@ -0,0 +1 @@
+wow
diff --git a/tests/phpunit/includes/search/SearchEngineTest.php b/tests/phpunit/includes/search/SearchEngineTest.php
index 3da13615..d0cbfa0a 100644
--- a/tests/phpunit/includes/search/SearchEngineTest.php
+++ b/tests/phpunit/includes/search/SearchEngineTest.php
@@ -14,8 +14,6 @@ class SearchEngineTest extends MediaWikiLangTestCase {
*/
protected $search;
- protected $pageList;
-
/**
* Checks for database type & version.
* Will skip current test if DB does not support search.
@@ -37,10 +35,6 @@ class SearchEngineTest extends MediaWikiLangTestCase {
'wgSearchType' => $searchType
) );
- if ( !isset( self::$pageList ) ) {
- $this->addPages();
- }
-
$this->search = new $searchType( $this->db );
}
@@ -50,33 +44,32 @@ class SearchEngineTest extends MediaWikiLangTestCase {
parent::tearDown();
}
- protected function addPages() {
+ public function addDBData() {
if ( !$this->isWikitextNS( NS_MAIN ) ) {
// @todo cover the case of non-wikitext content in the main namespace
return;
}
- $this->insertPage( "Not_Main_Page", "This is not a main page", 0 );
+ $this->insertPage( 'Not_Main_Page', 'This is not a main page' );
$this->insertPage(
'Talk:Not_Main_Page',
- 'This is not a talk page to the main page, see [[smithee]]',
- 1
+ 'This is not a talk page to the main page, see [[smithee]]'
);
- $this->insertPage( 'Smithee', 'A smithee is one who smiths. See also [[Alan Smithee]]', 0 );
- $this->insertPage( 'Talk:Smithee', 'This article sucks.', 1 );
- $this->insertPage( 'Unrelated_page', 'Nothing in this page is about the S word.', 0 );
- $this->insertPage( 'Another_page', 'This page also is unrelated.', 0 );
- $this->insertPage( 'Help:Help', 'Help me!', 4 );
- $this->insertPage( 'Thppt', 'Blah blah', 0 );
- $this->insertPage( 'Alan_Smithee', 'yum', 0 );
- $this->insertPage( 'Pages', 'are\'food', 0 );
- $this->insertPage( 'HalfOneUp', 'AZ', 0 );
- $this->insertPage( 'FullOneUp', 'AZ', 0 );
- $this->insertPage( 'HalfTwoLow', 'az', 0 );
- $this->insertPage( 'FullTwoLow', 'az', 0 );
- $this->insertPage( 'HalfNumbers', '1234567890', 0 );
- $this->insertPage( 'FullNumbers', '1234567890', 0 );
- $this->insertPage( 'DomainName', 'example.com', 0 );
+ $this->insertPage( 'Smithee', 'A smithee is one who smiths. See also [[Alan Smithee]]' );
+ $this->insertPage( 'Talk:Smithee', 'This article sucks.' );
+ $this->insertPage( 'Unrelated_page', 'Nothing in this page is about the S word.' );
+ $this->insertPage( 'Another_page', 'This page also is unrelated.' );
+ $this->insertPage( 'Help:Help', 'Help me!' );
+ $this->insertPage( 'Thppt', 'Blah blah' );
+ $this->insertPage( 'Alan_Smithee', 'yum' );
+ $this->insertPage( 'Pages', 'are\'food' );
+ $this->insertPage( 'HalfOneUp', 'AZ' );
+ $this->insertPage( 'FullOneUp', 'AZ' );
+ $this->insertPage( 'HalfTwoLow', 'az' );
+ $this->insertPage( 'FullTwoLow', 'az' );
+ $this->insertPage( 'HalfNumbers', '1234567890' );
+ $this->insertPage( 'FullNumbers', '1234567890' );
+ $this->insertPage( 'DomainName', 'example.com' );
}
protected function fetchIds( $results ) {
@@ -101,30 +94,6 @@ class SearchEngineTest extends MediaWikiLangTestCase {
return $matches;
}
- /**
- * Insert a new page
- *
- * @param string $pageName Page name
- * @param string $text Page's content
- * @param int $ns Unused
- */
- protected function insertPage( $pageName, $text, $ns ) {
- $title = Title::newFromText( $pageName, $ns );
-
- $user = User::newFromName( 'WikiSysop' );
- $comment = 'Search Test';
-
- // avoid memory leak...?
- LinkCache::singleton()->clear();
-
- $page = WikiPage::factory( $title );
- $page->doEditContent( ContentHandler::makeContent( $text, $title ), $comment, 0, false, $user );
-
- $this->pageList[] = array( $title, $page->getId() );
-
- return true;
- }
-
public function testFullWidth() {
$this->assertEquals(
array( 'FullOneUp', 'FullTwoLow', 'HalfOneUp', 'HalfTwoLow' ),
diff --git a/tests/phpunit/includes/site/CachingSiteStoreTest.php b/tests/phpunit/includes/site/CachingSiteStoreTest.php
new file mode 100644
index 00000000..d0a79803
--- /dev/null
+++ b/tests/phpunit/includes/site/CachingSiteStoreTest.php
@@ -0,0 +1,161 @@
+<?php
+
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 1.25
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ * @group Database
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class CachingSiteStoreTest extends MediaWikiTestCase {
+
+ /**
+ * @covers CachingSiteStore::getSites
+ */
+ public function testGetSites() {
+ $testSites = TestSites::getSites();
+
+ $store = new CachingSiteStore(
+ $this->getHashSiteStore( $testSites ),
+ wfGetMainCache()
+ );
+
+ $sites = $store->getSites();
+
+ $this->assertInstanceOf( 'SiteList', $sites );
+
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $this->assertInstanceOf( 'Site', $site );
+ }
+
+ foreach ( $testSites as $site ) {
+ if ( $site->getGlobalId() !== null ) {
+ $this->assertTrue( $sites->hasSite( $site->getGlobalId() ) );
+ }
+ }
+ }
+
+ /**
+ * @covers CachingSiteStore::saveSites
+ */
+ public function testSaveSites() {
+ $store = new CachingSiteStore( new HashSiteStore(), wfGetMainCache() );
+
+ $sites = array();
+
+ $site = new Site();
+ $site->setGlobalId( 'ertrywuutr' );
+ $site->setLanguageCode( 'en' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'sdfhxujgkfpth' );
+ $site->setLanguageCode( 'nl' );
+ $sites[] = $site;
+
+ $this->assertTrue( $store->saveSites( $sites ) );
+
+ $site = $store->getSite( 'ertrywuutr' );
+ $this->assertInstanceOf( 'Site', $site );
+ $this->assertEquals( 'en', $site->getLanguageCode() );
+
+ $site = $store->getSite( 'sdfhxujgkfpth' );
+ $this->assertInstanceOf( 'Site', $site );
+ $this->assertEquals( 'nl', $site->getLanguageCode() );
+ }
+
+ /**
+ * @covers CachingSiteStore::reset
+ */
+ public function testReset() {
+ $dbSiteStore = $this->getMockBuilder( 'SiteStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ // php 5.3 compatibility!
+ $self = $this;
+
+ $dbSiteStore->expects( $this->any() )
+ ->method( 'getSite' )
+ ->will( $this->returnValue( $self->getTestSite() ) );
+
+ $dbSiteStore->expects( $this->any() )
+ ->method( 'getSites' )
+ ->will( $this->returnCallback( function() use( $self ) {
+ $siteList = new SiteList();
+ $siteList->setSite( $self->getTestSite() );
+
+ return $siteList;
+ } ) );
+
+ $store = new CachingSiteStore( $dbSiteStore, wfGetMainCache() );
+
+ // initialize internal cache
+ $this->assertGreaterThan( 0, $store->getSites()->count(), 'count sites' );
+
+ $store->getSite( 'enwiki' )->setLanguageCode( 'en-ca' );
+
+ // sanity check: $store should have the new language code for 'enwiki'
+ $this->assertEquals( 'en-ca', $store->getSite( 'enwiki' )->getLanguageCode(), 'sanity check' );
+
+ // purge cache
+ $store->reset();
+
+ // the internal cache of $store should be updated, and now pulling
+ // the site from the 'fallback' DBSiteStore with the original language code.
+ $this->assertEquals( 'en', $store->getSite( 'enwiki' )->getLanguageCode(), 'reset' );
+ }
+
+ public function getTestSite() {
+ $enwiki = new MediaWikiSite();
+ $enwiki->setGlobalId( 'enwiki' );
+ $enwiki->setLanguageCode( 'en' );
+
+ return $enwiki;
+ }
+
+ /**
+ * @covers CachingSiteStore::clear
+ */
+ public function testClear() {
+ $store = new CachingSiteStore( new HashSiteStore(), wfGetMainCache() );
+ $this->assertTrue( $store->clear() );
+
+ $site = $store->getSite( 'enwiki' );
+ $this->assertNull( $site );
+
+ $sites = $store->getSites();
+ $this->assertEquals( 0, $sites->count() );
+ }
+
+ private function getHashSiteStore( array $sites ) {
+ $siteStore = new HashSiteStore();
+ $siteStore->saveSites( $sites );
+
+ return $siteStore;
+ }
+
+}
diff --git a/tests/phpunit/includes/site/DBSiteStoreTest.php b/tests/phpunit/includes/site/DBSiteStoreTest.php
new file mode 100644
index 00000000..673ba54d
--- /dev/null
+++ b/tests/phpunit/includes/site/DBSiteStoreTest.php
@@ -0,0 +1,133 @@
+<?php
+
+/**
+ * Tests for the DBSiteStore class.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 1.21
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ * @group Database
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class DBSiteStoreTest extends MediaWikiTestCase {
+
+ /**
+ * @covers DBSiteStore::getSites
+ */
+ public function testGetSites() {
+ $expectedSites = TestSites::getSites();
+ TestSites::insertIntoDb();
+
+ $store = new DBSiteStore();
+
+ $sites = $store->getSites();
+
+ $this->assertInstanceOf( 'SiteList', $sites );
+
+ /**
+ * @var Site $site
+ */
+ foreach ( $sites as $site ) {
+ $this->assertInstanceOf( 'Site', $site );
+ }
+
+ foreach ( $expectedSites as $site ) {
+ if ( $site->getGlobalId() !== null ) {
+ $this->assertTrue( $sites->hasSite( $site->getGlobalId() ) );
+ }
+ }
+ }
+
+ /**
+ * @covers DBSiteStore::saveSites
+ */
+ public function testSaveSites() {
+ $store = new DBSiteStore();
+
+ $sites = array();
+
+ $site = new Site();
+ $site->setGlobalId( 'ertrywuutr' );
+ $site->setLanguageCode( 'en' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'sdfhxujgkfpth' );
+ $site->setLanguageCode( 'nl' );
+ $sites[] = $site;
+
+ $this->assertTrue( $store->saveSites( $sites ) );
+
+ $site = $store->getSite( 'ertrywuutr' );
+ $this->assertInstanceOf( 'Site', $site );
+ $this->assertEquals( 'en', $site->getLanguageCode() );
+ $this->assertTrue( is_integer( $site->getInternalId() ) );
+ $this->assertTrue( $site->getInternalId() >= 0 );
+
+ $site = $store->getSite( 'sdfhxujgkfpth' );
+ $this->assertInstanceOf( 'Site', $site );
+ $this->assertEquals( 'nl', $site->getLanguageCode() );
+ $this->assertTrue( is_integer( $site->getInternalId() ) );
+ $this->assertTrue( $site->getInternalId() >= 0 );
+ }
+
+ /**
+ * @covers DBSiteStore::reset
+ */
+ public function testReset() {
+ $store1 = new DBSiteStore();
+ $store2 = new DBSiteStore();
+
+ // initialize internal cache
+ $this->assertGreaterThan( 0, $store1->getSites()->count() );
+ $this->assertGreaterThan( 0, $store2->getSites()->count() );
+
+ // Clear actual data. Will purge the external cache and reset the internal
+ // cache in $store1, but not the internal cache in store2.
+ $this->assertTrue( $store1->clear() );
+
+ // sanity check: $store2 should have a stale cache now
+ $this->assertNotNull( $store2->getSite( 'enwiki' ) );
+
+ // purge cache
+ $store2->reset();
+
+ // ...now the internal cache of $store2 should be updated and thus empty.
+ $site = $store2->getSite( 'enwiki' );
+ $this->assertNull( $site );
+ }
+
+ /**
+ * @covers DBSiteStore::clear
+ */
+ public function testClear() {
+ $store = new DBSiteStore();
+ $this->assertTrue( $store->clear() );
+
+ $site = $store->getSite( 'enwiki' );
+ $this->assertNull( $site );
+
+ $sites = $store->getSites();
+ $this->assertEquals( 0, $sites->count() );
+ }
+}
diff --git a/tests/phpunit/includes/site/FileBasedSiteLookupTest.php b/tests/phpunit/includes/site/FileBasedSiteLookupTest.php
new file mode 100644
index 00000000..90ebe5c4
--- /dev/null
+++ b/tests/phpunit/includes/site/FileBasedSiteLookupTest.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 1.25
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @covers FileBasedSiteLookup
+ * @group Site
+ *
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class FileBasedSiteLookupTest extends PHPUnit_Framework_TestCase {
+
+ protected function setUp() {
+ $this->cacheFile = $this->getCacheFile();
+ }
+
+ protected function tearDown() {
+ unlink( $this->cacheFile );
+ }
+
+ public function testGetSites() {
+ $sites = $this->getSites();
+ $cacheBuilder = $this->newSitesCacheFileBuilder( $sites );
+ $cacheBuilder->build();
+
+ $cache = new FileBasedSiteLookup( $this->cacheFile );
+ $this->assertEquals( $sites, $cache->getSites() );
+ }
+
+ public function testGetSite() {
+ $sites = $this->getSites();
+ $cacheBuilder = $this->newSitesCacheFileBuilder( $sites );
+ $cacheBuilder->build();
+
+ $cache = new FileBasedSiteLookup( $this->cacheFile );
+
+ $this->assertEquals( $sites->getSite( 'enwiktionary' ), $cache->getSite( 'enwiktionary' ) );
+ }
+
+ private function newSitesCacheFileBuilder( SiteList $sites ) {
+ return new SitesCacheFileBuilder(
+ $this->getSiteLookup( $sites ),
+ $this->cacheFile
+ );
+ }
+
+ private function getSiteLookup( SiteList $sites ) {
+ $siteLookup = $this->getMockBuilder( 'SiteLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $siteLookup->expects( $this->any() )
+ ->method( 'getSites' )
+ ->will( $this->returnValue( $sites ) );
+
+ return $siteLookup;
+ }
+
+ private function getSites() {
+ $sites = array();
+
+ $site = new Site();
+ $site->setGlobalId( 'foobar' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'enwiktionary' );
+ $site->setGroup( 'wiktionary' );
+ $site->setLanguageCode( 'en' );
+ $site->addNavigationId( 'enwiktionary' );
+ $site->setPath( MediaWikiSite::PATH_PAGE, "https://en.wiktionary.org/wiki/$1" );
+ $site->setPath( MediaWikiSite::PATH_FILE, "https://en.wiktionary.org/w/$1" );
+ $sites[] = $site;
+
+ return new SiteList( $sites );
+ }
+
+ private function getCacheFile() {
+ return tempnam( sys_get_temp_dir(), 'mw-test-sitelist' );
+ }
+
+}
diff --git a/tests/phpunit/includes/site/HashSiteStoreTest.php b/tests/phpunit/includes/site/HashSiteStoreTest.php
new file mode 100644
index 00000000..49a96338
--- /dev/null
+++ b/tests/phpunit/includes/site/HashSiteStoreTest.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 1.25
+ *
+ * @ingroup Site
+ * @group Site
+ *
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class HashSiteStoreTest extends MediaWikiTestCase {
+
+ /**
+ * @covers HashSiteStore::getSites
+ */
+ public function testGetSites() {
+ $expectedSites = array();
+
+ foreach( TestSites::getSites() as $testSite ) {
+ $siteId = $testSite->getGlobalId();
+ $expectedSites[$siteId] = $testSite;
+ }
+
+ $siteStore = new HashSiteStore( $expectedSites );
+
+ $this->assertEquals( new SiteList( $expectedSites ), $siteStore->getSites() );
+ }
+
+ /**
+ * @covers HashSiteStore::saveSite
+ * @covers HashSiteStore::getSite
+ */
+ public function testSaveSite() {
+ $store = new HashSiteStore();
+
+ $site = new Site();
+ $site->setGlobalId( 'dewiki' );
+
+ $this->assertCount( 0, $store->getSites(), '0 sites in store' );
+
+ $store->saveSite( $site );
+
+ $this->assertCount( 1, $store->getSites(), 'Store has 1 sites' );
+ $this->assertEquals( $site, $store->getSite( 'dewiki' ), 'Store has dewiki' );
+ }
+
+ /**
+ * @covers HashSiteStore::saveSites
+ */
+ public function testSaveSites() {
+ $store = new HashSiteStore();
+
+ $sites = array();
+
+ $site = new Site();
+ $site->setGlobalId( 'enwiki' );
+ $site->setLanguageCode( 'en' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'eswiki' );
+ $site->setLanguageCode( 'es' );
+ $sites[] = $site;
+
+ $this->assertCount( 0, $store->getSites(), '0 sites in store' );
+
+ $store->saveSites( $sites );
+
+ $this->assertCount( 2, $store->getSites(), 'Store has 2 sites' );
+ $this->assertTrue( $store->getSites()->hasSite( 'enwiki' ), 'Store has enwiki' );
+ $this->assertTrue( $store->getSites()->hasSite( 'eswiki' ), 'Store has eswiki' );
+ }
+
+ /**
+ * @covers HashSiteStore::clear
+ */
+ public function testClear() {
+ $store = new HashSiteStore();
+
+ $site = new Site();
+ $site->setGlobalId( 'arwiki' );
+ $store->saveSite( $site );
+
+ $this->assertCount( 1, $store->getSites(), '1 site in store' );
+
+ $store->clear();
+ $this->assertCount( 0, $store->getSites(), '0 sites in store' );
+ }
+}
diff --git a/tests/phpunit/includes/site/MediaWikiSiteTest.php b/tests/phpunit/includes/site/MediaWikiSiteTest.php
index c3fd1557..ef2ccca2 100644
--- a/tests/phpunit/includes/site/MediaWikiSiteTest.php
+++ b/tests/phpunit/includes/site/MediaWikiSiteTest.php
@@ -26,7 +26,6 @@
*
* @group Site
*
- * @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
class MediaWikiSiteTest extends SiteTest {
diff --git a/tests/phpunit/includes/site/SiteExporterTest.php b/tests/phpunit/includes/site/SiteExporterTest.php
new file mode 100644
index 00000000..19dd0aa1
--- /dev/null
+++ b/tests/phpunit/includes/site/SiteExporterTest.php
@@ -0,0 +1,147 @@
+<?php
+
+/**
+ * Tests for the SiteExporter class.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ *
+ * @covers SiteExporter
+ *
+ * @author Daniel Kinzler
+ */
+class SiteExporterTest extends PHPUnit_Framework_TestCase {
+
+ public function testConstructor_InvalidArgument() {
+ $this->setExpectedException( 'InvalidArgumentException' );
+
+ new SiteExporter( 'Foo' );
+ }
+
+ public function testExportSites() {
+ $foo = Site::newForType( Site::TYPE_UNKNOWN );
+ $foo->setGlobalId( 'Foo' );
+
+ $acme = Site::newForType( Site::TYPE_UNKNOWN );
+ $acme->setGlobalId( 'acme.com' );
+ $acme->setGroup( 'Test' );
+ $acme->addLocalId( Site::ID_INTERWIKI, 'acme' );
+ $acme->setPath( Site::PATH_LINK, 'http://acme.com/' );
+
+ $tmp = tmpfile();
+ $exporter = new SiteExporter( $tmp );
+
+ $exporter->exportSites( array( $foo, $acme ) );
+
+ fseek( $tmp, 0 );
+ $xml = fread( $tmp, 16*1024 );
+
+ $this->assertContains( '<sites ', $xml );
+ $this->assertContains( '<site>', $xml );
+ $this->assertContains( '<globalid>Foo</globalid>', $xml );
+ $this->assertContains( '</site>', $xml );
+ $this->assertContains( '<globalid>acme.com</globalid>', $xml );
+ $this->assertContains( '<group>Test</group>', $xml );
+ $this->assertContains( '<localid type="interwiki">acme</localid>', $xml );
+ $this->assertContains( '<path type="link">http://acme.com/</path>', $xml );
+ $this->assertContains( '</sites>', $xml );
+
+ // NOTE: HHVM (at least on wmf Jenkins) doesn't like file URLs.
+ $xsdFile = __DIR__ . '/../../../../docs/sitelist-1.0.xsd';
+ $xsdData = file_get_contents( $xsdFile );
+
+ $document = new DOMDocument();
+ $document->loadXML( $xml, LIBXML_NONET );
+ $document->schemaValidateSource( $xsdData );
+ }
+
+ private function newSiteStore( SiteList $sites ) {
+ $store = $this->getMock( 'SiteStore' );
+
+ $store->expects( $this->once() )
+ ->method( 'saveSites' )
+ ->will( $this->returnCallback( function ( $moreSites ) use ( $sites ) {
+ foreach ( $moreSites as $site ) {
+ $sites->setSite( $site );
+ }
+ } ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getSites' )
+ ->will( $this->returnValue( new SiteList() ) );
+
+ return $store;
+ }
+
+ public function provideRoundTrip() {
+ $foo = Site::newForType( Site::TYPE_UNKNOWN );
+ $foo->setGlobalId( 'Foo' );
+
+ $acme = Site::newForType( Site::TYPE_UNKNOWN );
+ $acme->setGlobalId( 'acme.com' );
+ $acme->setGroup( 'Test' );
+ $acme->addLocalId( Site::ID_INTERWIKI, 'acme' );
+ $acme->setPath( Site::PATH_LINK, 'http://acme.com/' );
+
+ $dewiki = Site::newForType( Site::TYPE_MEDIAWIKI );
+ $dewiki->setGlobalId( 'dewiki' );
+ $dewiki->setGroup( 'wikipedia' );
+ $dewiki->setForward( true );
+ $dewiki->addLocalId( Site::ID_INTERWIKI, 'wikipedia' );
+ $dewiki->addLocalId( Site::ID_EQUIVALENT, 'de' );
+ $dewiki->setPath( Site::PATH_LINK, 'http://de.wikipedia.org/w/' );
+ $dewiki->setPath( MediaWikiSite::PATH_PAGE, 'http://de.wikipedia.org/wiki/' );
+ $dewiki->setSource( 'meta.wikimedia.org' );
+
+ return array(
+ 'empty' => array(
+ new SiteList()
+ ),
+
+ 'some' => array(
+ new SiteList( array( $foo, $acme, $dewiki ) ),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider provideRoundTrip()
+ */
+ public function testRoundTrip( SiteList $sites ) {
+ $tmp = tmpfile();
+ $exporter = new SiteExporter( $tmp );
+
+ $exporter->exportSites( $sites );
+
+ fseek( $tmp, 0 );
+ $xml = fread( $tmp, 16*1024 );
+
+ $actualSites = new SiteList();
+ $store = $this->newSiteStore( $actualSites );
+
+ $importer = new SiteImporter( $store );
+ $importer->importFromXML( $xml );
+
+ $this->assertEquals( $sites, $actualSites );
+ }
+
+}
diff --git a/tests/phpunit/includes/site/SiteImporterTest.php b/tests/phpunit/includes/site/SiteImporterTest.php
new file mode 100644
index 00000000..cb0316ab
--- /dev/null
+++ b/tests/phpunit/includes/site/SiteImporterTest.php
@@ -0,0 +1,200 @@
+<?php
+
+/**
+ * Tests for the SiteImporter class.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @group Site
+ *
+ * @covers SiteImporter
+ *
+ * @author Daniel Kinzler
+ */
+class SiteImporterTest extends PHPUnit_Framework_TestCase {
+
+ private function newSiteImporter( array $expectedSites, $errorCount ) {
+ $store = $this->getMock( 'SiteStore' );
+
+ $self = $this;
+ $store->expects( $this->once() )
+ ->method( 'saveSites' )
+ ->will( $this->returnCallback( function ( $sites ) use ( $expectedSites, $self ) {
+ $self->assertSitesEqual( $expectedSites, $sites );
+ } ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getSites' )
+ ->will( $this->returnValue( new SiteList() ) );
+
+ $errorHandler = $this->getMock( 'Psr\Log\LoggerInterface' );
+ $errorHandler->expects( $this->exactly( $errorCount ) )
+ ->method( 'error' );
+
+ $importer = new SiteImporter( $store );
+ $importer->setExceptionCallback( array( $errorHandler, 'error' ) );
+
+ return $importer;
+ }
+
+ public function assertSitesEqual( $expected, $actual, $message = '' ) {
+ $this->assertEquals(
+ $this->getSerializedSiteList( $expected ),
+ $this->getSerializedSiteList( $actual ),
+ $message
+ );
+ }
+
+ public function provideImportFromXML() {
+ $foo = Site::newForType( Site::TYPE_UNKNOWN );
+ $foo->setGlobalId( 'Foo' );
+
+ $acme = Site::newForType( Site::TYPE_UNKNOWN );
+ $acme->setGlobalId( 'acme.com' );
+ $acme->setGroup( 'Test' );
+ $acme->addLocalId( Site::ID_INTERWIKI, 'acme' );
+ $acme->setPath( Site::PATH_LINK, 'http://acme.com/' );
+
+ $dewiki = Site::newForType( Site::TYPE_MEDIAWIKI );
+ $dewiki->setGlobalId( 'dewiki' );
+ $dewiki->setGroup( 'wikipedia' );
+ $dewiki->setForward( true );
+ $dewiki->addLocalId( Site::ID_INTERWIKI, 'wikipedia' );
+ $dewiki->addLocalId( Site::ID_EQUIVALENT, 'de' );
+ $dewiki->setPath( Site::PATH_LINK, 'http://de.wikipedia.org/w/' );
+ $dewiki->setPath( MediaWikiSite::PATH_PAGE, 'http://de.wikipedia.org/wiki/' );
+ $dewiki->setSource( 'meta.wikimedia.org' );
+
+ return array(
+ 'empty' => array(
+ '<sites></sites>',
+ array(),
+ ),
+ 'no sites' => array(
+ '<sites><Foo><globalid>Foo</globalid></Foo><Bar><quux>Bla</quux></Bar></sites>',
+ array(),
+ ),
+ 'minimal' => array(
+ '<sites>' .
+ '<site><globalid>Foo</globalid></site>' .
+ '</sites>',
+ array( $foo ),
+ ),
+ 'full' => array(
+ '<sites>' .
+ '<site><globalid>Foo</globalid></site>' .
+ '<site>' .
+ '<globalid>acme.com</globalid>' .
+ '<localid type="interwiki">acme</localid>' .
+ '<group>Test</group>' .
+ '<path type="link">http://acme.com/</path>' .
+ '</site>' .
+ '<site type="mediawiki">' .
+ '<source>meta.wikimedia.org</source>' .
+ '<globalid>dewiki</globalid>' .
+ '<localid type="interwiki">wikipedia</localid>' .
+ '<localid type="equivalent">de</localid>' .
+ '<group>wikipedia</group>' .
+ '<forward/>' .
+ '<path type="link">http://de.wikipedia.org/w/</path>' .
+ '<path type="page_path">http://de.wikipedia.org/wiki/</path>' .
+ '</site>' .
+ '</sites>',
+ array( $foo, $acme, $dewiki ),
+ ),
+ 'skip' => array(
+ '<sites>' .
+ '<site><globalid>Foo</globalid></site>' .
+ '<site><barf>Foo</barf></site>' .
+ '<site>' .
+ '<globalid>acme.com</globalid>' .
+ '<localid type="interwiki">acme</localid>' .
+ '<silly>boop!</silly>' .
+ '<group>Test</group>' .
+ '<path type="link">http://acme.com/</path>' .
+ '</site>' .
+ '</sites>',
+ array( $foo, $acme ),
+ 1
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider provideImportFromXML
+ */
+ public function testImportFromXML( $xml, array $expectedSites, $errorCount = 0 ) {
+ $importer = $this->newSiteImporter( $expectedSites, $errorCount );
+ $importer->importFromXML( $xml );
+ }
+
+ public function testImportFromXML_malformed() {
+ $this->setExpectedException( 'Exception' );
+
+ $store = $this->getMock( 'SiteStore' );
+ $importer = new SiteImporter( $store );
+ $importer->importFromXML( 'THIS IS NOT XML' );
+ }
+
+ public function testImportFromFile() {
+ $foo = Site::newForType( Site::TYPE_UNKNOWN );
+ $foo->setGlobalId( 'Foo' );
+
+ $acme = Site::newForType( Site::TYPE_UNKNOWN );
+ $acme->setGlobalId( 'acme.com' );
+ $acme->setGroup( 'Test' );
+ $acme->addLocalId( Site::ID_INTERWIKI, 'acme' );
+ $acme->setPath( Site::PATH_LINK, 'http://acme.com/' );
+
+ $dewiki = Site::newForType( Site::TYPE_MEDIAWIKI );
+ $dewiki->setGlobalId( 'dewiki' );
+ $dewiki->setGroup( 'wikipedia' );
+ $dewiki->setForward( true );
+ $dewiki->addLocalId( Site::ID_INTERWIKI, 'wikipedia' );
+ $dewiki->addLocalId( Site::ID_EQUIVALENT, 'de' );
+ $dewiki->setPath( Site::PATH_LINK, 'http://de.wikipedia.org/w/' );
+ $dewiki->setPath( MediaWikiSite::PATH_PAGE, 'http://de.wikipedia.org/wiki/' );
+ $dewiki->setSource( 'meta.wikimedia.org' );
+
+ $importer = $this->newSiteImporter( array( $foo, $acme, $dewiki ), 0 );
+
+ $file = __DIR__ . '/SiteImporterTest.xml';
+ $importer->importFromFile( $file );
+ }
+
+ /**
+ * @param Site[] $sites
+ *
+ * @return array[]
+ */
+ private function getSerializedSiteList( $sites ) {
+ $serialized = array();
+
+ foreach ( $sites as $site ) {
+ $key = $site->getGlobalId();
+ $data = unserialize( $site->serialize() );
+
+ $serialized[$key] = $data;
+ }
+
+ return $serialized;
+ }
+}
diff --git a/tests/phpunit/includes/site/SiteImporterTest.xml b/tests/phpunit/includes/site/SiteImporterTest.xml
new file mode 100644
index 00000000..720b1faf
--- /dev/null
+++ b/tests/phpunit/includes/site/SiteImporterTest.xml
@@ -0,0 +1,19 @@
+<sites version="1.0" xmlns="http://www.mediawiki.org/xml/sitelist-1.0/">
+ <site><globalid>Foo</globalid></site>
+ <site>
+ <globalid>acme.com</globalid>
+ <localid type="interwiki">acme</localid>
+ <group>Test</group>
+ <path type="link">http://acme.com/</path>
+ </site>
+ <site type="mediawiki">
+ <source>meta.wikimedia.org</source>
+ <globalid>dewiki</globalid>
+ <localid type="interwiki">wikipedia</localid>
+ <localid type="equivalent">de</localid>
+ <group>wikipedia</group>
+ <forward/>
+ <path type="link">http://de.wikipedia.org/w/</path>
+ <path type="page_path">http://de.wikipedia.org/wiki/</path>
+ </site>
+</sites>
diff --git a/tests/phpunit/includes/site/SiteListTest.php b/tests/phpunit/includes/site/SiteListTest.php
index 534ed9c9..d6c58cf6 100644
--- a/tests/phpunit/includes/site/SiteListTest.php
+++ b/tests/phpunit/includes/site/SiteListTest.php
@@ -26,7 +26,6 @@
*
* @group Site
*
- * @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
class SiteListTest extends MediaWikiTestCase {
diff --git a/tests/phpunit/includes/site/SiteSQLStoreTest.php b/tests/phpunit/includes/site/SiteSQLStoreTest.php
index 6002c1a1..69088006 100644
--- a/tests/phpunit/includes/site/SiteSQLStoreTest.php
+++ b/tests/phpunit/includes/site/SiteSQLStoreTest.php
@@ -1,8 +1,6 @@
<?php
/**
- * Tests for the SiteSQLStore class.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -19,7 +17,7 @@
* http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @since 1.21
+ * @since 1.25
*
* @ingroup Site
* @ingroup Test
@@ -27,108 +25,16 @@
* @group Site
* @group Database
*
- * @licence GNU GPL v2+
- * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ * @author Katie Filbert < aude.wiki@gmail.com >
*/
class SiteSQLStoreTest extends MediaWikiTestCase {
/**
- * @covers SiteSQLStore::getSites
- */
- public function testGetSites() {
- $expectedSites = TestSites::getSites();
- TestSites::insertIntoDb();
-
- $store = SiteSQLStore::newInstance();
-
- $sites = $store->getSites();
-
- $this->assertInstanceOf( 'SiteList', $sites );
-
- /**
- * @var Site $site
- */
- foreach ( $sites as $site ) {
- $this->assertInstanceOf( 'Site', $site );
- }
-
- foreach ( $expectedSites as $site ) {
- if ( $site->getGlobalId() !== null ) {
- $this->assertTrue( $sites->hasSite( $site->getGlobalId() ) );
- }
- }
- }
-
- /**
- * @covers SiteSQLStore::saveSites
- */
- public function testSaveSites() {
- $store = SiteSQLStore::newInstance();
-
- $sites = array();
-
- $site = new Site();
- $site->setGlobalId( 'ertrywuutr' );
- $site->setLanguageCode( 'en' );
- $sites[] = $site;
-
- $site = new MediaWikiSite();
- $site->setGlobalId( 'sdfhxujgkfpth' );
- $site->setLanguageCode( 'nl' );
- $sites[] = $site;
-
- $this->assertTrue( $store->saveSites( $sites ) );
-
- $site = $store->getSite( 'ertrywuutr' );
- $this->assertInstanceOf( 'Site', $site );
- $this->assertEquals( 'en', $site->getLanguageCode() );
- $this->assertTrue( is_integer( $site->getInternalId() ) );
- $this->assertTrue( $site->getInternalId() >= 0 );
-
- $site = $store->getSite( 'sdfhxujgkfpth' );
- $this->assertInstanceOf( 'Site', $site );
- $this->assertEquals( 'nl', $site->getLanguageCode() );
- $this->assertTrue( is_integer( $site->getInternalId() ) );
- $this->assertTrue( $site->getInternalId() >= 0 );
- }
-
- /**
- * @covers SiteSQLStore::reset
+ * @covers SiteSQLStore::newInstance
*/
- public function testReset() {
- $store1 = SiteSQLStore::newInstance();
- $store2 = SiteSQLStore::newInstance();
-
- // initialize internal cache
- $this->assertGreaterThan( 0, $store1->getSites()->count() );
- $this->assertGreaterThan( 0, $store2->getSites()->count() );
-
- // Clear actual data. Will purge the external cache and reset the internal
- // cache in $store1, but not the internal cache in store2.
- $this->assertTrue( $store1->clear() );
-
- // sanity check: $store2 should have a stale cache now
- $this->assertNotNull( $store2->getSite( 'enwiki' ) );
-
- // purge cache
- $store2->reset();
-
- // ...now the internal cache of $store2 should be updated and thus empty.
- $site = $store2->getSite( 'enwiki' );
- $this->assertNull( $site );
+ public function testNewInstance() {
+ $siteStore = SiteSQLStore::newInstance();
+ $this->assertInstanceOf( 'SiteSQLStore', $siteStore );
}
- /**
- * @covers SiteSQLStore::clear
- */
- public function testClear() {
- $store = SiteSQLStore::newInstance();
- $this->assertTrue( $store->clear() );
-
- $site = $store->getSite( 'enwiki' );
- $this->assertNull( $site );
-
- $sites = $store->getSites();
- $this->assertEquals( 0, $sites->count() );
- }
}
diff --git a/tests/phpunit/includes/site/SiteTest.php b/tests/phpunit/includes/site/SiteTest.php
index 29c1ff33..63d90d2e 100644
--- a/tests/phpunit/includes/site/SiteTest.php
+++ b/tests/phpunit/includes/site/SiteTest.php
@@ -26,7 +26,6 @@
*
* @group Site
*
- * @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
class SiteTest extends MediaWikiTestCase {
diff --git a/tests/phpunit/includes/site/SitesCacheFileBuilderTest.php b/tests/phpunit/includes/site/SitesCacheFileBuilderTest.php
new file mode 100644
index 00000000..087341a0
--- /dev/null
+++ b/tests/phpunit/includes/site/SitesCacheFileBuilderTest.php
@@ -0,0 +1,135 @@
+<?php
+
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 1.25
+ *
+ * @ingroup Site
+ * @ingroup Test
+ *
+ * @covers SitesCacheFileBuilder
+ * @group Site
+ *
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class SitesCacheFileBuilderTest extends PHPUnit_Framework_TestCase {
+
+ protected function setUp() {
+ $this->cacheFile = $this->getCacheFile();
+ }
+
+ protected function tearDown() {
+ unlink( $this->cacheFile );
+ }
+
+ public function testBuild() {
+ $cacheBuilder = $this->newSitesCacheFileBuilder( $this->getSites() );
+ $cacheBuilder->build();
+
+ $contents = file_get_contents( $this->cacheFile );
+ $this->assertEquals( json_encode( $this->getExpectedData() ), $contents );
+ }
+
+ private function getExpectedData() {
+ return array(
+ 'sites' => array(
+ 'foobar' => array(
+ 'globalid' => 'foobar',
+ 'type' => 'unknown',
+ 'group' => 'none',
+ 'source' => 'local',
+ 'language' => null,
+ 'localids' => array(),
+ 'config' => array(),
+ 'data' => array(),
+ 'forward' => false,
+ 'internalid' => null,
+ 'identifiers' => array()
+ ),
+ 'enwiktionary' => array(
+ 'globalid' => 'enwiktionary',
+ 'type' => 'mediawiki',
+ 'group' => 'wiktionary',
+ 'source' => 'local',
+ 'language' => 'en',
+ 'localids' => array(
+ 'equivalent' => array( 'enwiktionary' )
+ ),
+ 'config' => array(),
+ 'data' => array(
+ 'paths' => array(
+ 'page_path' => 'https://en.wiktionary.org/wiki/$1',
+ 'file_path' => 'https://en.wiktionary.org/w/$1'
+ )
+ ),
+ 'forward' => false,
+ 'internalid' => null,
+ 'identifiers' => array(
+ array(
+ 'type' => 'equivalent',
+ 'key' => 'enwiktionary'
+ )
+ )
+ )
+ )
+ );
+ }
+
+ private function newSitesCacheFileBuilder( SiteList $sites ) {
+ return new SitesCacheFileBuilder(
+ $this->getSiteLookup( $sites ),
+ $this->cacheFile
+ );
+ }
+
+ private function getSiteLookup( SiteList $sites ) {
+ $siteLookup = $this->getMockBuilder( 'SiteLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $siteLookup->expects( $this->any() )
+ ->method( 'getSites' )
+ ->will( $this->returnValue( $sites ) );
+
+ return $siteLookup;
+ }
+
+ private function getSites() {
+ $sites = array();
+
+ $site = new Site();
+ $site->setGlobalId( 'foobar' );
+ $sites[] = $site;
+
+ $site = new MediaWikiSite();
+ $site->setGlobalId( 'enwiktionary' );
+ $site->setGroup( 'wiktionary' );
+ $site->setLanguageCode( 'en' );
+ $site->addNavigationId( 'enwiktionary' );
+ $site->setPath( MediaWikiSite::PATH_PAGE, "https://en.wiktionary.org/wiki/$1" );
+ $site->setPath( MediaWikiSite::PATH_FILE, "https://en.wiktionary.org/w/$1" );
+ $sites[] = $site;
+
+ return new SiteList( $sites );
+ }
+
+ private function getCacheFile() {
+ return tempnam( sys_get_temp_dir(), 'mw-test-sitelist' );
+ }
+
+}
diff --git a/tests/phpunit/includes/site/TestSites.php b/tests/phpunit/includes/site/TestSites.php
index af314ba2..4c402484 100644
--- a/tests/phpunit/includes/site/TestSites.php
+++ b/tests/phpunit/includes/site/TestSites.php
@@ -26,7 +26,6 @@
*
* @group Site
*
- * @licence GNU GPL v2+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
*/
class TestSites {
@@ -108,7 +107,7 @@ class TestSites {
* @since 0.1
*/
public static function insertIntoDb() {
- $sitesTable = SiteSQLStore::newInstance();
+ $sitesTable = new DBSiteStore();
$sitesTable->clear();
$sitesTable->saveSites( TestSites::getSites() );
}
diff --git a/tests/phpunit/includes/skins/SkinTemplateTest.php b/tests/phpunit/includes/skins/SkinTemplateTest.php
index baa995d4..8084a66f 100644
--- a/tests/phpunit/includes/skins/SkinTemplateTest.php
+++ b/tests/phpunit/includes/skins/SkinTemplateTest.php
@@ -5,7 +5,6 @@
*
* @group Output
*
- * @licence GNU GPL v2+
* @author Bene* < benestar.wikimedia@gmail.com >
*/
diff --git a/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php b/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php
index 779fa558..fd6911f6 100644
--- a/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php
+++ b/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php
@@ -28,21 +28,52 @@ class SpecialPageFactoryTest extends MediaWikiTestCase {
SpecialPageFactory::resetList();
}
+ public function testResetList() {
+ SpecialPageFactory::resetList();
+ $this->assertContains( 'Specialpages', SpecialPageFactory::getNames() );
+ }
+
+ public function testHookNotCalledTwice() {
+ $count = 0;
+ $this->mergeMwGlobalArrayValue( 'wgHooks', array(
+ 'SpecialPage_initList' => array(
+ function () use ( &$count ) {
+ $count++;
+ }
+ ) ) );
+ SpecialPageFactory::resetList();
+ SpecialPageFactory::getNames();
+ SpecialPageFactory::getNames();
+ $this->assertEquals( 1, $count );
+ }
+
public function newSpecialAllPages() {
return new SpecialAllPages();
}
public function specialPageProvider() {
+ $specialPageTestHelper = new SpecialPageTestHelper();
+
return array(
'class name' => array( 'SpecialAllPages', false ),
- 'closure' => array( function() {
+ 'closure' => array( function () {
return new SpecialAllPages();
}, false ),
- 'function' => array( array( $this, 'newSpecialAllPages' ), false ),
+ 'function' => array( array( $this, 'newSpecialAllPages' ), false ),
+ 'callback string' => array( 'SpecialPageTestHelper::newSpecialAllPages', false ),
+ 'callback with object' => array(
+ array( $specialPageTestHelper, 'newSpecialAllPages' ),
+ false
+ ),
+ 'callback array' => array(
+ array( 'SpecialPageTestHelper', 'newSpecialAllPages' ),
+ false
+ )
);
}
/**
+ * @covers SpecialPageFactory::getPage
* @dataProvider specialPageProvider
*/
public function testGetPage( $spec, $shouldReuseInstance ) {
@@ -56,6 +87,9 @@ class SpecialPageFactoryTest extends MediaWikiTestCase {
$this->assertEquals( $shouldReuseInstance, $page2 === $page, "Should re-use instance:" );
}
+ /**
+ * @covers SpecialPageFactory::getNames
+ */
public function testGetNames() {
$this->mergeMwGlobalArrayValue( 'wgSpecialPages', array( 'testdummy' => 'SpecialAllPages' ) );
SpecialPageFactory::resetList();
@@ -65,6 +99,9 @@ class SpecialPageFactoryTest extends MediaWikiTestCase {
$this->assertContains( 'testdummy', $names );
}
+ /**
+ * @covers SpecialPageFactory::resolveAlias
+ */
public function testResolveAlias() {
$this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
SpecialPageFactory::resetList();
@@ -74,6 +111,9 @@ class SpecialPageFactoryTest extends MediaWikiTestCase {
$this->assertEquals( 'Foo', $param );
}
+ /**
+ * @covers SpecialPageFactory::getLocalNameFor
+ */
public function testGetLocalNameFor() {
$this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
SpecialPageFactory::resetList();
@@ -82,6 +122,9 @@ class SpecialPageFactoryTest extends MediaWikiTestCase {
$this->assertEquals( 'Spezialseiten/Foo', $name );
}
+ /**
+ * @covers SpecialPageFactory::getTitleForAlias
+ */
public function testGetTitleForAlias() {
$this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
SpecialPageFactory::resetList();
@@ -222,4 +265,19 @@ class SpecialPageFactoryTest extends MediaWikiTestCase {
);
}
+ public function testGetAliasListRecursion() {
+ $called = false;
+ $this->mergeMwGlobalArrayValue( 'wgHooks', array(
+ 'SpecialPage_initList' => array(
+ function () use ( &$called ) {
+ SpecialPageFactory::getLocalNameFor( 'Specialpages' );
+ $called = true;
+ }
+ ),
+ ) );
+ SpecialPageFactory::resetList();
+ SpecialPageFactory::getLocalNameFor( 'Specialpages' );
+ $this->assertTrue( $called, 'Recursive call succeeded' );
+ }
+
}
diff --git a/tests/phpunit/includes/SpecialPageTest.php b/tests/phpunit/includes/specialpage/SpecialPageTest.php
index 245cdffd..5a0aef97 100644
--- a/tests/phpunit/includes/SpecialPageTest.php
+++ b/tests/phpunit/includes/specialpage/SpecialPageTest.php
@@ -5,7 +5,6 @@
*
* @group Database
*
- * @licence GNU GPL v2+
* @author Katie Filbert < aude.wiki@gmail.com >
*/
class SpecialPageTest extends MediaWikiTestCase {
diff --git a/tests/phpunit/includes/specialpage/SpecialPageTestHelper.php b/tests/phpunit/includes/specialpage/SpecialPageTestHelper.php
new file mode 100644
index 00000000..37e29dcb
--- /dev/null
+++ b/tests/phpunit/includes/specialpage/SpecialPageTestHelper.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+class SpecialPageTestHelper {
+
+ public static function newSpecialAllPages() {
+ return new SpecialAllPages();
+ }
+
+}
diff --git a/tests/phpunit/includes/specials/SpecialBooksourcesTest.php b/tests/phpunit/includes/specials/SpecialBooksourcesTest.php
new file mode 100644
index 00000000..69485a03
--- /dev/null
+++ b/tests/phpunit/includes/specials/SpecialBooksourcesTest.php
@@ -0,0 +1,36 @@
+<?php
+class SpecialBooksourcesTest extends MediaWikiTestCase {
+ public static function provideISBNs() {
+ return array(
+ array( '978-0-300-14424-6', true ),
+ array( '0-14-020652-3', true ),
+ array( '020652-3', false ),
+ array( '9781234567897', true ),
+ array( '1-4133-0454-0', true ),
+ array( '978-1413304541', true ),
+ array( '0136091814', true ),
+ array( '0136091812', false ),
+ array( '9780136091813', true ),
+ array( '9780136091817', false ),
+ array( '123456789X', true ),
+
+ // Bug 67021
+ array( '1413304541', false ),
+ array( '141330454X', false ),
+ array( '1413304540', true ),
+ array( '14133X4540', false ),
+ array( '97814133X4541', false ),
+ array( '978035642615X', false ),
+ array( '9781413304541', true ),
+ array( '9780356426150', true ),
+ );
+ }
+
+ /**
+ * @covers SpecialBookSources::isValidISBN
+ * @dataProvider provideISBNs
+ */
+ public function testIsValidISBN( $isbn, $isValid ) {
+ $this->assertSame( $isValid, SpecialBookSources::isValidISBN( $isbn ) );
+ }
+}
diff --git a/tests/phpunit/includes/specials/SpecialMIMESearchTest.php b/tests/phpunit/includes/specials/SpecialMIMESearchTest.php
index 14d19685..fe1c9e83 100644
--- a/tests/phpunit/includes/specials/SpecialMIMESearchTest.php
+++ b/tests/phpunit/includes/specials/SpecialMIMESearchTest.php
@@ -5,11 +5,11 @@
class SpecialMIMESearchTest extends MediaWikiTestCase {
- /** @var MIMESearchPage */
+ /** @var MIMEsearchPage */
private $page;
function setUp() {
- $this->page = new MIMESearchPage;
+ $this->page = new MIMEsearchPage;
$context = new RequestContext();
$context->setTitle( Title::makeTitle( NS_SPECIAL, 'MIMESearch' ) );
$context->setRequest( new FauxRequest() );
diff --git a/tests/phpunit/includes/title/ForeignTitleTest.php b/tests/phpunit/includes/title/ForeignTitleTest.php
new file mode 100644
index 00000000..599d2a33
--- /dev/null
+++ b/tests/phpunit/includes/title/ForeignTitleTest.php
@@ -0,0 +1,103 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author This, that and the other
+ */
+
+/**
+ * @covers ForeignTitle
+ *
+ * @group Title
+ */
+class ForeignTitleTest extends MediaWikiTestCase {
+
+ public function basicProvider() {
+ return array(
+ array(
+ new ForeignTitle( 20, 'Contributor', 'JohnDoe' ),
+ 20, 'Contributor', 'JohnDoe'
+ ),
+ array(
+ new ForeignTitle( '1', 'Discussion', 'Capital' ),
+ 1, 'Discussion', 'Capital'
+ ),
+ array(
+ new ForeignTitle( 0, '', 'MainNamespace' ),
+ 0, '', 'MainNamespace'
+ ),
+ array(
+ new ForeignTitle( 4, 'Some ns', 'Article title with spaces' ),
+ 4, 'Some_ns', 'Article_title_with_spaces'
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider basicProvider
+ */
+ public function testBasic( ForeignTitle $title, $expectedId, $expectedName,
+ $expectedText ) {
+
+ $this->assertEquals( true, $title->isNamespaceIdKnown() );
+ $this->assertEquals( $expectedId, $title->getNamespaceId() );
+ $this->assertEquals( $expectedName, $title->getNamespaceName() );
+ $this->assertEquals( $expectedText, $title->getText() );
+ }
+
+ public function testUnknownNamespaceCheck( ) {
+ $title = new ForeignTitle( null, 'this', 'that' );
+
+ $this->assertEquals( false, $title->isNamespaceIdKnown() );
+ $this->assertEquals( 'this', $title->getNamespaceName() );
+ $this->assertEquals( 'that', $title->getText() );
+ }
+
+ public function testUnknownNamespaceError( ) {
+ $this->setExpectedException( 'MWException' );
+ $title = new ForeignTitle( null, 'this', 'that' );
+ $title->getNamespaceId();
+ }
+
+ public function fullTextProvider() {
+ return array(
+ array(
+ new ForeignTitle( 20, 'Contributor', 'JohnDoe' ),
+ 'Contributor:JohnDoe'
+ ),
+ array(
+ new ForeignTitle( '1', 'Discussion', 'Capital' ),
+ 'Discussion:Capital'
+ ),
+ array(
+ new ForeignTitle( 0, '', 'MainNamespace' ),
+ 'MainNamespace'
+ ),
+ array(
+ new ForeignTitle( 4, 'Some ns', 'Article title with spaces' ),
+ 'Some_ns:Article_title_with_spaces'
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider fullTextProvider
+ */
+ public function testFullText( ForeignTitle $title, $fullText ) {
+ $this->assertEquals( $fullText, $title->getFullText() );
+ }
+}
diff --git a/tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php b/tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php
index 4171c10e..cd0d0b1c 100644
--- a/tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php
+++ b/tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php
@@ -16,7 +16,6 @@
* http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @license GPL 2+
* @author Daniel Kinzler
*/
diff --git a/tests/phpunit/includes/title/MediaWikiTitleCodecTest.php b/tests/phpunit/includes/title/MediaWikiTitleCodecTest.php
index f95b3050..78d304c1 100644
--- a/tests/phpunit/includes/title/MediaWikiTitleCodecTest.php
+++ b/tests/phpunit/includes/title/MediaWikiTitleCodecTest.php
@@ -16,7 +16,6 @@
* http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @license GPL 2+
* @author Daniel Kinzler
*/
@@ -39,6 +38,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
'wgLang' => Language::factory( 'en' ),
'wgAllowUserJs' => false,
'wgDefaultLanguageVariant' => false,
+ 'wgMetaNamespace' => 'Project',
'wgLocalInterwikis' => array( 'localtestiw' ),
'wgCapitalLinks' => true,
@@ -82,6 +82,8 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
protected function makeCodec( $lang ) {
$gender = $this->getGenderCache();
$lang = Language::factory( $lang );
+ // language object can came from cache, which does not respect test settings
+ $lang->resetNamespaces();
return new MediaWikiTitleCodec( $lang, $gender );
}
@@ -367,13 +369,6 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
/**
* @dataProvider provideGetNamespaceName
- *
- * @param int $namespace
- * @param string $text
- * @param string $lang
- * @param string $expected
- *
- * @internal param \TitleValue $title
*/
public function testGetNamespaceName( $namespace, $text, $lang, $expected ) {
$codec = $this->makeCodec( $lang );
diff --git a/tests/phpunit/includes/title/NaiveForeignTitleFactoryTest.php b/tests/phpunit/includes/title/NaiveForeignTitleFactoryTest.php
new file mode 100644
index 00000000..504e8712
--- /dev/null
+++ b/tests/phpunit/includes/title/NaiveForeignTitleFactoryTest.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author This, that and the other
+ */
+
+/**
+ * @covers NaiveForeignTitleFactory
+ *
+ * @group Title
+ */
+class NaiveForeignTitleFactoryTest extends MediaWikiTestCase {
+
+ public function basicProvider() {
+ return array(
+ array(
+ 'MainNamespaceArticle', 0,
+ new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+ ),
+ array(
+ 'MainNamespaceArticle', null,
+ new ForeignTitle( null, '', 'MainNamespaceArticle' ),
+ ),
+ array(
+ 'Talk:Nice_talk', 1,
+ new ForeignTitle( 1, 'Talk', 'Nice_talk' ),
+ ),
+ array(
+ 'Bogus:Nice_talk', 0,
+ new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+ ),
+ array(
+ 'Bogus:Nice_talk', 9000, // non-existent local namespace ID
+ new ForeignTitle( 9000, 'Bogus', 'Nice_talk' ),
+ ),
+ array(
+ 'Bogus:Nice_talk', 4, // existing local namespace ID
+ new ForeignTitle( 4, 'Bogus', 'Nice_talk' ),
+ ),
+ array(
+ 'Talk:Extra:Nice_talk', 1,
+ new ForeignTitle( 1, 'Talk', 'Extra:Nice_talk' ),
+ ),
+ array(
+ 'Talk:Extra:Nice_talk', null,
+ new ForeignTitle( null, 'Talk', 'Extra:Nice_talk' ),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider basicProvider
+ */
+ public function testBasic( $title, $ns, ForeignTitle $foreignTitle ) {
+ $factory = new NaiveForeignTitleFactory();
+ $testTitle = $factory->createForeignTitle( $title, $ns );
+
+ $this->assertEquals( $testTitle->isNamespaceIdKnown(),
+ $foreignTitle->isNamespaceIdKnown() );
+
+ if (
+ $testTitle->isNamespaceIdKnown() &&
+ $foreignTitle->isNamespaceIdKnown()
+ ) {
+ $this->assertEquals( $testTitle->getNamespaceId(),
+ $foreignTitle->getNamespaceId() );
+ }
+
+ $this->assertEquals( $testTitle->getNamespaceName(),
+ $foreignTitle->getNamespaceName() );
+ $this->assertEquals( $testTitle->getText(), $foreignTitle->getText() );
+
+ $this->assertEquals( str_replace( ' ', '_', $title ),
+ $foreignTitle->getFullText() );
+ }
+}
diff --git a/tests/phpunit/includes/title/NaiveImportTitleFactoryTest.php b/tests/phpunit/includes/title/NaiveImportTitleFactoryTest.php
new file mode 100644
index 00000000..98b414e0
--- /dev/null
+++ b/tests/phpunit/includes/title/NaiveImportTitleFactoryTest.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author This, that and the other
+ */
+
+/**
+ * @covers NaiveImportTitleFactory
+ *
+ * @group Title
+ */
+class NaiveImportTitleFactoryTest extends MediaWikiTestCase {
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->setMwGlobals( array(
+ 'wgLanguageCode' => 'en',
+ 'wgContLang' => Language::factory( 'en' ),
+ 'wgExtraNamespaces' => array( 100 => 'Portal' ),
+ ) );
+ }
+
+ public function basicProvider() {
+ return array(
+ array(
+ new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+ Title::newFromText( 'MainNamespaceArticle' )
+ ),
+ array(
+ new ForeignTitle( null, '', 'MainNamespaceArticle' ),
+ Title::newFromText( 'MainNamespaceArticle' )
+ ),
+ array(
+ new ForeignTitle( 1, 'Discussion', 'Nice_talk' ),
+ Title::newFromText( 'Talk:Nice_talk' )
+ ),
+ array(
+ new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+ Title::newFromText( 'Bogus:Nice_talk' )
+ ),
+ array(
+ new ForeignTitle( 100, 'Bogus', 'Nice_talk' ),
+ Title::newFromText( 'Bogus:Nice_talk' ) // not Portal:Nice_talk
+ ),
+ array(
+ new ForeignTitle( 1, 'Bogus', 'Nice_talk' ),
+ Title::newFromText( 'Talk:Nice_talk' ) // not Bogus:Nice_talk
+ ),
+ array(
+ new ForeignTitle( 100, 'Portal', 'Nice_talk' ),
+ Title::newFromText( 'Portal:Nice_talk' )
+ ),
+ array(
+ new ForeignTitle( 724, 'Portal', 'Nice_talk' ),
+ Title::newFromText( 'Portal:Nice_talk' )
+ ),
+ array(
+ new ForeignTitle( 2, 'Portal', 'Nice_talk' ),
+ Title::newFromText( 'User:Nice_talk' )
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider basicProvider
+ */
+ public function testBasic( ForeignTitle $foreignTitle, Title $title ) {
+ $factory = new NaiveImportTitleFactory();
+ $testTitle = $factory->createTitleFromForeignTitle( $foreignTitle );
+
+ $this->assertTrue( $title->equals( $testTitle ) );
+ }
+}
diff --git a/tests/phpunit/includes/title/NamespaceAwareForeignTitleFactoryTest.php b/tests/phpunit/includes/title/NamespaceAwareForeignTitleFactoryTest.php
new file mode 100644
index 00000000..9cb195cc
--- /dev/null
+++ b/tests/phpunit/includes/title/NamespaceAwareForeignTitleFactoryTest.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author This, that and the other
+ */
+
+/**
+ * @covers NamespaceAwareForeignTitleFactory
+ *
+ * @group Title
+ */
+class NamespaceAwareForeignTitleFactoryTest extends MediaWikiTestCase {
+
+ public function basicProvider() {
+ return array(
+ array(
+ 'MainNamespaceArticle', 0,
+ new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+ ),
+ array(
+ 'MainNamespaceArticle', null,
+ new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+ ),
+ array(
+ 'Talk:Nice_talk', 1,
+ new ForeignTitle( 1, 'Talk', 'Nice_talk' ),
+ ),
+ array(
+ 'Bogus:Nice_talk', 0,
+ new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+ ),
+ array(
+ 'Bogus:Nice_talk', null,
+ new ForeignTitle( 9000, 'Bogus', 'Nice_talk' ),
+ ),
+ array(
+ 'Bogus:Nice_talk', 4,
+ new ForeignTitle( 4, 'Bogus', 'Nice_talk' ),
+ ),
+ array(
+ 'Bogus:Nice_talk', 1,
+ new ForeignTitle( 1, 'Talk', 'Nice_talk' ),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider basicProvider
+ */
+ public function testBasic( $title, $ns, ForeignTitle $foreignTitle ) {
+
+ $foreignNamespaces = array(
+ 0 => '', 1 => 'Talk', 100 => 'Portal', 9000 => 'Bogus'
+ );
+
+ $factory = new NamespaceAwareForeignTitleFactory( $foreignNamespaces );
+ $testTitle = $factory->createForeignTitle( $title, $ns );
+
+ $this->assertEquals( $testTitle->isNamespaceIdKnown(),
+ $foreignTitle->isNamespaceIdKnown() );
+
+ if (
+ $testTitle->isNamespaceIdKnown() &&
+ $foreignTitle->isNamespaceIdKnown()
+ ) {
+ $this->assertEquals( $testTitle->getNamespaceId(),
+ $foreignTitle->getNamespaceId() );
+ }
+
+ $this->assertEquals( $testTitle->getNamespaceName(),
+ $foreignTitle->getNamespaceName() );
+ $this->assertEquals( $testTitle->getText(), $foreignTitle->getText() );
+ }
+}
diff --git a/tests/phpunit/includes/title/NamespaceImportTitleFactoryTest.php b/tests/phpunit/includes/title/NamespaceImportTitleFactoryTest.php
new file mode 100644
index 00000000..d6fe6848
--- /dev/null
+++ b/tests/phpunit/includes/title/NamespaceImportTitleFactoryTest.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author This, that and the other
+ */
+
+/**
+ * @covers NamespaceImportTitleFactory
+ *
+ * @group Title
+ */
+class NamespaceImportTitleFactoryTest extends MediaWikiTestCase {
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->setMwGlobals( array(
+ 'wgLanguageCode' => 'en',
+ 'wgContLang' => Language::factory( 'en' ),
+ ) );
+ }
+
+ public function basicProvider() {
+ return array(
+ array(
+ new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+ 0,
+ Title::newFromText( 'MainNamespaceArticle' )
+ ),
+ array(
+ new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+ 2,
+ Title::newFromText( 'User:MainNamespaceArticle' )
+ ),
+ array(
+ new ForeignTitle( 1, 'Discussion', 'Nice_talk' ),
+ 0,
+ Title::newFromText( 'Nice_talk' )
+ ),
+ array(
+ new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+ 0,
+ Title::newFromText( 'Bogus:Nice_talk' )
+ ),
+ array(
+ new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+ 2,
+ Title::newFromText( 'User:Bogus:Nice_talk' )
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider basicProvider
+ */
+ public function testBasic( ForeignTitle $foreignTitle, $ns, Title $title ) {
+ $factory = new NamespaceImportTitleFactory( $ns );
+ $testTitle = $factory->createTitleFromForeignTitle( $foreignTitle );
+
+ $this->assertTrue( $title->equals( $testTitle ) );
+ }
+}
diff --git a/tests/phpunit/includes/title/SubpageImportTitleFactoryTest.php b/tests/phpunit/includes/title/SubpageImportTitleFactoryTest.php
new file mode 100644
index 00000000..d5c17f3e
--- /dev/null
+++ b/tests/phpunit/includes/title/SubpageImportTitleFactoryTest.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author This, that and the other
+ */
+
+/**
+ * @covers SubpageImportTitleFactory
+ *
+ * @group Title
+ */
+class SubpageImportTitleFactoryTest extends MediaWikiTestCase {
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->setMwGlobals( array(
+ 'wgLanguageCode' => 'en',
+ 'wgContLang' => Language::factory( 'en' ),
+ 'wgNamespacesWithSubpages' => array( 0 => false, 2 => true ),
+ ) );
+ }
+
+ public function basicProvider() {
+ return array(
+ array(
+ new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+ Title::newFromText( 'User:Graham' ),
+ Title::newFromText( 'User:Graham/MainNamespaceArticle' )
+ ),
+ array(
+ new ForeignTitle( 1, 'Discussion', 'Nice_talk' ),
+ Title::newFromText( 'User:Graham' ),
+ Title::newFromText( 'User:Graham/Discussion:Nice_talk' )
+ ),
+ array(
+ new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+ Title::newFromText( 'User:Graham' ),
+ Title::newFromText( 'User:Graham/Bogus:Nice_talk' )
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider basicProvider
+ */
+ public function testBasic( ForeignTitle $foreignTitle, Title $rootPage,
+ Title $title ) {
+
+ $factory = new SubpageImportTitleFactory( $rootPage );
+ $testTitle = $factory->createTitleFromForeignTitle( $foreignTitle );
+
+ $this->assertTrue( $testTitle->equals( $title ) );
+ }
+
+ public function failureProvider() {
+ return array(
+ array(
+ Title::newFromText( 'Graham' ),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider failureProvider
+ */
+ public function testFailures( Title $rootPage ) {
+ $this->setExpectedException( 'MWException' );
+ new SubpageImportTitleFactory( $rootPage );
+ }
+}
diff --git a/tests/phpunit/includes/title/TitleValueTest.php b/tests/phpunit/includes/title/TitleValueTest.php
index 3ba008d6..184198d2 100644
--- a/tests/phpunit/includes/title/TitleValueTest.php
+++ b/tests/phpunit/includes/title/TitleValueTest.php
@@ -16,7 +16,6 @@
* http://www.gnu.org/copyleft/gpl.html
*
* @file
- * @license GPL 2+
* @author Daniel Kinzler
*/
diff --git a/tests/phpunit/includes/upload/UploadBaseTest.php b/tests/phpunit/includes/upload/UploadBaseTest.php
index 3d3b0068..9441b77f 100644
--- a/tests/phpunit/includes/upload/UploadBaseTest.php
+++ b/tests/phpunit/includes/upload/UploadBaseTest.php
@@ -9,21 +9,17 @@ class UploadBaseTest extends MediaWikiTestCase {
protected $upload;
protected function setUp() {
- global $wgHooks;
parent::setUp();
$this->upload = new UploadTestHandler;
- $this->hooks = $wgHooks;
- $wgHooks['InterwikiLoadPrefix'][] = function ( $prefix, &$data ) {
- return false;
- };
- }
-
- protected function tearDown() {
- global $wgHooks;
- $wgHooks = $this->hooks;
- parent::tearDown();
+ $this->setMwGlobals( 'wgHooks', array(
+ 'InterwikiLoadPrefix' => array(
+ function ( $prefix, &$data ) {
+ return false;
+ }
+ ),
+ ) );
}
/**
@@ -97,7 +93,7 @@ class UploadBaseTest extends MediaWikiTestCase {
// Helper used to create an empty file of size $size.
private function createFileOfSize( $size ) {
- $filename = tempnam( wfTempDir(), "mwuploadtest" );
+ $filename = $this->getNewTempFile();
$fh = fopen( $filename, 'w' );
ftruncate( $fh, $size );
@@ -112,22 +108,21 @@ class UploadBaseTest extends MediaWikiTestCase {
* This method should be abstracted so we can test different settings.
*/
public function testMaxUploadSize() {
- global $wgMaxUploadSize;
- $savedGlobal = $wgMaxUploadSize; // save global
- global $wgFileExtensions;
- $wgFileExtensions[] = 'txt';
-
- $wgMaxUploadSize = 100;
+ $this->setMwGlobals( array(
+ 'wgMaxUploadSize' => 100,
+ 'wgFileExtensions' => array(
+ 'txt',
+ ),
+ ) );
- $filename = $this->createFileOfSize( $wgMaxUploadSize );
+ $filename = $this->createFileOfSize( 100 );
$this->upload->initializePathInfo( basename( $filename ) . '.txt', $filename, 100 );
$result = $this->upload->verifyUpload();
- unlink( $filename );
$this->assertEquals(
- array( 'status' => UploadBase::OK ), $result );
-
- $wgMaxUploadSize = $savedGlobal; // restore global
+ array( 'status' => UploadBase::OK ),
+ $result
+ );
}
diff --git a/tests/phpunit/includes/upload/UploadFromUrlTest.php b/tests/phpunit/includes/upload/UploadFromUrlTest.php
index ec56b63e..b7496629 100644
--- a/tests/phpunit/includes/upload/UploadFromUrlTest.php
+++ b/tests/phpunit/includes/upload/UploadFromUrlTest.php
@@ -35,7 +35,10 @@ class UploadFromUrlTest extends ApiTestCase {
wfSetupSession( $sessionId );
- return array( $module->getResultData(), $req );
+ return array(
+ $module->getResult()->getResultData( null, array( 'Strip' => 'all' ) ),
+ $req
+ );
}
/**
diff --git a/tests/phpunit/includes/utils/CdbTest.php b/tests/phpunit/includes/utils/CdbTest.php
deleted file mode 100644
index 487ee1fc..00000000
--- a/tests/phpunit/includes/utils/CdbTest.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-
-/**
- * Test the CDB reader/writer
- * @covers CdbWriterPHP
- * @covers CdbWriterDBA
- */
-class CdbTest extends MediaWikiTestCase {
-
- protected function setUp() {
- parent::setUp();
- if ( !CdbReader::haveExtension() ) {
- $this->markTestSkipped( 'Native CDB support is not available' );
- }
- }
-
- /**
- * @group medium
- */
- public function testCdb() {
- $dir = wfTempDir();
- if ( !is_writable( $dir ) ) {
- $this->markTestSkipped( "Temp dir isn't writable" );
- }
-
- $phpcdbfile = $this->getNewTempFile();
- $dbacdbfile = $this->getNewTempFile();
-
- $w1 = new CdbWriterPHP( $phpcdbfile );
- $w2 = new CdbWriterDBA( $dbacdbfile );
-
- $data = array();
- for ( $i = 0; $i < 1000; $i++ ) {
- $key = $this->randomString();
- $value = $this->randomString();
- $w1->set( $key, $value );
- $w2->set( $key, $value );
-
- if ( !isset( $data[$key] ) ) {
- $data[$key] = $value;
- }
- }
-
- $w1->close();
- $w2->close();
-
- $this->assertEquals(
- md5_file( $phpcdbfile ),
- md5_file( $dbacdbfile ),
- 'same hash'
- );
-
- $r1 = new CdbReaderPHP( $phpcdbfile );
- $r2 = new CdbReaderDBA( $dbacdbfile );
-
- foreach ( $data as $key => $value ) {
- if ( $key === '' ) {
- // Known bug
- continue;
- }
- $v1 = $r1->get( $key );
- $v2 = $r2->get( $key );
-
- $v1 = $v1 === false ? '(not found)' : $v1;
- $v2 = $v2 === false ? '(not found)' : $v2;
-
- # cdbAssert( 'Mismatch', $key, $v1, $v2 );
- $this->cdbAssert( "PHP error", $key, $v1, $value );
- $this->cdbAssert( "DBA error", $key, $v2, $value );
- }
- }
-
- private function randomString() {
- $len = mt_rand( 0, 10 );
- $s = '';
- for ( $j = 0; $j < $len; $j++ ) {
- $s .= chr( mt_rand( 0, 255 ) );
- }
-
- return $s;
- }
-
- private function cdbAssert( $msg, $key, $v1, $v2 ) {
- $this->assertEquals(
- $v2,
- $v1,
- $msg . ', k=' . bin2hex( $key )
- );
- }
-}
diff --git a/tests/phpunit/includes/utils/IPTest.php b/tests/phpunit/includes/utils/IPTest.php
index ebe347fd..09c1587d 100644
--- a/tests/phpunit/includes/utils/IPTest.php
+++ b/tests/phpunit/includes/utils/IPTest.php
@@ -9,7 +9,7 @@
* dataprovider.
*/
-class IPTest extends MediaWikiTestCase {
+class IPTest extends PHPUnit_Framework_TestCase {
/**
* not sure it should be tested with boolean false. hashar 20100924
* @covers IP::isIPAddress
diff --git a/tests/phpunit/includes/utils/MWCryptHKDFTest.php b/tests/phpunit/includes/utils/MWCryptHKDFTest.php
index 7e37534a..73e4c1a9 100644
--- a/tests/phpunit/includes/utils/MWCryptHKDFTest.php
+++ b/tests/phpunit/includes/utils/MWCryptHKDFTest.php
@@ -6,6 +6,12 @@
class MWCryptHKDFTest extends MediaWikiTestCase {
+ protected function setUp() {
+ parent::setUp();
+
+ $this->setMwGlobals( 'wgSecretKey', '5bf1945342e67799cb50704a7fa19ac6' );
+ }
+
/**
* Test basic usage works
*/
diff --git a/tests/phpunit/includes/MWFunctionTest.php b/tests/phpunit/includes/utils/MWFunctionTest.php
index f2a720e8..f4d17999 100644
--- a/tests/phpunit/includes/MWFunctionTest.php
+++ b/tests/phpunit/includes/utils/MWFunctionTest.php
@@ -13,6 +13,7 @@ class MWFunctionTest extends MediaWikiTestCase {
$args = array( $arg1, $arg2, $arg3, $arg4 );
$newObject = new MWBlankClass( $arg1, $arg2, $arg3, $arg4 );
+ $this->hideDeprecated( 'MWFunction::newObj' );
$this->assertEquals(
MWFunction::newObj( 'MWBlankClass', $args )->args,
$newObject->args
diff --git a/tests/phpunit/includes/utils/UIDGeneratorTest.php b/tests/phpunit/includes/utils/UIDGeneratorTest.php
index 50fa3849..0e11ccad 100644
--- a/tests/phpunit/includes/utils/UIDGeneratorTest.php
+++ b/tests/phpunit/includes/utils/UIDGeneratorTest.php
@@ -35,14 +35,14 @@ class UIDGeneratorTest extends MediaWikiTestCase {
$lastId_bin = wfBaseConvert( $lastId, 10, 2 );
$this->assertGreaterThanOrEqual(
- substr( $id_bin, 0, $tbits ),
substr( $lastId_bin, 0, $tbits ),
+ substr( $id_bin, 0, $tbits ),
"New ID timestamp ($id_bin) >= prior one ($lastId_bin)." );
if ( $hostbits ) {
$this->assertEquals(
- substr( $id_bin, 0, -$hostbits ),
- substr( $lastId_bin, 0, -$hostbits ),
+ substr( $id_bin, -$hostbits ),
+ substr( $lastId_bin, -$hostbits ),
"Host ID of ($id_bin) is same as prior one ($lastId_bin)." );
}
diff --git a/tests/phpunit/includes/utils/ZipDirectoryReaderTest.php b/tests/phpunit/includes/utils/ZipDirectoryReaderTest.php
index 34ffb535..05d07d45 100644
--- a/tests/phpunit/includes/utils/ZipDirectoryReaderTest.php
+++ b/tests/phpunit/includes/utils/ZipDirectoryReaderTest.php
@@ -4,7 +4,7 @@
* @covers ZipDirectoryReader
* NOTE: this test is more like an integration test than a unit test
*/
-class ZipDirectoryReaderTest extends MediaWikiTestCase {
+class ZipDirectoryReaderTest extends PHPUnit_Framework_TestCase {
protected $zipDir;
protected $entries;
diff --git a/tests/phpunit/install-phpunit.sh b/tests/phpunit/install-phpunit.sh
deleted file mode 100644
index 022f998e..00000000
--- a/tests/phpunit/install-phpunit.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-
-has_binary () {
- if [ -z `which $1` ]; then
- return 1
- fi
- return 0
-}
-
-if [ `id -u` -ne 0 ]; then
- echo '*** ERROR: Must be root to run'
- exit 1
-fi
-
-if ( has_binary phpunit ); then
- echo PHPUnit already installed
-else if ( has_binary pear ); then
- echo Installing phpunit with pear
- pear channel-discover pear.phpunit.de
- pear channel-discover components.ez.no
- pear channel-discover pear.symfony.com
- pear update-channels
- #Temporary fix for 64597
- pear install --alldeps phpunit/PHPUnit-3.7.35
-else if ( has_binary apt-get ); then
- echo Installing phpunit with apt-get
- apt-get install phpunit
-else if ( has_binary yum ); then
- echo Installing phpunit with yum
- yum install phpunit
-else if ( has_binary port ); then
- echo Installing phpunit with macports
- port install php5-unit
-fi
-fi
-fi
-fi
-fi
diff --git a/tests/phpunit/includes/LanguageConverterTest.php b/tests/phpunit/languages/LanguageConverterTest.php
index d4ccca99..d4ccca99 100644
--- a/tests/phpunit/includes/LanguageConverterTest.php
+++ b/tests/phpunit/languages/LanguageConverterTest.php
diff --git a/tests/phpunit/languages/SpecialPageAliasTest.php b/tests/phpunit/languages/SpecialPageAliasTest.php
index f6d6bc96..a6d9d270 100644
--- a/tests/phpunit/languages/SpecialPageAliasTest.php
+++ b/tests/phpunit/languages/SpecialPageAliasTest.php
@@ -8,7 +8,6 @@
* @group SystemTest
* @group medium
*
- * @licence GNU GPL v2+
* @author Katie Filbert < aude.wiki@gmail.com >
*/
class SpecialPageAliasTest extends MediaWikiTestCase {
diff --git a/tests/phpunit/languages/LanguageAmTest.php b/tests/phpunit/languages/classes/LanguageAmTest.php
index a644f5e0..a644f5e0 100644
--- a/tests/phpunit/languages/LanguageAmTest.php
+++ b/tests/phpunit/languages/classes/LanguageAmTest.php
diff --git a/tests/phpunit/languages/LanguageArTest.php b/tests/phpunit/languages/classes/LanguageArTest.php
index 7b48f236..7b48f236 100644
--- a/tests/phpunit/languages/LanguageArTest.php
+++ b/tests/phpunit/languages/classes/LanguageArTest.php
diff --git a/tests/phpunit/languages/LanguageArqTest.php b/tests/phpunit/languages/classes/LanguageArqTest.php
index 3fa56d78..3fa56d78 100644
--- a/tests/phpunit/languages/LanguageArqTest.php
+++ b/tests/phpunit/languages/classes/LanguageArqTest.php
diff --git a/tests/phpunit/languages/LanguageBeTest.php b/tests/phpunit/languages/classes/LanguageBeTest.php
index 7bd586af..7bd586af 100644
--- a/tests/phpunit/languages/LanguageBeTest.php
+++ b/tests/phpunit/languages/classes/LanguageBeTest.php
diff --git a/tests/phpunit/languages/LanguageBe_taraskTest.php b/tests/phpunit/languages/classes/LanguageBe_taraskTest.php
index 4dd5cdd7..4dd5cdd7 100644
--- a/tests/phpunit/languages/LanguageBe_taraskTest.php
+++ b/tests/phpunit/languages/classes/LanguageBe_taraskTest.php
diff --git a/tests/phpunit/languages/LanguageBhoTest.php b/tests/phpunit/languages/classes/LanguageBhoTest.php
index 187bfbbc..187bfbbc 100644
--- a/tests/phpunit/languages/LanguageBhoTest.php
+++ b/tests/phpunit/languages/classes/LanguageBhoTest.php
diff --git a/tests/phpunit/languages/LanguageBsTest.php b/tests/phpunit/languages/classes/LanguageBsTest.php
index 7aca2ab1..7aca2ab1 100644
--- a/tests/phpunit/languages/LanguageBsTest.php
+++ b/tests/phpunit/languages/classes/LanguageBsTest.php
diff --git a/tests/phpunit/languages/LanguageCsTest.php b/tests/phpunit/languages/classes/LanguageCsTest.php
index da9e6b88..da9e6b88 100644
--- a/tests/phpunit/languages/LanguageCsTest.php
+++ b/tests/phpunit/languages/classes/LanguageCsTest.php
diff --git a/tests/phpunit/languages/LanguageCuTest.php b/tests/phpunit/languages/classes/LanguageCuTest.php
index 07193172..07193172 100644
--- a/tests/phpunit/languages/LanguageCuTest.php
+++ b/tests/phpunit/languages/classes/LanguageCuTest.php
diff --git a/tests/phpunit/languages/LanguageCyTest.php b/tests/phpunit/languages/classes/LanguageCyTest.php
index eaf663a8..eaf663a8 100644
--- a/tests/phpunit/languages/LanguageCyTest.php
+++ b/tests/phpunit/languages/classes/LanguageCyTest.php
diff --git a/tests/phpunit/languages/LanguageDsbTest.php b/tests/phpunit/languages/classes/LanguageDsbTest.php
index 94c11bcc..94c11bcc 100644
--- a/tests/phpunit/languages/LanguageDsbTest.php
+++ b/tests/phpunit/languages/classes/LanguageDsbTest.php
diff --git a/tests/phpunit/languages/LanguageFrTest.php b/tests/phpunit/languages/classes/LanguageFrTest.php
index 46b65011..46b65011 100644
--- a/tests/phpunit/languages/LanguageFrTest.php
+++ b/tests/phpunit/languages/classes/LanguageFrTest.php
diff --git a/tests/phpunit/languages/LanguageGaTest.php b/tests/phpunit/languages/classes/LanguageGaTest.php
index c009f56b..c009f56b 100644
--- a/tests/phpunit/languages/LanguageGaTest.php
+++ b/tests/phpunit/languages/classes/LanguageGaTest.php
diff --git a/tests/phpunit/languages/LanguageGdTest.php b/tests/phpunit/languages/classes/LanguageGdTest.php
index b89b4df9..b89b4df9 100644
--- a/tests/phpunit/languages/LanguageGdTest.php
+++ b/tests/phpunit/languages/classes/LanguageGdTest.php
diff --git a/tests/phpunit/languages/LanguageGvTest.php b/tests/phpunit/languages/classes/LanguageGvTest.php
index fc58022a..e6a0cf07 100644
--- a/tests/phpunit/languages/LanguageGvTest.php
+++ b/tests/phpunit/languages/classes/LanguageGvTest.php
@@ -37,7 +37,7 @@ class LanguageGvTest extends LanguageClassesTestCase {
array( 'other', 23 ),
array( 'other', 50 ),
array( 'few', 60 ),
- array( 'other', 80 ),
+ array( 'few', 80 ),
array( 'few', 100 )
);
}
diff --git a/tests/phpunit/languages/LanguageHeTest.php b/tests/phpunit/languages/classes/LanguageHeTest.php
index c382244f..c382244f 100644
--- a/tests/phpunit/languages/LanguageHeTest.php
+++ b/tests/phpunit/languages/classes/LanguageHeTest.php
diff --git a/tests/phpunit/languages/LanguageHiTest.php b/tests/phpunit/languages/classes/LanguageHiTest.php
index f6d2c9e9..f6d2c9e9 100644
--- a/tests/phpunit/languages/LanguageHiTest.php
+++ b/tests/phpunit/languages/classes/LanguageHiTest.php
diff --git a/tests/phpunit/languages/LanguageHrTest.php b/tests/phpunit/languages/classes/LanguageHrTest.php
index 644c5255..644c5255 100644
--- a/tests/phpunit/languages/LanguageHrTest.php
+++ b/tests/phpunit/languages/classes/LanguageHrTest.php
diff --git a/tests/phpunit/languages/LanguageHsbTest.php b/tests/phpunit/languages/classes/LanguageHsbTest.php
index f95a43bf..f95a43bf 100644
--- a/tests/phpunit/languages/LanguageHsbTest.php
+++ b/tests/phpunit/languages/classes/LanguageHsbTest.php
diff --git a/tests/phpunit/languages/LanguageHuTest.php b/tests/phpunit/languages/classes/LanguageHuTest.php
index ee9197d7..ee9197d7 100644
--- a/tests/phpunit/languages/LanguageHuTest.php
+++ b/tests/phpunit/languages/classes/LanguageHuTest.php
diff --git a/tests/phpunit/languages/LanguageHyTest.php b/tests/phpunit/languages/classes/LanguageHyTest.php
index 92e0ef94..92e0ef94 100644
--- a/tests/phpunit/languages/LanguageHyTest.php
+++ b/tests/phpunit/languages/classes/LanguageHyTest.php
diff --git a/tests/phpunit/languages/LanguageKshTest.php b/tests/phpunit/languages/classes/LanguageKshTest.php
index 568a3780..568a3780 100644
--- a/tests/phpunit/languages/LanguageKshTest.php
+++ b/tests/phpunit/languages/classes/LanguageKshTest.php
diff --git a/tests/phpunit/languages/LanguageLnTest.php b/tests/phpunit/languages/classes/LanguageLnTest.php
index 10b3234f..10b3234f 100644
--- a/tests/phpunit/languages/LanguageLnTest.php
+++ b/tests/phpunit/languages/classes/LanguageLnTest.php
diff --git a/tests/phpunit/languages/LanguageLtTest.php b/tests/phpunit/languages/classes/LanguageLtTest.php
index 30642f62..30642f62 100644
--- a/tests/phpunit/languages/LanguageLtTest.php
+++ b/tests/phpunit/languages/classes/LanguageLtTest.php
diff --git a/tests/phpunit/languages/LanguageLvTest.php b/tests/phpunit/languages/classes/LanguageLvTest.php
index 7120cfe3..7120cfe3 100644
--- a/tests/phpunit/languages/LanguageLvTest.php
+++ b/tests/phpunit/languages/classes/LanguageLvTest.php
diff --git a/tests/phpunit/languages/LanguageMgTest.php b/tests/phpunit/languages/classes/LanguageMgTest.php
index 65e8fd7b..65e8fd7b 100644
--- a/tests/phpunit/languages/LanguageMgTest.php
+++ b/tests/phpunit/languages/classes/LanguageMgTest.php
diff --git a/tests/phpunit/languages/LanguageMkTest.php b/tests/phpunit/languages/classes/LanguageMkTest.php
index ed155263..ed155263 100644
--- a/tests/phpunit/languages/LanguageMkTest.php
+++ b/tests/phpunit/languages/classes/LanguageMkTest.php
diff --git a/tests/phpunit/languages/LanguageMlTest.php b/tests/phpunit/languages/classes/LanguageMlTest.php
index 4fa45ce3..4fa45ce3 100644
--- a/tests/phpunit/languages/LanguageMlTest.php
+++ b/tests/phpunit/languages/classes/LanguageMlTest.php
diff --git a/tests/phpunit/languages/LanguageMoTest.php b/tests/phpunit/languages/classes/LanguageMoTest.php
index e0e54ca8..e0e54ca8 100644
--- a/tests/phpunit/languages/LanguageMoTest.php
+++ b/tests/phpunit/languages/classes/LanguageMoTest.php
diff --git a/tests/phpunit/languages/LanguageMtTest.php b/tests/phpunit/languages/classes/LanguageMtTest.php
index 96d2bc92..96d2bc92 100644
--- a/tests/phpunit/languages/LanguageMtTest.php
+++ b/tests/phpunit/languages/classes/LanguageMtTest.php
diff --git a/tests/phpunit/languages/LanguageNlTest.php b/tests/phpunit/languages/classes/LanguageNlTest.php
index 26bd691a..26bd691a 100644
--- a/tests/phpunit/languages/LanguageNlTest.php
+++ b/tests/phpunit/languages/classes/LanguageNlTest.php
diff --git a/tests/phpunit/languages/LanguageNsoTest.php b/tests/phpunit/languages/classes/LanguageNsoTest.php
index 18efd736..18efd736 100644
--- a/tests/phpunit/languages/LanguageNsoTest.php
+++ b/tests/phpunit/languages/classes/LanguageNsoTest.php
diff --git a/tests/phpunit/languages/LanguagePlTest.php b/tests/phpunit/languages/classes/LanguagePlTest.php
index d180037b..d180037b 100644
--- a/tests/phpunit/languages/LanguagePlTest.php
+++ b/tests/phpunit/languages/classes/LanguagePlTest.php
diff --git a/tests/phpunit/languages/LanguageRoTest.php b/tests/phpunit/languages/classes/LanguageRoTest.php
index ae7816bc..ae7816bc 100644
--- a/tests/phpunit/languages/LanguageRoTest.php
+++ b/tests/phpunit/languages/classes/LanguageRoTest.php
diff --git a/tests/phpunit/languages/LanguageRuTest.php b/tests/phpunit/languages/classes/LanguageRuTest.php
index f64fc722..1381afbf 100644
--- a/tests/phpunit/languages/LanguageRuTest.php
+++ b/tests/phpunit/languages/classes/LanguageRuTest.php
@@ -13,7 +13,7 @@ class LanguageRuTest extends LanguageClassesTestCase {
* @covers Language::convertPlural
*/
public function testPlural( $result, $value ) {
- $forms = array( 'one', 'many', 'other' );
+ $forms = array( 'one', 'few', 'many', 'other' );
$this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
}
@@ -22,9 +22,9 @@ class LanguageRuTest extends LanguageClassesTestCase {
* @covers Language::convertPlural
*/
public function testExplicitPlural() {
- $forms = array( 'one', 'many', 'other', '12=dozen' );
+ $forms = array( 'one', 'few', 'many', 'other', '12=dozen' );
$this->assertEquals( 'dozen', $this->getLang()->convertPlural( 12, $forms ) );
- $forms = array( 'one', 'many', '100=hundred', 'other', '12=dozen' );
+ $forms = array( 'one', 'few', 'many', '100=hundred', 'other', '12=dozen' );
$this->assertEquals( 'hundred', $this->getLang()->convertPlural( 100, $forms ) );
}
@@ -42,10 +42,10 @@ class LanguageRuTest extends LanguageClassesTestCase {
array( 'many', 11 ),
array( 'one', 91 ),
array( 'one', 121 ),
- array( 'other', 2 ),
- array( 'other', 3 ),
- array( 'other', 4 ),
- array( 'other', 334 ),
+ array( 'few', 2 ),
+ array( 'few', 3 ),
+ array( 'few', 4 ),
+ array( 'few', 334 ),
array( 'many', 5 ),
array( 'many', 15 ),
array( 'many', 120 ),
diff --git a/tests/phpunit/languages/LanguageSeTest.php b/tests/phpunit/languages/classes/LanguageSeTest.php
index 533aa2bc..533aa2bc 100644
--- a/tests/phpunit/languages/LanguageSeTest.php
+++ b/tests/phpunit/languages/classes/LanguageSeTest.php
diff --git a/tests/phpunit/languages/LanguageSgsTest.php b/tests/phpunit/languages/classes/LanguageSgsTest.php
index fa49a4dd..fa49a4dd 100644
--- a/tests/phpunit/languages/LanguageSgsTest.php
+++ b/tests/phpunit/languages/classes/LanguageSgsTest.php
diff --git a/tests/phpunit/languages/LanguageShTest.php b/tests/phpunit/languages/classes/LanguageShTest.php
index 1b390872..1b390872 100644
--- a/tests/phpunit/languages/LanguageShTest.php
+++ b/tests/phpunit/languages/classes/LanguageShTest.php
diff --git a/tests/phpunit/languages/LanguageSkTest.php b/tests/phpunit/languages/classes/LanguageSkTest.php
index cb8a13b8..cb8a13b8 100644
--- a/tests/phpunit/languages/LanguageSkTest.php
+++ b/tests/phpunit/languages/classes/LanguageSkTest.php
diff --git a/tests/phpunit/languages/LanguageSlTest.php b/tests/phpunit/languages/classes/LanguageSlTest.php
index 9783dd80..9783dd80 100644
--- a/tests/phpunit/languages/LanguageSlTest.php
+++ b/tests/phpunit/languages/classes/LanguageSlTest.php
diff --git a/tests/phpunit/languages/LanguageSmaTest.php b/tests/phpunit/languages/classes/LanguageSmaTest.php
index 95cb333c..95cb333c 100644
--- a/tests/phpunit/languages/LanguageSmaTest.php
+++ b/tests/phpunit/languages/classes/LanguageSmaTest.php
diff --git a/tests/phpunit/languages/LanguageSrTest.php b/tests/phpunit/languages/classes/LanguageSrTest.php
index bfb199f3..bfb199f3 100644
--- a/tests/phpunit/languages/LanguageSrTest.php
+++ b/tests/phpunit/languages/classes/LanguageSrTest.php
diff --git a/tests/phpunit/languages/LanguageTiTest.php b/tests/phpunit/languages/classes/LanguageTiTest.php
index e225af97..e225af97 100644
--- a/tests/phpunit/languages/LanguageTiTest.php
+++ b/tests/phpunit/languages/classes/LanguageTiTest.php
diff --git a/tests/phpunit/languages/LanguageTlTest.php b/tests/phpunit/languages/classes/LanguageTlTest.php
index 7ac51c69..20f5bd7f 100644
--- a/tests/phpunit/languages/LanguageTlTest.php
+++ b/tests/phpunit/languages/classes/LanguageTlTest.php
@@ -28,7 +28,9 @@ class LanguageTlTest extends LanguageClassesTestCase {
return array(
array( 'one', 0 ),
array( 'one', 1 ),
- array( 'other', 2 ),
+ array( 'one', 2 ),
+ array( 'other', 4 ),
+ array( 'other', 6 ),
);
}
}
diff --git a/tests/phpunit/languages/LanguageTrTest.php b/tests/phpunit/languages/classes/LanguageTrTest.php
index 2c9905f7..2c9905f7 100644
--- a/tests/phpunit/languages/LanguageTrTest.php
+++ b/tests/phpunit/languages/classes/LanguageTrTest.php
diff --git a/tests/phpunit/languages/LanguageUkTest.php b/tests/phpunit/languages/classes/LanguageUkTest.php
index 9051bcff..9051bcff 100644
--- a/tests/phpunit/languages/LanguageUkTest.php
+++ b/tests/phpunit/languages/classes/LanguageUkTest.php
diff --git a/tests/phpunit/languages/LanguageUzTest.php b/tests/phpunit/languages/classes/LanguageUzTest.php
index 4881103f..4881103f 100644
--- a/tests/phpunit/languages/LanguageUzTest.php
+++ b/tests/phpunit/languages/classes/LanguageUzTest.php
diff --git a/tests/phpunit/languages/LanguageWaTest.php b/tests/phpunit/languages/classes/LanguageWaTest.php
index d05196c0..d05196c0 100644
--- a/tests/phpunit/languages/LanguageWaTest.php
+++ b/tests/phpunit/languages/classes/LanguageWaTest.php
diff --git a/tests/phpunit/maintenance/DumpTestCase.php b/tests/phpunit/maintenance/DumpTestCase.php
index 8b6aef53..8c763970 100644
--- a/tests/phpunit/maintenance/DumpTestCase.php
+++ b/tests/phpunit/maintenance/DumpTestCase.php
@@ -19,7 +19,7 @@ abstract class DumpTestCase extends MediaWikiLangTestCase {
protected $exceptionFromAddDBData = null;
/**
- * Holds the xmlreader used for analyzing an xml dump
+ * Holds the XMLReader used for analyzing an XML dump
*
* @var XMLReader|null
*/
@@ -30,13 +30,15 @@ abstract class DumpTestCase extends MediaWikiLangTestCase {
*
* @param Page $page Page to add the revision to
* @param string $text Revisions text
- * @param string $summary Revisions summare
- * @return array
+ * @param string $summary Revisions summary
+ * @param string $model The model ID (defaults to wikitext)
+ *
* @throws MWException
+ * @return array
*/
- protected function addRevision( Page $page, $text, $summary ) {
+ protected function addRevision( Page $page, $text, $summary, $model = CONTENT_MODEL_WIKITEXT ) {
$status = $page->doEditContent(
- ContentHandler::makeContent( $text, $page->getTitle() ),
+ ContentHandler::makeContent( $text, $page->getTitle(), $model ),
$summary
);
@@ -330,6 +332,12 @@ abstract class DumpTestCase extends MediaWikiLangTestCase {
$this->assertTextNode( "comment", $summary );
$this->skipWhitespace();
+ $this->assertTextNode( "model", $model );
+ $this->skipWhitespace();
+
+ $this->assertTextNode( "format", $format );
+ $this->skipWhitespace();
+
if ( $this->xml->name == "text" ) {
// note: <text> tag may occur here or at the very end.
$text_found = true;
@@ -340,12 +348,6 @@ abstract class DumpTestCase extends MediaWikiLangTestCase {
$this->assertTextNode( "sha1", $text_sha1 );
- $this->assertTextNode( "model", $model );
- $this->skipWhitespace();
-
- $this->assertTextNode( "format", $format );
- $this->skipWhitespace();
-
if ( !$text_found ) {
$this->assertText( $id, $text_id, $text_bytes, $text );
}
diff --git a/tests/phpunit/maintenance/backupTextPassTest.php b/tests/phpunit/maintenance/backupTextPassTest.php
index a37a97c7..a5ef7624 100644
--- a/tests/phpunit/maintenance/backupTextPassTest.php
+++ b/tests/phpunit/maintenance/backupTextPassTest.php
@@ -3,13 +3,13 @@
require_once __DIR__ . "/../../../maintenance/backupTextPass.inc";
/**
- * Tests for page dumps of BackupDumper
+ * Tests for TextPassDumper that rely on the database
*
* @group Database
* @group Dump
* @covers TextPassDumper
*/
-class TextPassDumperTest extends DumpTestCase {
+class TextPassDumperDatabaseTest extends DumpTestCase {
// We'll add several pages, revision and texts. The following variables hold the
// corresponding ids.
@@ -27,6 +27,10 @@ class TextPassDumperTest extends DumpTestCase {
$this->tablesUsed[] = 'revision';
$this->tablesUsed[] = 'text';
+ $this->mergeMwGlobalArrayValue( 'wgContentHandlers', array(
+ "BackupTextPassTestModel" => "BackupTextPassTestModelHandler"
+ ) );
+
$ns = $this->getDefaultWikitextNS();
try {
@@ -61,7 +65,8 @@ class TextPassDumperTest extends DumpTestCase {
$this->pageId3 = $page->getId();
$page->doDeleteArticle( "Testing ;)" );
- // Page from non-default namespace
+ // Page from non-default namespace and model.
+ // ExportTransform applies.
if ( $ns === NS_TALK ) {
// @todo work around this.
@@ -73,7 +78,8 @@ class TextPassDumperTest extends DumpTestCase {
$page = WikiPage::factory( $title );
list( $this->revId4_1, $this->textId4_1 ) = $this->addRevision( $page,
"Talk about BackupDumperTestP1 Text1",
- "Talk BackupDumperTestP1 Summary1" );
+ "Talk BackupDumperTestP1 Summary1",
+ "BackupTextPassTestModel" );
$this->pageId4 = $page->getId();
} catch ( Exception $e ) {
// We'd love to pass $e directly. However, ... see
@@ -141,7 +147,10 @@ class TextPassDumperTest extends DumpTestCase {
$this->assertPageStart( $this->pageId4, NS_TALK, "Talk:BackupDumperTestP1" );
$this->assertRevision( $this->revId4_1, "Talk BackupDumperTestP1 Summary1",
$this->textId4_1, false, "nktofwzd0tl192k3zfepmlzxoax1lpe",
- "Talk about BackupDumperTestP1 Text1" );
+ "TALK ABOUT BACKUPDUMPERTESTP1 TEXT1",
+ false,
+ "BackupTextPassTestModel",
+ "text/plain" );
$this->assertPageEnd();
$this->assertDumpEnd();
@@ -209,7 +218,10 @@ class TextPassDumperTest extends DumpTestCase {
$this->assertPageStart( $this->pageId4, NS_TALK, "Talk:BackupDumperTestP1" );
$this->assertRevision( $this->revId4_1, "Talk BackupDumperTestP1 Summary1",
$this->textId4_1, false, "nktofwzd0tl192k3zfepmlzxoax1lpe",
- "Talk about BackupDumperTestP1 Text1" );
+ "TALK ABOUT BACKUPDUMPERTESTP1 TEXT1",
+ false,
+ "BackupTextPassTestModel",
+ "text/plain" );
$this->assertPageEnd();
$this->assertDumpEnd();
@@ -232,7 +244,9 @@ class TextPassDumperTest extends DumpTestCase {
$this->fail( "Could not open stream for stderr" );
}
- $iterations = 32; // We'll start with that many iterations of revisions in stub
+ $iterations = 32; // We'll start with that many iterations of revisions
+ // in stub. Make sure that the generated volume is above the buffer size
+ // set below. Otherwise, the checkpointing does not trigger.
$lastDuration = 0;
$minDuration = 2; // We want the dump to take at least this many seconds
$checkpointAfter = 0.5; // Generate checkpoint after this many seconds
@@ -250,6 +264,7 @@ class TextPassDumperTest extends DumpTestCase {
$dumper = new TextPassDumper( array( "--stub=file:" . $nameStub,
"--output=" . $checkpointFormat . ":" . $nameOutputDir . "/full",
"--maxtime=1" /*This is in minutes. Fixup is below*/,
+ "--buffersize=32768", // The default of 32 iterations fill up 32KB about twice
"--checkpointfile=checkpoint-%s-%s.xml.gz" ) );
$dumper->setDb( $this->db );
$dumper->maxTimeAllowed = $checkpointAfter; // Patching maxTime from 1 minute
@@ -362,7 +377,10 @@ class TextPassDumperTest extends DumpTestCase {
$this->assertRevision( $this->revId4_1 + $i * self::$numOfRevs,
"Talk BackupDumperTestP1 Summary1",
$this->textId4_1, false, "nktofwzd0tl192k3zfepmlzxoax1lpe",
- "Talk about BackupDumperTestP1 Text1" );
+ "TALK ABOUT BACKUPDUMPERTESTP1 TEXT1",
+ false,
+ "BackupTextPassTestModel",
+ "text/plain" );
$this->assertPageEnd();
$lookingForPage = 1;
@@ -440,10 +458,10 @@ class TextPassDumperTest extends DumpTestCase {
if ( $fname === null ) {
$fname = $this->getNewTempFile();
}
- $header = '<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.7/" '
+ $header = '<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" '
. 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
- . 'xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.7/ '
- . 'http://www.mediawiki.org/xml/export-0.7.xsd" version="0.7" xml:lang="en">
+ . 'xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ '
+ . 'http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
<siteinfo>
<sitename>wikisvn</sitename>
<base>http://localhost/wiki-svn/index.php/Main_Page</base>
@@ -489,10 +507,10 @@ class TextPassDumperTest extends DumpTestCase {
<ip>127.0.0.1</ip>
</contributor>
<comment>BackupDumperTestP1Summary1</comment>
- <sha1>0bolhl6ol7i6x0e7yq91gxgaan39j87</sha1>
<model>wikitext</model>
<format>text/x-wiki</format>
<text id="' . $this->textId1_1 . '" bytes="23" />
+ <sha1>0bolhl6ol7i6x0e7yq91gxgaan39j87</sha1>
</revision>
</page>
';
@@ -507,10 +525,10 @@ class TextPassDumperTest extends DumpTestCase {
<ip>127.0.0.1</ip>
</contributor>
<comment>BackupDumperTestP2Summary1</comment>
- <sha1>jprywrymfhysqllua29tj3sc7z39dl2</sha1>
<model>wikitext</model>
<format>text/x-wiki</format>
<text id="' . $this->textId2_1 . '" bytes="23" />
+ <sha1>jprywrymfhysqllua29tj3sc7z39dl2</sha1>
</revision>
<revision>
<id>' . ( $this->revId2_2 + $i * self::$numOfRevs ) . '</id>
@@ -520,10 +538,10 @@ class TextPassDumperTest extends DumpTestCase {
<ip>127.0.0.1</ip>
</contributor>
<comment>BackupDumperTestP2Summary2</comment>
- <sha1>b7vj5ks32po5m1z1t1br4o7scdwwy95</sha1>
<model>wikitext</model>
<format>text/x-wiki</format>
<text id="' . $this->textId2_2 . '" bytes="23" />
+ <sha1>b7vj5ks32po5m1z1t1br4o7scdwwy95</sha1>
</revision>
<revision>
<id>' . ( $this->revId2_3 + $i * self::$numOfRevs ) . '</id>
@@ -533,10 +551,10 @@ class TextPassDumperTest extends DumpTestCase {
<ip>127.0.0.1</ip>
</contributor>
<comment>BackupDumperTestP2Summary3</comment>
- <sha1>jfunqmh1ssfb8rs43r19w98k28gg56r</sha1>
<model>wikitext</model>
<format>text/x-wiki</format>
<text id="' . $this->textId2_3 . '" bytes="23" />
+ <sha1>jfunqmh1ssfb8rs43r19w98k28gg56r</sha1>
</revision>
<revision>
<id>' . ( $this->revId2_4 + $i * self::$numOfRevs ) . '</id>
@@ -546,10 +564,10 @@ class TextPassDumperTest extends DumpTestCase {
<ip>127.0.0.1</ip>
</contributor>
<comment>BackupDumperTestP2Summary4 extra</comment>
- <sha1>6o1ciaxa6pybnqprmungwofc4lv00wv</sha1>
<model>wikitext</model>
<format>text/x-wiki</format>
<text id="' . $this->textId2_4 . '" bytes="44" />
+ <sha1>6o1ciaxa6pybnqprmungwofc4lv00wv</sha1>
</revision>
</page>
';
@@ -566,10 +584,10 @@ class TextPassDumperTest extends DumpTestCase {
<ip>127.0.0.1</ip>
</contributor>
<comment>Talk BackupDumperTestP1 Summary1</comment>
- <sha1>nktofwzd0tl192k3zfepmlzxoax1lpe</sha1>
- <model>wikitext</model>
- <format>text/x-wiki</format>
+ <model>BackupTextPassTestModel</model>
+ <format>text/plain</format>
<text id="' . $this->textId4_1 . '" bytes="35" />
+ <sha1>nktofwzd0tl192k3zfepmlzxoax1lpe</sha1>
</revision>
</page>
';
@@ -582,3 +600,73 @@ class TextPassDumperTest extends DumpTestCase {
return $fname;
}
}
+
+class BackupTextPassTestModelHandler extends TextContentHandler {
+
+ public function __construct() {
+ parent::__construct( 'BackupTextPassTestModel' );
+ }
+
+ public function exportTransform( $text, $format = null ) {
+ return strtoupper( $text );
+ }
+
+}
+
+/**
+ * Tests for TextPassDumper that do not rely on the database
+ *
+ * (As the Database group is only detected at class level (not method level), we
+ * cannot bring this test case's tests into the above main test case.)
+ *
+ * @group Dump
+ * @covers TextPassDumper
+ */
+class TextPassDumperDatabaselessTest extends MediaWikiLangTestCase {
+ /**
+ * Ensures that setting the buffer size is effective.
+ *
+ * @dataProvider bufferSizeProvider
+ */
+ function testBufferSizeSetting( $expected, $size, $msg ) {
+ $dumper = new TextPassDumperAccessor( array( "--buffersize=" . $size ) );
+ $this->assertEquals( $expected, $dumper->getBufferSize(), $msg);
+ }
+
+ /**
+ * Ensures that setting the buffer size is effective.
+ *
+ * @dataProvider bufferSizeProvider
+ */
+ function bufferSizeProvider() {
+ // expected, bufferSize to initialize with, message
+ return array(
+ array( 512 * 1024, 512 * 1024, "Setting 512KB is not effective" ),
+ array( 8192, 8192, "Setting 8KB is not effective" ),
+ array( 4096, 2048, "Could set buffer size below lower bound" )
+ );
+ }
+}
+
+/**
+ * Accessor for internal state of TextPassDumper
+ *
+ * Do not warrentless add getters here.
+ */
+class TextPassDumperAccessor extends TextPassDumper {
+ /**
+ * Gets the bufferSize.
+ *
+ * If bufferSize setting does not work correctly, testCheckpoint... tests
+ * fail and point in the wrong direction. To aid in troubleshooting when
+ * testCheckpoint... tests break at some point in the future, we test the
+ * bufferSize setting, hence need this accessor.
+ *
+ * (Yes, bufferSize is internal state of the TextPassDumper, but aiding
+ * debugging of testCheckpoint... in the future seems to be worth testing
+ * against it nonetheless.)
+ */
+ public function getBufferSize() {
+ return $this->bufferSize;
+ }
+}
diff --git a/tests/phpunit/phpunit.php b/tests/phpunit/phpunit.php
index 11255043..e59b5063 100644
--- a/tests/phpunit/phpunit.php
+++ b/tests/phpunit/phpunit.php
@@ -93,6 +93,12 @@ class PHPUnitMaintClass extends Maintenance {
public function execute() {
global $IP;
+ // Deregister handler from MWExceptionHandler::installHandle so that PHPUnit's own handler
+ // stays in tact.
+ // Has to in execute() instead of finalSetup(), because finalSetup() runs before
+ // doMaintenance.php includes Setup.php, which calls MWExceptionHandler::installHandle().
+ restore_error_handler();
+
$this->forceFormatServerArgv();
# Make sure we have --configuration or PHPUnit might complain
diff --git a/tests/phpunit/structure/AutoLoaderTest.php b/tests/phpunit/structure/AutoLoaderTest.php
index 2bdc9c9a..cde6547a 100644
--- a/tests/phpunit/structure/AutoLoaderTest.php
+++ b/tests/phpunit/structure/AutoLoaderTest.php
@@ -2,27 +2,22 @@
class AutoLoaderTest extends MediaWikiTestCase {
protected function setUp() {
- global $wgAutoloadLocalClasses, $wgAutoloadClasses;
-
parent::setUp();
// Fancy dance to trigger a rebuild of AutoLoader::$autoloadLocalClassesLower
- $this->testLocalClasses = array(
- 'TestAutoloadedLocalClass' => __DIR__ . '/../data/autoloader/TestAutoloadedLocalClass.php',
- 'TestAutoloadedCamlClass' => __DIR__ . '/../data/autoloader/TestAutoloadedCamlClass.php',
+ $this->mergeMwGlobalArrayValue( 'wgAutoloadLocalClasses', array(
+ 'TestAutoloadedLocalClass' =>
+ __DIR__ . '/../data/autoloader/TestAutoloadedLocalClass.php',
+ 'TestAutoloadedCamlClass' =>
+ __DIR__ . '/../data/autoloader/TestAutoloadedCamlClass.php',
'TestAutoloadedSerializedClass' =>
__DIR__ . '/../data/autoloader/TestAutoloadedSerializedClass.php',
- );
- $this->setMwGlobals(
- 'wgAutoloadLocalClasses',
- $this->testLocalClasses + $wgAutoloadLocalClasses
- );
+ ) );
AutoLoader::resetAutoloadLocalClassesLower();
- $this->testExtensionClasses = array(
+ $this->mergeMwGlobalArrayValue( 'wgAutoloadClasses', array(
'TestAutoloadedClass' => __DIR__ . '/../data/autoloader/TestAutoloadedClass.php',
- );
- $this->setMwGlobals( 'wgAutoloadClasses', $this->testExtensionClasses + $wgAutoloadClasses );
+ ) );
}
/**
@@ -49,7 +44,7 @@ class AutoLoaderTest extends MediaWikiTestCase {
$files = array_unique( $expected );
- foreach ( $files as $file ) {
+ foreach ( $files as $class => $file ) {
// Only prefix $IP if it doesn't have it already.
// Generally local classes don't have it, and those from extensions and test suites do.
if ( substr( $file, 0, 1 ) != '/' && substr( $file, 1, 1 ) != ':' ) {
@@ -58,7 +53,19 @@ class AutoLoaderTest extends MediaWikiTestCase {
$filePath = $file;
}
+ if ( !file_exists( $filePath ) ) {
+ $actual[$class] = "[file '$filePath' does not exist]";
+ continue;
+ }
+
+ wfSuppressWarnings();
$contents = file_get_contents( $filePath );
+ wfRestoreWarnings();
+
+ if ( $contents === false ) {
+ $actual[$class] = "[couldn't read file '$filePath']";
+ continue;
+ }
// We could use token_get_all() here, but this is faster
$matches = array();
@@ -123,10 +130,14 @@ class AutoLoaderTest extends MediaWikiTestCase {
}
function testWrongCaseClass() {
+ $this->setMwGlobals( 'wgAutoloadAttemptLowercase', true );
+
$this->assertTrue( class_exists( 'testautoLoadedcamlCLASS' ) );
}
function testWrongCaseSerializedClass() {
+ $this->setMwGlobals( 'wgAutoloadAttemptLowercase', true );
+
$dummyCereal = 'O:29:"testautoloadedserializedclass":0:{}';
$uncerealized = unserialize( $dummyCereal );
$this->assertFalse( $uncerealized instanceof __PHP_Incomplete_Class,
diff --git a/tests/phpunit/structure/AvailableRightsTest.php b/tests/phpunit/structure/AvailableRightsTest.php
new file mode 100644
index 00000000..51d31aaa
--- /dev/null
+++ b/tests/phpunit/structure/AvailableRightsTest.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * Try to make sure that extensions register all rights in $wgAvailableRights
+ * or via the 'UserGetAllRights' hook.
+ *
+ * @author Marius Hoch < hoo@online.de >
+ */
+class AvailableRightsTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * Returns all rights that should be in $wgAvailableRights + all rights
+ * registered via the 'UserGetAllRights' hook + all "core" rights.
+ *
+ * @return string[]
+ */
+ private function getAllVisibleRights() {
+ global $wgGroupPermissions, $wgRevokePermissions;
+
+ $rights = User::getAllRights();
+
+ foreach( $wgGroupPermissions as $permissions ) {
+ $rights = array_merge( $rights, array_keys( $permissions ) );
+ }
+
+ foreach( $wgRevokePermissions as $permissions ) {
+ $rights = array_merge( $rights, array_keys( $permissions ) );
+ }
+
+ $rights = array_unique( $rights );
+ sort( $rights );
+
+ return $rights;
+ }
+
+ public function testAvailableRights() {
+ $missingRights = array_diff(
+ $this->getAllVisibleRights(),
+ User::getAllRights()
+ );
+
+ $this->assertEquals(
+ array(),
+ // Re-index to produce nicer output, keys are meaningless.
+ array_values( $missingRights ),
+ 'Additional user rights need to be added to $wgAvailableRights or ' .
+ 'via the "UserGetAllRights" hook. See the instructions at: ' .
+ 'https://www.mediawiki.org/wiki/Manual:User_rights#Adding_new_rights'
+ );
+ }
+}
diff --git a/tests/phpunit/structure/ResourcesTest.php b/tests/phpunit/structure/ResourcesTest.php
index 2396ea29..d2b699d9 100644
--- a/tests/phpunit/structure/ResourcesTest.php
+++ b/tests/phpunit/structure/ResourcesTest.php
@@ -12,7 +12,6 @@
* @copyright © 2012, Santhosh Thottingal
* @copyright © 2012, Timo Tijhof
*
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
*/
class ResourcesTest extends MediaWikiTestCase {
@@ -91,6 +90,10 @@ class ResourcesTest extends MediaWikiTestCase {
foreach ( $data['modules'] as $moduleName => $module ) {
$moduleTargets = $module->getTargets();
foreach ( $module->getDependencies() as $dep ) {
+ if ( !isset( $data['modules'][$dep] ) ) {
+ // Missing dependencies reported by testMissingDependencies
+ continue;
+ }
$targets = $data['modules'][$dep]->getTargets();
foreach ( $moduleTargets as $moduleTarget ) {
$this->assertContains(
diff --git a/tests/phpunit/suite.xml b/tests/phpunit/suite.xml
index 574c11e4..1acbc241 100644
--- a/tests/phpunit/suite.xml
+++ b/tests/phpunit/suite.xml
@@ -39,6 +39,7 @@ phpunit.php enables colors for other OSs at runtime
<file>suites/UploadFromUrlTestSuite.php</file>
</testsuite>
<testsuite name="extensions">
+ <directory>structure</directory>
<file>suites/ExtensionsTestSuite.php</file>
<file>suites/ExtensionsParserTestSuite.php</file>
<file>suites/LessTestSuite.php</file>
@@ -57,7 +58,6 @@ phpunit.php enables colors for other OSs at runtime
<directory suffix=".php">../../includes</directory>
<directory suffix=".php">../../languages</directory>
<directory suffix=".php">../../maintenance</directory>
- <directory suffix=".php">../../resources</directory>
<directory suffix=".php">../../skins</directory>
</whitelist>
</filter>
diff --git a/tests/phpunit/suites/ExtensionsTestSuite.php b/tests/phpunit/suites/ExtensionsTestSuite.php
index 116065f8..723328e2 100644
--- a/tests/phpunit/suites/ExtensionsTestSuite.php
+++ b/tests/phpunit/suites/ExtensionsTestSuite.php
@@ -10,7 +10,7 @@ class ExtensionsTestSuite extends PHPUnit_Framework_TestSuite {
parent::__construct();
$paths = array();
// Extensions can return a list of files or directories
- wfRunHooks( 'UnitTestsList', array( &$paths ) );
+ Hooks::run( 'UnitTestsList', array( &$paths ) );
foreach ( $paths as $path ) {
if ( is_dir( $path ) ) {
// If the path is a directory, search for test cases.
diff --git a/tests/qunit/QUnitTestResources.php b/tests/qunit/QUnitTestResources.php
index 15c33f64..17b8b632 100644
--- a/tests/qunit/QUnitTestResources.php
+++ b/tests/qunit/QUnitTestResources.php
@@ -48,7 +48,6 @@ return array(
'tests/qunit/suites/resources/jquery/jquery.autoEllipsis.test.js',
'tests/qunit/suites/resources/jquery/jquery.byteLength.test.js',
'tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js',
- 'tests/qunit/suites/resources/jquery/jquery.client.test.js',
'tests/qunit/suites/resources/jquery/jquery.color.test.js',
'tests/qunit/suites/resources/jquery/jquery.colorUtil.test.js',
'tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js',
@@ -60,18 +59,24 @@ return array(
'tests/qunit/suites/resources/jquery/jquery.placeholder.test.js',
'tests/qunit/suites/resources/jquery/jquery.tabIndex.test.js',
'tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js',
+ 'tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js',
'tests/qunit/suites/resources/jquery/jquery.textSelection.test.js',
'tests/qunit/data/mediawiki.jqueryMsg.data.js',
+ 'tests/qunit/suites/resources/mediawiki/mediawiki.errorLogger.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.jscompat.test.js',
+ 'tests/qunit/suites/resources/mediawiki/mediawiki.messagePoster.factory.test.js',
+ 'tests/qunit/suites/resources/mediawiki/mediawiki.template.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.toc.test.js',
+ 'tests/qunit/suites/resources/mediawiki/mediawiki.track.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.user.test.js',
'tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js',
'tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js',
'tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js',
+ 'tests/qunit/suites/resources/mediawiki.api/mediawiki.api.options.test.js',
'tests/qunit/suites/resources/mediawiki.api/mediawiki.api.parse.test.js',
'tests/qunit/suites/resources/mediawiki.api/mediawiki.api.watch.test.js',
'tests/qunit/suites/resources/mediawiki.special/mediawiki.special.recentchanges.test.js',
@@ -84,7 +89,6 @@ return array(
'jquery.autoEllipsis',
'jquery.byteLength',
'jquery.byteLimit',
- 'jquery.client',
'jquery.color',
'jquery.colorUtil',
'jquery.getAttrs',
@@ -99,13 +103,16 @@ return array(
'jquery.textSelection',
'mediawiki.api',
'mediawiki.api.category',
+ 'mediawiki.api.options',
'mediawiki.api.parse',
'mediawiki.api.watch',
'mediawiki.jqueryMsg',
+ 'mediawiki.messagePoster',
'mediawiki.Title',
'mediawiki.toc',
'mediawiki.Uri',
'mediawiki.user',
+ 'mediawiki.template',
'mediawiki.util',
'mediawiki.special.recentchanges',
'mediawiki.language',
diff --git a/tests/qunit/data/testrunner.js b/tests/qunit/data/testrunner.js
index db312b21..03aaf4af 100644
--- a/tests/qunit/data/testrunner.js
+++ b/tests/qunit/data/testrunner.js
@@ -26,32 +26,20 @@
*/
// When a test() indicates asynchronicity with stop(),
- // allow 10 seconds to pass before killing the test(),
+ // allow 30 seconds to pass before killing the test(),
// and assuming failure.
- QUnit.config.testTimeout = 10 * 1000;
+ QUnit.config.testTimeout = 30 * 1000;
+
+ QUnit.config.requireExpects = true;
// Add a checkbox to QUnit header to toggle MediaWiki ResourceLoader debug mode.
QUnit.config.urlConfig.push( {
id: 'debug',
label: 'Enable ResourceLoaderDebug',
- tooltip: 'Enable debug mode in ResourceLoader'
+ tooltip: 'Enable debug mode in ResourceLoader',
+ value: 'true'
} );
- QUnit.config.requireExpects = true;
-
- /**
- * Load TestSwarm agent
- */
- // Only if the current url indicates that there is a TestSwarm instance watching us
- // (TestSwarm appends swarmURL to the test suites url it loads in iframes).
- // Otherwise this is just a simple view of Special:JavaScriptTest/qunit directly,
- // no point in loading inject.js in that case. Also, make sure that this instance
- // of MediaWiki has actually been configured with the required url to that inject.js
- // script. By default it is false.
- if ( QUnit.urlParams.swarmURL && mw.config.get( 'QUnitTestSwarmInjectJSPath' ) ) {
- jQuery.getScript( QUnit.fixurl( mw.config.get( 'QUnitTestSwarmInjectJSPath' ) ) );
- }
-
/**
* CompletenessTest
*
@@ -256,6 +244,7 @@
},
teardown: function () {
+ var timers;
log( 'MwEnvironment> TEARDOWN for "' + QUnit.config.current.module
+ ': ' + QUnit.config.current.testName + '"' );
@@ -272,9 +261,18 @@
// Check for incomplete animations/requests/etc and throw
// error if there are any.
if ( $.timers && $.timers.length !== 0 ) {
- // Test may need to use fake timers, wait for animations or
- // call $.fx.stop().
- throw new Error( 'Unfinished animations: ' + $.timers.length );
+ timers = $.timers.length;
+ // Tests shoulld use fake timers or wait for animations to complete
+ $.each( $.timers, function ( i, timer ) {
+ var node = timer.elem;
+ mw.log.warn( 'Unfinished animation #' + i + ' in ' + timer.queue + ' queue on ' +
+ mw.html.element( node.nodeName.toLowerCase(), $(node).getAttrs() )
+ );
+ } );
+ // Force animations to stop to give the next test a clean start
+ $.fx.stop();
+
+ throw new Error( 'Unfinished animations: ' + timers );
}
if ( $.active !== undefined && $.active !== 0 ) {
// Test may need to use fake XHR, wait for requests or
diff --git a/tests/qunit/suites/resources/jquery/jquery.accessKeyLabel.test.js b/tests/qunit/suites/resources/jquery/jquery.accessKeyLabel.test.js
index f6ea1b48..4484467d 100644
--- a/tests/qunit/suites/resources/jquery/jquery.accessKeyLabel.test.js
+++ b/tests/qunit/suites/resources/jquery/jquery.accessKeyLabel.test.js
@@ -7,7 +7,7 @@
} ) );
var getAccessKeyPrefixTestData = [
- //ua string, platform string, expected prefix
+ // ua string, platform string, expected prefix
// Internet Explorer
['Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)', 'Win32', 'alt-'],
['Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', 'Win32', 'alt-'],
@@ -27,11 +27,11 @@
['Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30', 'MacIntel', 'ctrl-option-'],
['Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.68 Safari/534.30', 'Linux i686', 'alt-shift-']
],
- //strings appended to title to make sure updateTooltipAccessKeys handles them correctly
+ // strings appended to title to make sure updateTooltipAccessKeys handles them correctly
updateTooltipAccessKeysTestData = [ '', ' [a]', ' [test-a]', ' [alt-b]' ];
function makeInput( title, accessKey ) {
- //The properties aren't escaped, so make sure you don't call this function with values that need to be escaped!
+ // The properties aren't escaped, so make sure you don't call this function with values that need to be escaped!
return '<input title="' + title + '" ' + ( accessKey ? 'accessKey="' + accessKey + '" ' : '' ) + ' />';
}
@@ -46,10 +46,10 @@
} );
QUnit.test( 'updateTooltipAccessKeys - current browser', 2, function ( assert ) {
- var title = $( makeInput ( 'Title', 'a' ) ).updateTooltipAccessKeys().prop( 'title' ),
- //The new title should be something like "Title [alt-a]", but the exact label will depend on the browser.
- //The "a" could be capitalized, and the prefix could be anything, e.g. a simple "^" for ctrl-
- //(no browser is known using such a short prefix, though) or "Alt+Umschalt+" in German Firefox.
+ var title = $( makeInput( 'Title', 'a' ) ).updateTooltipAccessKeys().prop( 'title' ),
+ // The new title should be something like "Title [alt-a]", but the exact label will depend on the browser.
+ // The "a" could be capitalized, and the prefix could be anything, e.g. a simple "^" for ctrl-
+ // (no browser is known using such a short prefix, though) or "Alt+Umschalt+" in German Firefox.
result = /^Title \[(.+)[aA]\]$/.exec( title );
assert.ok( result, 'title should match expected structure.' );
assert.notEqual( result[1], 'test-', 'Prefix used for testing shouldn\'t be used in production.' );
diff --git a/tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js b/tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js
index 22d2af19..0cb9cc81 100644
--- a/tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js
+++ b/tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js
@@ -60,7 +60,7 @@
);
QUnit.start();
- }, 10 );
+ } );
} );
}
diff --git a/tests/qunit/suites/resources/jquery/jquery.client.test.js b/tests/qunit/suites/resources/jquery/jquery.client.test.js
deleted file mode 100644
index c6dd91c4..00000000
--- a/tests/qunit/suites/resources/jquery/jquery.client.test.js
+++ /dev/null
@@ -1,638 +0,0 @@
-( function ( $ ) {
-
- QUnit.module( 'jquery.client', QUnit.newMwEnvironment() );
-
- var uacount = 0,
- // Object keyed by userAgent. Value is an array (human-readable name, client-profile object, navigator.platform value)
- uas = {
- // Internet Explorer 6
- // Internet Explorer 7
- 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)': {
- title: 'Internet Explorer 7',
- platform: 'Win32',
- profile: {
- name: 'msie',
- layout: 'trident',
- layoutVersion: 'unknown',
- platform: 'win',
- version: '7.0',
- versionBase: '7',
- versionNumber: 7
- },
- wikiEditor: {
- ltr: true,
- rtl: false
- }
- },
- // Internet Explorer 8
- // Internet Explorer 9
- // Internet Explorer 10
- 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)': {
- title: 'Internet Explorer 10',
- platform: 'Win32',
- profile: {
- name: 'msie',
- layout: 'trident',
- layoutVersion: 6,
- platform: 'win',
- version: '10.0',
- versionBase: '10',
- versionNumber: 10
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Internet Explorer 11
- 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv 11.0) like Gecko': {
- title: 'Internet Explorer 11',
- platform: 'Win32',
- profile: {
- name: 'msie',
- layout: 'trident',
- layoutVersion: 7,
- platform: 'win',
- version: '11.0',
- versionBase: '11',
- versionNumber: 11
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Internet Explorer 11 - Windows 8.1 x64 Modern UI
- 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; rv:11.0) like Gecko': {
- title: 'Internet Explorer 11',
- platform: 'Win64',
- profile: {
- name: 'msie',
- layout: 'trident',
- layoutVersion: 7,
- platform: 'win',
- version: '11.0',
- versionBase: '11',
- versionNumber: 11
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Internet Explorer 11 - Windows 8.1 x64 desktop UI
- 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko': {
- title: 'Internet Explorer 11',
- platform: 'WOW64',
- profile: {
- name: 'msie',
- layout: 'trident',
- layoutVersion: 7,
- platform: 'win',
- version: '11.0',
- versionBase: '11',
- versionNumber: 11
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Firefox 2
- // Firefox 3.5
- 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.19) Gecko/20110420 Firefox/3.5.19': {
- title: 'Firefox 3.5',
- platform: 'MacIntel',
- profile: {
- name: 'firefox',
- layout: 'gecko',
- layoutVersion: 20110420,
- platform: 'mac',
- version: '3.5.19',
- versionBase: '3',
- versionNumber: 3.5
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Firefox 3.6
- 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.10 (maverick) Firefox/3.6.17': {
- title: 'Firefox 3.6',
- platform: 'Linux i686',
- profile: {
- name: 'firefox',
- layout: 'gecko',
- layoutVersion: 20110422,
- platform: 'linux',
- version: '3.6.17',
- versionBase: '3',
- versionNumber: 3.6
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Firefox 4
- 'Mozilla/5.0 (Windows NT 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1': {
- title: 'Firefox 4',
- platform: 'Win32',
- profile: {
- name: 'firefox',
- layout: 'gecko',
- layoutVersion: 20100101,
- platform: 'win',
- version: '4.0.1',
- versionBase: '4',
- versionNumber: 4
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Firefox 10 nightly build
- 'Mozilla/5.0 (X11; Linux x86_64; rv:10.0a1) Gecko/20111103 Firefox/10.0a1': {
- title: 'Firefox 10 nightly',
- platform: 'Linux',
- profile: {
- name: 'firefox',
- layout: 'gecko',
- layoutVersion: 20111103,
- platform: 'linux',
- version: '10.0a1',
- versionBase: '10',
- versionNumber: 10
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Iceweasel 10.0.6
- 'Mozilla/5.0 (X11; Linux i686; rv:10.0.6) Gecko/20100101 Iceweasel/10.0.6': {
- title: 'Iceweasel 10.0.6',
- platform: 'Linux',
- profile: {
- name: 'iceweasel',
- layout: 'gecko',
- layoutVersion: 20100101,
- platform: 'linux',
- version: '10.0.6',
- versionBase: '10',
- versionNumber: 10
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Iceweasel 15.0.1
- 'Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1 Iceweasel/15.0.1': {
- title: 'Iceweasel 15.0.1',
- platform: 'Linux',
- profile: {
- name: 'iceweasel',
- layout: 'gecko',
- layoutVersion: 20100101,
- platform: 'linux',
- version: '15.0.1',
- versionBase: '15',
- versionNumber: 15
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Firefox 5
- // Safari 3
- // Safari 4
- 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; nl-nl) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7': {
- title: 'Safari 4',
- platform: 'MacIntel',
- profile: {
- name: 'safari',
- layout: 'webkit',
- layoutVersion: 531,
- platform: 'mac',
- version: '4.0.5',
- versionBase: '4',
- versionNumber: 4
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- 'Mozilla/5.0 (Windows; U; Windows NT 6.0; cs-CZ) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7': {
- title: 'Safari 4',
- platform: 'Win32',
- profile: {
- name: 'safari',
- layout: 'webkit',
- layoutVersion: 533,
- platform: 'win',
- version: '4.0.5',
- versionBase: '4',
- versionNumber: 4
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Safari 5
- // Safari 6
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.29.13 (KHTML, like Gecko) Version/6.0.4 Safari/536.29.13': {
- title: 'Safari 6',
- platform: 'MacIntel',
- profile: {
- name: 'safari',
- layout: 'webkit',
- layoutVersion: 536,
- platform: 'mac',
- version: '6.0.4',
- versionBase: '6',
- versionNumber: 6
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Safari 6.0.5+ (doesn't have the comma in "KHTML, like Gecko")
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 1084) AppleWebKit/536.30.1 (KHTML like Gecko) Version/6.0.5 Safari/536.30.1': {
- title: 'Safari 6',
- platform: 'MacIntel',
- profile: {
- name: 'safari',
- layout: 'webkit',
- layoutVersion: 536,
- platform: 'mac',
- version: '6.0.5',
- versionBase: '6',
- versionNumber: 6
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Opera 10+
- 'Opera/9.80 (Windows NT 5.1)': {
- title: 'Opera 10+ (exact version unspecified)',
- platform: 'Win32',
- profile: {
- name: 'opera',
- layout: 'presto',
- layoutVersion: 'unknown',
- platform: 'win',
- version: '10',
- versionBase: '10',
- versionNumber: 10
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Opera 12
- 'Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.11': {
- title: 'Opera 12',
- platform: 'Win32',
- profile: {
- name: 'opera',
- layout: 'presto',
- layoutVersion: 'unknown',
- platform: 'win',
- version: '12.11',
- versionBase: '12',
- versionNumber: 12.11
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Opera 15 (WebKit-based)
- 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.52 Safari/537.36 OPR/15.0.1147.130': {
- title: 'Opera 15',
- platform: 'Win32',
- profile: {
- name: 'opera',
- layout: 'webkit',
- layoutVersion: 537,
- platform: 'win',
- version: '15.0.1147.130',
- versionBase: '15',
- versionNumber: 15
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Chrome 5
- // Chrome 6
- // Chrome 7
- // Chrome 8
- // Chrome 9
- // Chrome 10
- // Chrome 11
- // Chrome 12
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30': {
- title: 'Chrome 12',
- platform: 'MacIntel',
- profile: {
- name: 'chrome',
- layout: 'webkit',
- layoutVersion: 534,
- platform: 'mac',
- version: '12.0.742.112',
- versionBase: '12',
- versionNumber: 12
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.68 Safari/534.30': {
- title: 'Chrome 12',
- platform: 'Linux i686',
- profile: {
- name: 'chrome',
- layout: 'webkit',
- layoutVersion: 534,
- platform: 'linux',
- version: '12.0.742.68',
- versionBase: '12',
- versionNumber: 12
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Android WebKit Browser 2.3
- 'Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; HTC Vision Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1': {
- title: 'Android WebKit Browser 2.3',
- platform: 'Linux armv7l',
- profile: {
- name: 'android',
- layout: 'webkit',
- layoutVersion: 533,
- platform: 'linux',
- version: '2.3.5',
- versionBase: '2',
- versionNumber: 2.3
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Rekonq (bug 34924)
- 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.34 (KHTML, like Gecko) rekonq Safari/534.34': {
- title: 'Rekonq',
- platform: 'Linux i686',
- profile: {
- name: 'rekonq',
- layout: 'webkit',
- layoutVersion: 534,
- platform: 'linux',
- version: '534.34',
- versionBase: '534',
- versionNumber: 534.34
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- // Konqueror
- 'Mozilla/5.0 (X11; Linux i686) KHTML/4.9.1 (like Gecko) Konqueror/4.9': {
- title: 'Konqueror',
- platform: 'Linux i686',
- profile: {
- name: 'konqueror',
- layout: 'khtml',
- layoutVersion: 'unknown',
- platform: 'linux',
- version: '4.9.1',
- versionBase: '4',
- versionNumber: 4.9
- },
- wikiEditor: {
- // '4.9' is less than '4.11'.
- ltr: false,
- rtl: false
- },
- wikiEditorLegacy: {
- // The check is missing in legacyTestMap
- ltr: true,
- rtl: true
- }
- },
- // Amazon Silk
- 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.0.13.81_10003810) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true': {
- title: 'Silk',
- platform: 'Desktop',
- profile: {
- name: 'silk',
- layout: 'webkit',
- layoutVersion: 533,
- platform: 'unknown',
- version: '1.0.13.81_10003810',
- versionBase: '1',
- versionNumber: 1
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- },
- 'Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; KFTT Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Silk/2.1 Mobile Safari/535.19 Silk-Accelerated=true': {
- title: 'Silk',
- platform: 'Mobile',
- profile: {
- name: 'silk',
- layout: 'webkit',
- layoutVersion: 535,
- platform: 'unknown',
- version: '2.1',
- versionBase: '2',
- versionNumber: 2.1
- },
- wikiEditor: {
- ltr: true,
- rtl: true
- }
- }
- },
- testMap = {
- // Example from WikiEditor, modified to provide version identifiers as strings and with
- // Konqueror 4.11 check added.
- 'ltr': {
- 'msie': [['>=', '7.0']],
- 'firefox': [['>=', '2']],
- 'opera': [['>=', '9.6']],
- 'safari': [['>=', '3']],
- 'chrome': [['>=', '3']],
- 'netscape': [['>=', '9']],
- 'konqueror': [['>=', '4.11']],
- 'blackberry': false,
- 'ipod': false,
- 'iphone': false
- },
- 'rtl': {
- 'msie': [['>=', '8']],
- 'firefox': [['>=', '2']],
- 'opera': [['>=', '9.6']],
- 'safari': [['>=', '3']],
- 'chrome': [['>=', '3']],
- 'netscape': [['>=', '9']],
- 'konqueror': [['>=', '4.11']],
- 'blackberry': false,
- 'ipod': false,
- 'iphone': false
- }
- },
- legacyTestMap = {
- // Original example from WikiEditor.
- // This is using the old, but still supported way of providing version identifiers as numbers
- // instead of strings; with this method, 4.9 would be considered larger than 4.11.
- 'ltr': {
- 'msie': [['>=', 7.0]],
- 'firefox': [['>=', 2]],
- 'opera': [['>=', 9.6]],
- 'safari': [['>=', 3]],
- 'chrome': [['>=', 3]],
- 'netscape': [['>=', 9]],
- 'blackberry': false,
- 'ipod': false,
- 'iphone': false
- },
- 'rtl': {
- 'msie': [['>=', 8]],
- 'firefox': [['>=', 2]],
- 'opera': [['>=', 9.6]],
- 'safari': [['>=', 3]],
- 'chrome': [['>=', 3]],
- 'netscape': [['>=', 9]],
- 'blackberry': false,
- 'ipod': false,
- 'iphone': false
- }
- }
- ;
-
- // Count test cases
- $.each( uas, function () {
- uacount++;
- } );
-
- QUnit.test( 'profile( navObject )', 7, function ( assert ) {
- var p = $.client.profile();
-
- function unknownOrType( val, type, summary ) {
- assert.ok( typeof val === type || val === 'unknown', summary );
- }
-
- assert.equal( typeof p, 'object', 'profile returns an object' );
- unknownOrType( p.layout, 'string', 'p.layout is a string (or "unknown")' );
- unknownOrType( p.layoutVersion, 'number', 'p.layoutVersion is a number (or "unknown")' );
- unknownOrType( p.platform, 'string', 'p.platform is a string (or "unknown")' );
- unknownOrType( p.version, 'string', 'p.version is a string (or "unknown")' );
- unknownOrType( p.versionBase, 'string', 'p.versionBase is a string (or "unknown")' );
- assert.equal( typeof p.versionNumber, 'number', 'p.versionNumber is a number' );
- } );
-
- QUnit.test( 'profile( navObject ) - samples', uacount, function ( assert ) {
- // Loop through and run tests
- $.each( uas, function ( rawUserAgent, data ) {
- // Generate a client profile object and compare recursively
- var ret = $.client.profile( {
- userAgent: rawUserAgent,
- platform: data.platform
- } );
- assert.deepEqual( ret, data.profile, 'Client profile support check for ' + data.title + ' (' + data.platform + '): ' + rawUserAgent );
- } );
- } );
-
- QUnit.test( 'test( testMap )', 4, function ( assert ) {
- // .test() uses eval, make sure no exceptions are thrown
- // then do a basic return value type check
- var testMatch = $.client.test( testMap ),
- ie7Profile = $.client.profile( {
- 'userAgent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
- 'platform': ''
- } );
-
- assert.equal( typeof testMatch, 'boolean', 'map with ltr/rtl split returns a boolean value' );
-
- testMatch = $.client.test( testMap.ltr );
-
- assert.equal( typeof testMatch, 'boolean', 'simple map (without ltr/rtl split) returns a boolean value' );
-
- assert.equal( $.client.test( {
- 'msie': null
- }, ie7Profile ), true, 'returns true if any version of a browser are allowed (null)' );
-
- assert.equal( $.client.test( {
- 'msie': false
- }, ie7Profile ), false, 'returns false if all versions of a browser are not allowed (false)' );
- } );
-
- QUnit.test( 'test( testMap, exactMatchOnly )', 2, function ( assert ) {
- var ie7Profile = $.client.profile( {
- 'userAgent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
- 'platform': ''
- } );
-
- assert.equal( $.client.test( {
- 'firefox': [['>=', 2]]
- }, ie7Profile, false ), true, 'returns true if browser not found and exactMatchOnly not set' );
-
- assert.equal( $.client.test( {
- 'firefox': [['>=', 2]]
- }, ie7Profile, true ), false, 'returns false if browser not found and exactMatchOnly is set' );
- } );
-
- QUnit.test( 'test( testMap ), test( legacyTestMap ) - WikiEditor sample', uacount * 2 * 2, function ( assert ) {
- var $body = $( 'body' ),
- bodyClasses = $body.attr( 'class' );
-
- // Loop through and run tests
- $.each( uas, function ( agent, data ) {
- $.each( ['ltr', 'rtl'], function ( i, dir ) {
- var profile, testMatch, legacyTestMatch;
- $body.removeClass( 'ltr rtl' ).addClass( dir );
- profile = $.client.profile( {
- userAgent: agent,
- platform: data.platform
- } );
- testMatch = $.client.test( testMap, profile );
- legacyTestMatch = $.client.test( legacyTestMap, profile );
- $body.removeClass( dir );
-
- assert.equal(
- testMatch,
- data.wikiEditor[dir],
- 'testing comparison based on ' + dir + ', ' + agent
- );
- assert.equal(
- legacyTestMatch,
- data.wikiEditorLegacy ? data.wikiEditorLegacy[dir] : data.wikiEditor[dir],
- 'testing comparison based on ' + dir + ', ' + agent + ' (legacyTestMap)'
- );
- } );
- } );
-
- // Restore body classes
- $body.attr( 'class', bodyClasses );
- } );
-}( jQuery ) );
diff --git a/tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js b/tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js
index 0b7e87ee..ca3f418c 100644
--- a/tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js
+++ b/tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js
@@ -1,13 +1,14 @@
( function ( $ ) {
QUnit.module( 'jquery.getAttrs', QUnit.newMwEnvironment() );
- QUnit.test( 'Check', 1, function ( assert ) {
+ QUnit.test( 'getAttrs()', 1, function ( assert ) {
var attrs = {
foo: 'bar',
- 'class': 'lorem'
+ 'class': 'lorem',
+ 'data-foo': 'data value'
},
$el = $( '<div>' ).attr( attrs );
- assert.deepEqual( $el.getAttrs(), attrs, 'getAttrs() return object should match the attributes set, no more, no less' );
+ assert.propEqual( $el.getAttrs(), attrs, 'keys and values match' );
} );
}( jQuery ) );
diff --git a/tests/qunit/suites/resources/jquery/jquery.placeholder.test.js b/tests/qunit/suites/resources/jquery/jquery.placeholder.test.js
index bbea8297..78c185f1 100644
--- a/tests/qunit/suites/resources/jquery/jquery.placeholder.test.js
+++ b/tests/qunit/suites/resources/jquery/jquery.placeholder.test.js
@@ -1,10 +1,10 @@
-(function ($) {
+( function ($) {
QUnit.module('jquery.placeholder', QUnit.newMwEnvironment());
QUnit.test('caches results of feature tests', 2, function (assert) {
- assert.strictEqual(typeof $.fn.placeholder.input, 'boolean', '$.fn.placeholder.input');
- assert.strictEqual(typeof $.fn.placeholder.textarea, 'boolean', '$.fn.placeholder.textarea');
+ assert.strictEqual( typeof $.fn.placeholder.input, 'boolean', '$.fn.placeholder.input');
+ assert.strictEqual( typeof $.fn.placeholder.textarea, 'boolean', '$.fn.placeholder.textarea');
});
if ($.fn.placeholder.input && $.fn.placeholder.textarea) {
diff --git a/tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js b/tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js
new file mode 100644
index 00000000..97a3ae12
--- /dev/null
+++ b/tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js
@@ -0,0 +1,223 @@
+( function ( $, mw ) {
+ /**
+ * This module tests the input/output capabilities of the parsers of tablesorter.
+ * It does not test actual sorting.
+ */
+
+ var text, ipv4,
+ simpleMDYDatesInMDY, simpleMDYDatesInDMY, oldMDYDates, complexMDYDates, clobberedDates, MYDates, YDates,
+ currencyData, transformedCurrencyData;
+
+ QUnit.module( 'jquery.tablesorter.parsers', QUnit.newMwEnvironment( {
+ setup: function () {
+ this.liveMonths = mw.language.months;
+ mw.language.months = {
+ 'keys': {
+ 'names': ['january', 'february', 'march', 'april', 'may_long', 'june',
+ 'july', 'august', 'september', 'october', 'november', 'december'],
+ 'genitive': ['january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen',
+ 'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen', 'december-gen'],
+ 'abbrev': ['jan', 'feb', 'mar', 'apr', 'may', 'jun',
+ 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
+ },
+ 'names': ['January', 'February', 'March', 'April', 'May', 'June',
+ 'July', 'August', 'September', 'October', 'November', 'December'],
+ 'genitive': ['January', 'February', 'March', 'April', 'May', 'June',
+ 'July', 'August', 'September', 'October', 'November', 'December'],
+ 'abbrev': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+ };
+ },
+ teardown: function () {
+ mw.language.months = this.liveMonths;
+ },
+ config: {
+ wgContentLanguage: 'en',
+ /* default date format of the content language */
+ wgDefaultDateFormat: 'dmy',
+ /* These two are important for numeric interpretations */
+ wgSeparatorTransformTable: ['', ''],
+ wgDigitTransformTable: ['', '']
+ }
+ } ) );
+
+ /**
+ * For a value, check if the parser recognizes it and how it transforms it
+ *
+ * @param {String} msg text to pass on to qunit describing the test case
+ * @param {String[]} parserId of the parser that will be tested
+ * @param {String[][]} data Array of testcases. Each testcase, array of
+ * inputValue: The string value that we want to test the parser for
+ * recognized: If we expect that this value's type is detectable by the parser
+ * outputValue: The value the parser has converted the input to
+ * msg: describing the testcase
+ * @param {function($table)} callback something to do before we start the testcase
+ */
+ function parserTest( msg, parserId, data, callback ) {
+ QUnit.test( msg, data.length * 2, function ( assert ) {
+ var extractedR, extractedF, parser;
+
+ if (callback !== undefined ) {
+ callback();
+ }
+
+ parser = $.tablesorter.getParser( parserId );
+ $.each( data, function ( index, testcase ) {
+ extractedR = parser.is( testcase[0] );
+ extractedF = parser.format( testcase[0] );
+
+ assert.strictEqual( extractedR, testcase[1], 'Detect: ' + testcase[3] );
+ assert.strictEqual( extractedF, testcase[2], 'Sortkey: ' + testcase[3] );
+ } );
+
+ } );
+ }
+
+ text = [
+ [ 'Mars', true, 'mars', 'Simple text' ],
+ [ 'Mẘas', true, 'mẘas', 'Non ascii character' ],
+ [ 'A sentence', true, 'a sentence', 'A sentence with space chars' ]
+ ];
+ parserTest( 'Textual keys', 'text', text );
+
+ ipv4 = [
+ // Some randomly generated fake IPs
+ ['0.0.0.0', true, 0, 'An IP address' ],
+ ['255.255.255.255', true, 255255255255, 'An IP address' ],
+ ['45.238.27.109', true, 45238027109, 'An IP address' ],
+ ['1.238.27.1', true, 1238027001, 'An IP address with small numbers' ],
+ ['238.27.1', false, 238027001, 'A malformed IP Address' ],
+ ['1', false, 1, 'A super malformed IP Address' ],
+ ['Just text', false, 0, 'A line with just text' ],
+ ['45.238.27.109Postfix', false, 45238027109, 'An IP address with a connected postfix' ],
+ ['45.238.27.109 postfix', false, 45238027109, 'An IP address with a seperated postfix' ]
+ ];
+ parserTest( 'IPv4', 'IPAddress', ipv4 );
+
+ simpleMDYDatesInMDY = [
+ ['January 17, 2010', true, 20100117, 'Long middle endian date'],
+ ['Jan 17, 2010', true, 20100117, 'Short middle endian date'],
+ ['1/17/2010', true, 20100117, 'Numeric middle endian date'],
+ ['01/17/2010', true, 20100117, 'Numeric middle endian date with padding on month'],
+ ['01/07/2010', true, 20100107, 'Numeric middle endian date with padding on day'],
+ ['01/07/0010', true, 20100107, 'Numeric middle endian date with padding on year'],
+ ['5.12.1990', true, 19900512, 'Numeric middle endian date with . separator']
+ ];
+ parserTest( 'MDY Dates using mdy content language', 'date', simpleMDYDatesInMDY );
+
+ simpleMDYDatesInDMY = [
+ ['January 17, 2010', true, 20100117, 'Long middle endian date'],
+ ['Jan 17, 2010', true, 20100117, 'Short middle endian date'],
+ ['1/17/2010', true, 20101701, 'Numeric middle endian date'],
+ ['01/17/2010', true, 20101701, 'Numeric middle endian date with padding on month'],
+ ['01/07/2010', true, 20100701, 'Numeric middle endian date with padding on day'],
+ ['01/07/0010', true, 20100701, 'Numeric middle endian date with padding on year'],
+ ['5.12.1990', true, 19901205, 'Numeric middle endian date with . separator']
+ ];
+ parserTest( 'MDY Dates using dmy content language', 'date', simpleMDYDatesInDMY, function () {
+ mw.config.set( {
+ 'wgDefaultDateFormat': 'dmy',
+ 'wgContentLanguage': 'de'
+ } );
+ } );
+
+ oldMDYDates = [
+ ['January 19, 1400 BC', false, '99999999', 'BC'],
+ ['January 19, 1400BC', false, '99999999', 'Connected BC'],
+ ['January, 19 1400 B.C.', false, '99999999', 'B.C.'],
+ ['January 19, 1400 AD', false, '99999999', 'AD'],
+ ['January, 19 10', true, 20100119, 'AD'],
+ ['January, 19 1', false, '99999999', 'AD']
+ ];
+ parserTest( 'Very old MDY dates', 'date', oldMDYDates );
+
+ complexMDYDates = [
+ ['January, 19 2010', true, 20100119, 'Comma after month'],
+ ['January 19, 2010', true, 20100119, 'Comma after day'],
+ ['January/19/2010', true, 20100119, 'Forward slash separator'],
+ ['04 22 1991', true, 19910422, 'Month with 0 padding'],
+ ['April 21 1991', true, 19910421, 'Space separation'],
+ ['04 22 1991', true, 19910422, 'Month with 0 padding'],
+ ['December 12 \'10', true, 20101212, ''],
+ ['Dec 12 \'10', true, 20101212, ''],
+ ['Dec. 12 \'10', true, 20101212, '']
+ ];
+ parserTest( 'MDY Dates', 'date', complexMDYDates );
+
+ clobberedDates = [
+ ['January, 19 2010 - January, 20 2010', false, '99999999', 'Date range with hyphen'],
+ ['January, 19 2010 — January, 20 2010', false, '99999999', 'Date range with mdash'],
+ ['prefixJanuary, 19 2010', false, '99999999', 'Connected prefix'],
+ ['prefix January, 19 2010', false, '99999999', 'Prefix'],
+ ['December 12 2010postfix', false, '99999999', 'ConnectedPostfix'],
+ ['December 12 2010 postfix', false, '99999999', 'Postfix'],
+ ['A simple text', false, '99999999', 'Plain text in date sort'],
+ ['04l22l1991', false, '99999999', 'l char as separator'],
+ ['January\\19\\2010', false, '99999999', 'backslash as date separator']
+ ];
+ parserTest( 'Clobbered Dates', 'date', clobberedDates );
+
+ MYDates = [
+ ['December 2010', false, '99999999', 'Plain month year'],
+ ['Dec 2010', false, '99999999', 'Abreviated month year'],
+ ['12 2010', false, '99999999', 'Numeric month year']
+ ];
+ parserTest( 'MY Dates', 'date', MYDates );
+
+ YDates = [
+ ['2010', false, '99999999', 'Plain 4-digit year'],
+ ['876', false, '99999999', '3-digit year'],
+ ['76', false, '99999999', '2-digit year'],
+ ['\'76', false, '99999999', '2-digit millenium bug year'],
+ ['2010 BC', false, '99999999', '4-digit year BC']
+ ];
+ parserTest( 'Y Dates', 'date', YDates );
+
+ currencyData = [
+ ['1.02 $', true, 1.02, ''],
+ ['$ 3.00', true, 3, ''],
+ ['€ 2,99', true, 299, ''],
+ ['$ 1.00', true, 1, ''],
+ ['$3.50', true, 3.50, ''],
+ ['$ 1.50', true, 1.50, ''],
+ ['€ 0.99', true, 0.99, ''],
+ ['$ 299.99', true, 299.99, ''],
+ ['$ 2,299.99', true, 2299.99, ''],
+ ['$ 2,989', true, 2989, ''],
+ ['$ 2 299.99', true, 2299.99, ''],
+ ['$ 2 989', true, 2989, ''],
+ ['$ 2.989', true, 2.989, '']
+ ];
+ parserTest( 'Currency', 'currency', currencyData );
+
+ transformedCurrencyData = [
+ ['1.02 $', true, 102, ''],
+ ['$ 3.00', true, 300, ''],
+ ['€ 2,99', true, 2.99, ''],
+ ['$ 1.00', true, 100, ''],
+ ['$3.50', true, 350, ''],
+ ['$ 1.50', true, 150, ''],
+ ['€ 0.99', true, 99, ''],
+ ['$ 299.99', true, 29999, ''],
+ ['$ 2\'299,99', true, 2299.99, ''],
+ ['$ 2,989', true, 2.989, ''],
+ ['$ 2 299.99', true, 229999, ''],
+ ['2 989 $', true, 2989, ''],
+ ['299.99 $', true, 29999, ''],
+ ['2\'299,99 $', true, 2299.99, ''],
+ ['2,989 $', true, 2.989, ''],
+ ['2 299.99 $', true, 229999, ''],
+ ['2 989 $', true, 2989, '']
+ ];
+ parserTest( 'Currency with european separators', 'currency', transformedCurrencyData, function () {
+ mw.config.set( {
+ // We expect 22'234.444,22
+ // Map from ascii separators => localized separators
+ wgSeparatorTransformTable: [', . ,', '\' , .'],
+ wgDigitTransformTable: ['', '']
+ } );
+ } );
+
+ // TODO add numbers sorting tests for bug 8115 with a different language
+
+}( jQuery, mediaWiki ) );
diff --git a/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js b/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
index 92dad9ff..f63aa27a 100644
--- a/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
+++ b/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
@@ -156,9 +156,29 @@
];
QUnit.module( 'jquery.tablesorter', QUnit.newMwEnvironment( {
+ setup: function () {
+ this.liveMonths = mw.language.months;
+ mw.language.months = {
+ 'keys': {
+ 'names': ['january', 'february', 'march', 'april', 'may_long', 'june',
+ 'july', 'august', 'september', 'october', 'november', 'december'],
+ 'genitive': ['january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen',
+ 'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen', 'december-gen'],
+ 'abbrev': ['jan', 'feb', 'mar', 'apr', 'may', 'jun',
+ 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
+ },
+ 'names': ['January', 'February', 'March', 'April', 'May', 'June',
+ 'July', 'August', 'September', 'October', 'November', 'December'],
+ 'genitive': ['January', 'February', 'March', 'April', 'May', 'June',
+ 'July', 'August', 'September', 'October', 'November', 'December'],
+ 'abbrev': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+ };
+ },
+ teardown: function () {
+ mw.language.months = this.liveMonths;
+ },
config: {
- wgMonthNames: ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
- wgMonthNamesShort: ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
wgDefaultDateFormat: 'dmy',
wgSeparatorTransformTable: ['', ''],
wgDigitTransformTable: ['', ''],
@@ -1160,11 +1180,11 @@
'</table>'
);
$table.tablesorter();
- assert.equal( $table.find( '#A2' ).prop( 'headerIndex' ),
+ assert.equal( $table.find( '#A2' ).data( 'headerIndex' ),
undefined,
'A2 should not be a sort header'
);
- assert.equal( $table.find( '#C1' ).prop( 'headerIndex' ),
+ assert.equal( $table.find( '#C1' ).data( 'headerIndex' ),
2,
'C1 should be a sort header'
);
@@ -1181,11 +1201,11 @@
'</table>'
);
$table.tablesorter();
- assert.equal( $table.find( '#C2' ).prop( 'headerIndex' ),
+ assert.equal( $table.find( '#C2' ).data( 'headerIndex' ),
2,
'C2 should be a sort header'
);
- assert.equal( $table.find( '#C1' ).prop( 'headerIndex' ),
+ assert.equal( $table.find( '#C1' ).data( 'headerIndex' ),
undefined,
'C1 should not be a sort header'
);
@@ -1209,18 +1229,19 @@
// bug 53211 - exploding rowspans in more complex cases
QUnit.test(
'Rowspan exploding with row headers and colspans', 1, function ( assert ) {
- var $table = $( '<table class="sortable">' +
- '<thead><tr><th rowspan="2">n</th><th colspan="2">foo</th><th rowspan="2">baz</th></tr>' +
- '<tr><th>foo</th><th>bar</th></tr></thead>' +
- '<tbody>' +
- '<tr><td>1</td><td>foo</td><td>bar</td><td>baz</td></tr>' +
- '<tr><td>2</td><td>foo</td><td>bar</td><td>baz</td></tr>' +
- '</tbody></table>' );
+ var $table = $( '<table class="sortable">' +
+ '<thead><tr><th rowspan="2">n</th><th colspan="2">foo</th><th rowspan="2">baz</th></tr>' +
+ '<tr><th>foo</th><th>bar</th></tr></thead>' +
+ '<tbody>' +
+ '<tr><td>1</td><td>foo</td><td>bar</td><td>baz</td></tr>' +
+ '<tr><td>2</td><td>foo</td><td>bar</td><td>baz</td></tr>' +
+ '</tbody></table>' );
$table.tablesorter();
- assert.equal( $table.find( 'tr:eq(1) th:eq(1)').prop('headerIndex'),
+ assert.equal( $table.find( 'tr:eq(1) th:eq(1)').data('headerIndex'),
2,
- 'Incorrect index of sort header' );
+ 'Incorrect index of sort header'
+ );
}
);
diff --git a/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.options.test.js b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.options.test.js
new file mode 100644
index 00000000..c0a6585f
--- /dev/null
+++ b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.options.test.js
@@ -0,0 +1,78 @@
+( function ( mw ) {
+ QUnit.module( 'mediawiki.api.options', QUnit.newMwEnvironment( {
+ setup: function () {
+ this.server = this.sandbox.useFakeServer();
+ }
+ } ) );
+
+ QUnit.test( 'saveOption', function ( assert ) {
+ QUnit.expect( 2 );
+
+ var
+ api = new mw.Api(),
+ stub = this.sandbox.stub( mw.Api.prototype, 'saveOptions' );
+
+ api.saveOption( 'foo', 'bar' );
+
+ assert.ok( stub.calledOnce, '#saveOptions called once' );
+ assert.deepEqual( stub.getCall( 0 ).args, [ { foo: 'bar' } ], '#saveOptions called correctly' );
+ } );
+
+ QUnit.test( 'saveOptions', function ( assert ) {
+ QUnit.expect( 13 );
+
+ var api = new mw.Api();
+
+ // We need to respond to the request for token first, otherwise the other requests won't be sent
+ // until after the server.respond call, which confuses sinon terribly. This sucks a lot.
+ api.getToken( 'options' );
+ this.server.respond(
+ /action=tokens.*&type=options/,
+ [ 200, { 'Content-Type': 'application/json' },
+ '{ "tokens": { "optionstoken": "+\\\\" } }' ]
+ );
+
+ api.saveOptions( {} ).done( function () {
+ assert.ok( true, 'Request completed: empty case' );
+ } );
+ api.saveOptions( { foo: 'bar' } ).done( function () {
+ assert.ok( true, 'Request completed: simple' );
+ } );
+ api.saveOptions( { foo: 'bar', baz: 'quux' } ).done( function () {
+ assert.ok( true, 'Request completed: two options' );
+ } );
+ api.saveOptions( { foo: 'bar|quux', bar: 'a|b|c', baz: 'quux' } ).done( function () {
+ assert.ok( true, 'Request completed: not bundleable' );
+ } );
+ api.saveOptions( { foo: null } ).done( function () {
+ assert.ok( true, 'Request completed: reset an option' );
+ } );
+ api.saveOptions( { 'foo|bar=quux': null } ).done( function () {
+ assert.ok( true, 'Request completed: reset an option, not bundleable' );
+ } );
+
+ // Requests are POST, match requestBody instead of url
+ this.server.respond( function ( request ) {
+ switch ( request.requestBody ) {
+ // simple
+ case 'action=options&format=json&change=foo%3Dbar&token=%2B%5C':
+ // two options
+ case 'action=options&format=json&change=foo%3Dbar%7Cbaz%3Dquux&token=%2B%5C':
+ // not bundleable
+ case 'action=options&format=json&optionname=foo&optionvalue=bar%7Cquux&token=%2B%5C':
+ case 'action=options&format=json&optionname=bar&optionvalue=a%7Cb%7Cc&token=%2B%5C':
+ case 'action=options&format=json&change=baz%3Dquux&token=%2B%5C':
+ // reset an option
+ case 'action=options&format=json&change=foo&token=%2B%5C':
+ // reset an option, not bundleable
+ case 'action=options&format=json&optionname=foo%7Cbar%3Dquux&token=%2B%5C':
+ assert.ok( true, 'Repond to ' + request.requestBody );
+ request.respond( 200, { 'Content-Type': 'application/json' },
+ '{ "options": "success" }' );
+ break;
+ default:
+ assert.ok( false, 'Unexpected request:' + request.requestBody );
+ }
+ } );
+ } );
+}( mediaWiki ) );
diff --git a/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js
index f156c728..b89526fb 100644
--- a/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js
+++ b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js
@@ -51,52 +51,26 @@
this.server.respond( function ( request ) {
if ( window.FormData ) {
- assert.ok( !request.url.match( /action=/), 'Request has no query string' );
+ assert.ok( !request.url.match( /action=/ ), 'Request has no query string' );
assert.ok( request.requestBody instanceof FormData, 'Request uses FormData body' );
} else {
- assert.ok( !request.url.match( /action=test/), 'Request has no query string' );
+ assert.ok( !request.url.match( /action=test/ ), 'Request has no query string' );
assert.equal( request.requestBody, 'action=test&format=json', 'Request uses query string body' );
}
request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
} );
} );
- QUnit.test( 'Deprecated callback methods', function ( assert ) {
- QUnit.expect( 3 );
+ QUnit.test( 'Converting arrays to pipe-separated', function ( assert ) {
+ QUnit.expect( 1 );
var api = new mw.Api();
+ api.get( { test: [ 'foo', 'bar', 'baz' ] } );
- this.suppressWarnings();
-
- api.get( {}, function () {
- assert.ok( true, 'Function argument treated as success callback.' );
- } );
-
- api.get( {}, {
- ok: function () {
- assert.ok( true, '"ok" property treated as success callback.' );
- }
- } );
-
- api.get( { action: 'doesntexist' }, {
- err: function () {
- assert.ok( true, '"err" property treated as error callback.' );
- }
- } );
-
- this.restoreWarnings();
-
- this.server.respondWith( /action=query/, function ( request ) {
+ this.server.respond( function ( request ) {
+ assert.ok( request.url.match( /test=foo%7Cbar%7Cbaz/ ), 'Pipe-separated value was submitted' );
request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
} );
-
- this.server.respondWith( /action=doesntexist/, function ( request ) {
- request.respond( 200, { 'Content-Type': 'application/json' },
- '{ "error": { "code": "unknown_action" } }'
- );
- } );
-
- this.server.respond();
} );
QUnit.test( 'getToken( pre-populated )', function ( assert ) {
@@ -196,6 +170,28 @@
);
} );
+ QUnit.test( 'postWithToken( tokenType, params with assert )', function ( assert ) {
+ QUnit.expect( 2 );
+
+ var api = new mw.Api( { ajax: { url: '/postWithToken/api.php' } } );
+
+ api.postWithToken( 'testasserttoken', { action: 'example', key: 'foo', assert: 'user' } )
+ .fail( function ( errorCode ) {
+ assert.equal( errorCode, 'assertuserfailed', 'getToken fails assert' );
+ } );
+
+ assert.equal( this.server.requests.length, 1, 'Request for token made' );
+ this.server.respondWith( /assert=user/, function ( request ) {
+ request.respond(
+ 200,
+ { 'Content-Type': 'application/json' },
+ '{ "error": { "code": "assertuserfailed", "info": "Assertion failed" } }'
+ );
+ } );
+
+ this.server.respond();
+ } );
+
QUnit.test( 'postWithToken( tokenType, params, ajaxOptions )', function ( assert ) {
QUnit.expect( 3 );
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js
index 7ab309aa..c0afe07c 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js
@@ -46,8 +46,8 @@
// Note: The ones with # are commented out as those are interpreted as fragment and
// as such end up being valid.
'A &eacute; B',
- //'A &#233; B',
- //'A &#x00E9; B',
+ // 'A &#233; B',
+ // 'A &#x00E9; B',
// Subject of NS_TALK does not roundtrip to NS_MAIN
'Talk:File:Example.svg',
// Directory navigation
@@ -437,33 +437,34 @@
} );
QUnit.test( 'getRelativeText', 5, function ( assert ) {
- var cases = [
- {
- text: 'asd',
- relativeTo: 123,
- expectedResult: ':Asd'
- },
- {
- text: 'dfg',
- relativeTo: 0,
- expectedResult: 'Dfg'
- },
- {
- text: 'Template:Ghj',
- relativeTo: 0,
- expectedResult: 'Template:Ghj'
- },
- {
- text: 'Template:1',
- relativeTo: 10,
- expectedResult: '1'
- },
- {
- text: 'User:Hi',
- relativeTo: 10,
- expectedResult: 'User:Hi'
- }
- ], i, thisCase, title;
+ var i, thisCase, title,
+ cases = [
+ {
+ text: 'asd',
+ relativeTo: 123,
+ expectedResult: ':Asd'
+ },
+ {
+ text: 'dfg',
+ relativeTo: 0,
+ expectedResult: 'Dfg'
+ },
+ {
+ text: 'Template:Ghj',
+ relativeTo: 0,
+ expectedResult: 'Template:Ghj'
+ },
+ {
+ text: 'Template:1',
+ relativeTo: 10,
+ expectedResult: '1'
+ },
+ {
+ text: 'User:Hi',
+ relativeTo: 10,
+ expectedResult: 'User:Hi'
+ }
+ ];
for ( i = 0; i < cases.length; i++ ) {
thisCase = cases[i];
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js
index 7a58d38d..ba366553 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js
@@ -314,6 +314,66 @@
assert.equal( uri.toString(), 'http://www.example.com/dir/', 'empty array value is ommitted' );
} );
+ QUnit.test( 'Variable defaultUri', 2, function ( assert ) {
+ var uri,
+ href = 'http://example.org/w/index.php#here',
+ UriClass = mw.UriRelative( function () {
+ return href;
+ } );
+
+ uri = new UriClass();
+ assert.deepEqual(
+ {
+ protocol: uri.protocol,
+ user: uri.user,
+ password: uri.password,
+ host: uri.host,
+ port: uri.port,
+ path: uri.path,
+ query: uri.query,
+ fragment: uri.fragment
+ },
+ {
+ protocol: 'http',
+ user: undefined,
+ password: undefined,
+ host: 'example.org',
+ port: undefined,
+ path: '/w/index.php',
+ query: {},
+ fragment: 'here'
+ },
+ 'basic object properties'
+ );
+
+ // Default URI may change, e.g. via history.replaceState, pushState or location.hash (T74334)
+ href = 'https://example.com/wiki/Foo?v=2';
+ uri = new UriClass();
+ assert.deepEqual(
+ {
+ protocol: uri.protocol,
+ user: uri.user,
+ password: uri.password,
+ host: uri.host,
+ port: uri.port,
+ path: uri.path,
+ query: uri.query,
+ fragment: uri.fragment
+ },
+ {
+ protocol: 'https',
+ user: undefined,
+ password: undefined,
+ host: 'example.com',
+ port: undefined,
+ path: '/wiki/Foo',
+ query: { 'v': '2' },
+ fragment: undefined
+ },
+ 'basic object properties'
+ );
+ } );
+
QUnit.test( 'Advanced URL', 11, function ( assert ) {
var uri, queryString, relativePath;
@@ -429,6 +489,5 @@
uri = new UriClass( testPath );
href = uri.toString();
assert.equal( href, testProtocol + testServer + ':' + testPort + testPath, 'Root-relative URL gets host, protocol, and port supplied' );
-
} );
}( mediaWiki, jQuery ) );
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.cookie.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.cookie.test.js
index c9653dab..f5f199ea 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.cookie.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.cookie.test.js
@@ -53,7 +53,7 @@
assert.strictEqual( call[ 1 ], '0', '0 is value' );
} );
- QUnit.test( 'set( key, value, expires )', 5, function ( assert ) {
+ QUnit.test( 'set( key, value, expires )', 6, function ( assert ) {
var date, options;
date = new Date();
@@ -61,15 +61,22 @@
mw.cookie.set( 'foo', 'bar' );
options = $.cookie.lastCall.args[ 2 ];
- assert.deepEqual( options.expires, expiryDate, 'Default cookie expiration is used' );
+ assert.deepEqual( options.expires, expiryDate, 'default expiration' );
mw.cookie.set( 'foo', 'bar', date );
options = $.cookie.lastCall.args[ 2 ];
- assert.strictEqual( options.expires, date, 'Custom expiration date' );
+ assert.strictEqual( options.expires, date, 'custom expiration as Date' );
+
+ date = new Date();
+ date.setDate( date.getDate() + 1 );
+
+ mw.cookie.set( 'foo', 'bar', 86400 );
+ options = $.cookie.lastCall.args[ 2 ];
+ assert.deepEqual( options.expires, date, 'custom expiration as lifetime in seconds' );
mw.cookie.set( 'foo', 'bar', null );
options = $.cookie.lastCall.args[ 2 ];
- assert.strictEqual( options.expires, undefined, 'Expiry null forces session cookie' );
+ assert.strictEqual( options.expires, undefined, 'null forces session cookie' );
// Per DefaultSettings.php, when wgCookieExpiration is 0, the default should
// be session cookies
@@ -81,7 +88,7 @@
mw.cookie.set( 'foo', 'bar', date );
options = $.cookie.lastCall.args[ 2 ];
- assert.strictEqual( options.expires, date, 'Custom expiration when default is session cookies' );
+ assert.strictEqual( options.expires, date, 'custom expiration (with wgCookieExpiration=0)' );
} );
QUnit.test( 'set( key, value, options )', 4, function ( assert ) {
@@ -169,4 +176,4 @@
assert.strictEqual( key, 'barfoo' );
} );
-} ( mediaWiki, jQuery ) );
+}( mediaWiki, jQuery ) );
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.errorLogger.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.errorLogger.test.js
new file mode 100644
index 00000000..7c3f1ecb
--- /dev/null
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.errorLogger.test.js
@@ -0,0 +1,42 @@
+( function ( $, mw ) {
+ QUnit.module( 'mediawiki.errorLogger', QUnit.newMwEnvironment() );
+
+ QUnit.test( 'installGlobalHandler', 7, function ( assert ) {
+ var w = {},
+ errorMessage = 'Foo',
+ errorUrl = 'http://example.com',
+ errorLine = '123',
+ errorColumn = '45',
+ errorObject = new Error( 'Foo'),
+ oldHandler = this.sandbox.stub();
+
+ this.sandbox.stub( mw, 'track' );
+
+ mw.errorLogger.installGlobalHandler( w );
+
+ assert.ok( w.onerror, 'Global handler has been installed' );
+ assert.strictEqual( w.onerror( errorMessage, errorUrl, errorLine ), false,
+ 'Global handler returns false when there is no previous handler' );
+ sinon.assert.calledWithExactly( mw.track, 'global.error',
+ sinon.match( { errorMessage: errorMessage, url: errorUrl, lineNumber: errorLine } ) );
+
+ mw.track.reset();
+ w.onerror( errorMessage, errorUrl, errorLine, errorColumn, errorObject );
+ sinon.assert.calledWithExactly( mw.track, 'global.error',
+ sinon.match( { errorMessage: errorMessage, url: errorUrl, lineNumber: errorLine,
+ columnNumber: errorColumn, errorObject: errorObject } ) );
+
+ w = { onerror: oldHandler };
+
+ mw.errorLogger.installGlobalHandler( w );
+ w.onerror( errorMessage, errorUrl, errorLine );
+ sinon.assert.calledWithExactly( oldHandler, errorMessage, errorUrl, errorLine );
+
+ oldHandler.returns( false );
+ assert.strictEqual( w.onerror( errorMessage, errorUrl, errorLine ), false,
+ 'Global handler preserves false return from previous handler' );
+ oldHandler.returns( true );
+ assert.strictEqual( w.onerror( errorMessage, errorUrl, errorLine ), true,
+ 'Global handler preserves true return from previous handler' );
+ } );
+}( jQuery, mediaWiki ) );
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
index 6b3be43b..7e23e2ff 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
@@ -55,7 +55,9 @@
'jquerymsg-test-version-entrypoints-index-php': '[https://www.mediawiki.org/wiki/Manual:index.php index.php]',
- 'external-link-replace': 'Foo [$1 bar]'
+ 'external-link-replace': 'Foo [$1 bar]',
+ 'external-link-plural': 'Foo {{PLURAL:$1|is [$2 one]|are [$2 some]|2=[$2 two]|3=three|4=a=b|5=}} things.',
+ 'plural-only-explicit-forms': 'It is a {{PLURAL:$1|1=single|2=double}} room.'
}
} ) );
@@ -107,7 +109,7 @@
run();
}
- QUnit.test( 'Replace', 9, function ( assert ) {
+ QUnit.test( 'Replace', 16, function ( assert ) {
mw.messages.set( 'simple', 'Foo $1 baz $2' );
assert.equal( formatParse( 'simple' ), 'Foo $1 baz $2', 'Replacements with no substitutes' );
@@ -155,6 +157,41 @@
'Foo <a href="http://example.org/?x=y&amp;z">bar</a>',
'Href is not double-escaped in wikilink function'
);
+ assert.equal(
+ formatParse( 'external-link-plural', 1, 'http://example.org' ),
+ 'Foo is <a href="http://example.org">one</a> things.',
+ 'Link is expanded inside plural and is not escaped html'
+ );
+ assert.equal(
+ formatParse( 'external-link-plural', 2, 'http://example.org' ),
+ 'Foo <a href=\"http://example.org\">two</a> things.',
+ 'Link is expanded inside an explicit plural form and is not escaped html'
+ );
+ assert.equal(
+ formatParse( 'external-link-plural', 3 ),
+ 'Foo three things.',
+ 'A simple explicit plural form co-existing with complex explicit plural forms'
+ );
+ assert.equal(
+ formatParse( 'external-link-plural', 4, 'http://example.org' ),
+ 'Foo a=b things.',
+ 'Only first equal sign is used as delimiter for explicit plural form. Repeated equal signs does not create issue'
+ );
+ assert.equal(
+ formatParse( 'external-link-plural', 5, 'http://example.org' ),
+ 'Foo are <a href="http://example.org">some</a> things.',
+ 'Invalid explicit plural form. Plural fallback to the "other" plural form'
+ );
+ assert.equal(
+ formatParse( 'external-link-plural', 6, 'http://example.org' ),
+ 'Foo are <a href="http://example.org">some</a> things.',
+ 'Plural fallback to the "other" plural form'
+ );
+ assert.equal(
+ formatParse( 'plural-only-explicit-forms', 2 ),
+ 'It is a double room.',
+ 'Plural with explicit forms alone.'
+ );
} );
QUnit.test( 'Plural', 6, function ( assert ) {
@@ -505,274 +542,274 @@
mw.jqueryMsg.getMessageFunction = oldGMF;
} );
-formatnumTests = [
- {
- lang: 'en',
- number: 987654321.654321,
- result: '987,654,321.654',
- description: 'formatnum test for English, decimal seperator'
- },
- {
- lang: 'ar',
- number: 987654321.654321,
- result: '٩٨٧٬٦٥٤٬٣٢١٫٦٥٤',
- description: 'formatnum test for Arabic, with decimal seperator'
- },
- {
- lang: 'ar',
- number: '٩٨٧٦٥٤٣٢١٫٦٥٤٣٢١',
- result: 987654321,
- integer: true,
- description: 'formatnum test for Arabic, with decimal seperator, reverse'
- },
- {
- lang: 'ar',
- number: -12.89,
- result: '-١٢٫٨٩',
- description: 'formatnum test for Arabic, negative number'
- },
- {
- lang: 'ar',
- number: '-١٢٫٨٩',
- result: -12,
- integer: true,
- description: 'formatnum test for Arabic, negative number, reverse'
- },
- {
- lang: 'nl',
- number: 987654321.654321,
- result: '987.654.321,654',
- description: 'formatnum test for Nederlands, decimal seperator'
- },
- {
- lang: 'nl',
- number: -12.89,
- result: '-12,89',
- description: 'formatnum test for Nederlands, negative number'
- },
- {
- lang: 'nl',
- number: '.89',
- result: '0,89',
- description: 'formatnum test for Nederlands'
- },
- {
- lang: 'nl',
- number: 'invalidnumber',
- result: 'invalidnumber',
- description: 'formatnum test for Nederlands, invalid number'
- },
- {
- lang: 'ml',
- number: '1000000000',
- result: '1,00,00,00,000',
- description: 'formatnum test for Malayalam'
- },
- {
- lang: 'ml',
- number: '-1000000000',
- result: '-1,00,00,00,000',
- description: 'formatnum test for Malayalam, negative number'
- },
- /*
- * This will fail because of wrong pattern for ml in MW(different from CLDR)
- {
- lang: 'ml',
- number: '1000000000.000',
- result: '1,00,00,00,000.000',
- description: 'formatnum test for Malayalam with decimal place'
- },
- */
- {
- lang: 'hi',
- number: '123456789.123456789',
- result: '१२,३४,५६,७८९',
- description: 'formatnum test for Hindi'
- },
- {
- lang: 'hi',
- number: '१२,३४,५६,७८९',
- result: '१२,३४,५६,७८९',
- description: 'formatnum test for Hindi, Devanagari digits passed'
- },
- {
- lang: 'hi',
- number: '१२३४५६,७८९',
- result: '123456',
- integer: true,
- description: 'formatnum test for Hindi, Devanagari digits passed to get integer value'
- }
-];
-
-QUnit.test( 'formatnum', formatnumTests.length, function ( assert ) {
- mw.messages.set( 'formatnum-msg', '{{formatnum:$1}}' );
- mw.messages.set( 'formatnum-msg-int', '{{formatnum:$1|R}}' );
- var queue = $.map( formatnumTests, function ( test ) {
- return function ( next ) {
- getMwLanguage( test.lang )
- .done( function ( langClass ) {
- mw.config.set( 'wgUserLanguage', test.lang );
- var parser = new mw.jqueryMsg.parser( { language: langClass } );
- assert.equal(
- parser.parse( test.integer ? 'formatnum-msg-int' : 'formatnum-msg',
- [ test.number ] ).html(),
- test.result,
- test.description
- );
- } )
- .fail( function () {
- assert.ok( false, 'Language "' + test.lang + '" failed to load' );
- } )
- .always( next );
- };
+ formatnumTests = [
+ {
+ lang: 'en',
+ number: 987654321.654321,
+ result: '987,654,321.654',
+ description: 'formatnum test for English, decimal separator'
+ },
+ {
+ lang: 'ar',
+ number: 987654321.654321,
+ result: '٩٨٧٬٦٥٤٬٣٢١٫٦٥٤',
+ description: 'formatnum test for Arabic, with decimal separator'
+ },
+ {
+ lang: 'ar',
+ number: '٩٨٧٦٥٤٣٢١٫٦٥٤٣٢١',
+ result: 987654321,
+ integer: true,
+ description: 'formatnum test for Arabic, with decimal separator, reverse'
+ },
+ {
+ lang: 'ar',
+ number: -12.89,
+ result: '-١٢٫٨٩',
+ description: 'formatnum test for Arabic, negative number'
+ },
+ {
+ lang: 'ar',
+ number: '-١٢٫٨٩',
+ result: -12,
+ integer: true,
+ description: 'formatnum test for Arabic, negative number, reverse'
+ },
+ {
+ lang: 'nl',
+ number: 987654321.654321,
+ result: '987.654.321,654',
+ description: 'formatnum test for Nederlands, decimal separator'
+ },
+ {
+ lang: 'nl',
+ number: -12.89,
+ result: '-12,89',
+ description: 'formatnum test for Nederlands, negative number'
+ },
+ {
+ lang: 'nl',
+ number: '.89',
+ result: '0,89',
+ description: 'formatnum test for Nederlands'
+ },
+ {
+ lang: 'nl',
+ number: 'invalidnumber',
+ result: 'invalidnumber',
+ description: 'formatnum test for Nederlands, invalid number'
+ },
+ {
+ lang: 'ml',
+ number: '1000000000',
+ result: '1,00,00,00,000',
+ description: 'formatnum test for Malayalam'
+ },
+ {
+ lang: 'ml',
+ number: '-1000000000',
+ result: '-1,00,00,00,000',
+ description: 'formatnum test for Malayalam, negative number'
+ },
+ /*
+ * This will fail because of wrong pattern for ml in MW(different from CLDR)
+ {
+ lang: 'ml',
+ number: '1000000000.000',
+ result: '1,00,00,00,000.000',
+ description: 'formatnum test for Malayalam with decimal place'
+ },
+ */
+ {
+ lang: 'hi',
+ number: '123456789.123456789',
+ result: '१२,३४,५६,७८९',
+ description: 'formatnum test for Hindi'
+ },
+ {
+ lang: 'hi',
+ number: '१२,३४,५६,७८९',
+ result: '१२,३४,५६,७८९',
+ description: 'formatnum test for Hindi, Devanagari digits passed'
+ },
+ {
+ lang: 'hi',
+ number: '१२३४५६,७८९',
+ result: '123456',
+ integer: true,
+ description: 'formatnum test for Hindi, Devanagari digits passed to get integer value'
+ }
+ ];
+
+ QUnit.test( 'formatnum', formatnumTests.length, function ( assert ) {
+ mw.messages.set( 'formatnum-msg', '{{formatnum:$1}}' );
+ mw.messages.set( 'formatnum-msg-int', '{{formatnum:$1|R}}' );
+ var queue = $.map( formatnumTests, function ( test ) {
+ return function ( next ) {
+ getMwLanguage( test.lang )
+ .done( function ( langClass ) {
+ mw.config.set( 'wgUserLanguage', test.lang );
+ var parser = new mw.jqueryMsg.parser( { language: langClass } );
+ assert.equal(
+ parser.parse( test.integer ? 'formatnum-msg-int' : 'formatnum-msg',
+ [ test.number ] ).html(),
+ test.result,
+ test.description
+ );
+ } )
+ .fail( function () {
+ assert.ok( false, 'Language "' + test.lang + '" failed to load' );
+ } )
+ .always( next );
+ };
+ } );
+ QUnit.stop();
+ process( queue, QUnit.start );
+ } );
+
+ // HTML in wikitext
+ QUnit.test( 'HTML', 26, function ( assert ) {
+ mw.messages.set( 'jquerymsg-italics-msg', '<i>Very</i> important' );
+
+ assertBothModes( assert, ['jquerymsg-italics-msg'], mw.messages.get( 'jquerymsg-italics-msg' ), 'Simple italics unchanged' );
+
+ mw.messages.set( 'jquerymsg-bold-msg', '<b>Strong</b> speaker' );
+ assertBothModes( assert, ['jquerymsg-bold-msg'], mw.messages.get( 'jquerymsg-bold-msg' ), 'Simple bold unchanged' );
+
+ mw.messages.set( 'jquerymsg-bold-italics-msg', 'It is <b><i>key</i></b>' );
+ assertBothModes( assert, ['jquerymsg-bold-italics-msg'], mw.messages.get( 'jquerymsg-bold-italics-msg' ), 'Bold and italics nesting order preserved' );
+
+ mw.messages.set( 'jquerymsg-italics-bold-msg', 'It is <i><b>vital</b></i>' );
+ assertBothModes( assert, ['jquerymsg-italics-bold-msg'], mw.messages.get( 'jquerymsg-italics-bold-msg' ), 'Italics and bold nesting order preserved' );
+
+ mw.messages.set( 'jquerymsg-italics-with-link', 'An <i>italicized [[link|wiki-link]]</i>' );
+
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-italics-with-link' ),
+ 'An <i>italicized <a title="link" href="' + mw.html.escape( mw.util.getUrl( 'link' ) ) + '">wiki-link</i>',
+ 'Italics with link inside in parse mode'
+ );
+
+ assert.equal(
+ formatText( 'jquerymsg-italics-with-link' ),
+ mw.messages.get( 'jquerymsg-italics-with-link' ),
+ 'Italics with link unchanged in text mode'
+ );
+
+ mw.messages.set( 'jquerymsg-italics-id-class', '<i id="foo" class="bar">Foo</i>' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-italics-id-class' ),
+ mw.messages.get( 'jquerymsg-italics-id-class' ),
+ 'ID and class are allowed'
+ );
+
+ mw.messages.set( 'jquerymsg-italics-onclick', '<i onclick="alert(\'foo\')">Foo</i>' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-italics-onclick' ),
+ '&lt;i onclick=&quot;alert(\'foo\')&quot;&gt;Foo&lt;/i&gt;',
+ 'element with onclick is escaped because it is not allowed'
+ );
+
+ mw.messages.set( 'jquerymsg-script-msg', '<script >alert( "Who put this tag here?" );</script>' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-script-msg' ),
+ '&lt;script &gt;alert( &quot;Who put this tag here?&quot; );&lt;/script&gt;',
+ 'Tag outside whitelist escaped in parse mode'
+ );
+
+ assert.equal(
+ formatText( 'jquerymsg-script-msg' ),
+ mw.messages.get( 'jquerymsg-script-msg' ),
+ 'Tag outside whitelist unchanged in text mode'
+ );
+
+ mw.messages.set( 'jquerymsg-script-link-msg', '<script>[[Foo|bar]]</script>' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-script-link-msg' ),
+ '&lt;script&gt;<a title="Foo" href="' + mw.html.escape( mw.util.getUrl( 'Foo' ) ) + '">bar</a>&lt;/script&gt;',
+ 'Script tag text is escaped because that element is not allowed, but link inside is still HTML'
+ );
+
+ mw.messages.set( 'jquerymsg-mismatched-html', '<i class="important">test</b>' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-mismatched-html' ),
+ '&lt;i class=&quot;important&quot;&gt;test&lt;/b&gt;',
+ 'Mismatched HTML start and end tag treated as text'
+ );
+
+ // TODO (mattflaschen, 2013-03-18): It's not a security issue, but there's no real
+ // reason the htmlEmitter span needs to be here. It's an artifact of how emitting works.
+ mw.messages.set( 'jquerymsg-script-and-external-link', '<script>alert( "jquerymsg-script-and-external-link test" );</script> [http://example.com <i>Foo</i> bar]' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-script-and-external-link' ),
+ '&lt;script&gt;alert( "jquerymsg-script-and-external-link test" );&lt;/script&gt; <a href="http://example.com"><span class="mediaWiki_htmlEmitter"><i>Foo</i> bar</span></a>',
+ 'HTML tags in external links not interfering with escaping of other tags'
+ );
+
+ mw.messages.set( 'jquerymsg-link-script', '[http://example.com <script>alert( "jquerymsg-link-script test" );</script>]' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-link-script' ),
+ '<a href="http://example.com"><span class="mediaWiki_htmlEmitter">&lt;script&gt;alert( "jquerymsg-link-script test" );&lt;/script&gt;</span></a>',
+ 'Non-whitelisted HTML tag in external link anchor treated as text'
+ );
+
+ // Intentionally not using htmlEqual for the quote tests
+ mw.messages.set( 'jquerymsg-double-quotes-preserved', '<i id="double">Double</i>' );
+ assert.equal(
+ formatParse( 'jquerymsg-double-quotes-preserved' ),
+ mw.messages.get( 'jquerymsg-double-quotes-preserved' ),
+ 'Attributes with double quotes are preserved as such'
+ );
+
+ mw.messages.set( 'jquerymsg-single-quotes-normalized-to-double', '<i id=\'single\'>Single</i>' );
+ assert.equal(
+ formatParse( 'jquerymsg-single-quotes-normalized-to-double' ),
+ '<i id="single">Single</i>',
+ 'Attributes with single quotes are normalized to double'
+ );
+
+ mw.messages.set( 'jquerymsg-escaped-double-quotes-attribute', '<i style="font-family:&quot;Arial&quot;">Styled</i>' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-escaped-double-quotes-attribute' ),
+ mw.messages.get( 'jquerymsg-escaped-double-quotes-attribute' ),
+ 'Escaped attributes are parsed correctly'
+ );
+
+ mw.messages.set( 'jquerymsg-escaped-single-quotes-attribute', '<i style=\'font-family:&#039;Arial&#039;\'>Styled</i>' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-escaped-single-quotes-attribute' ),
+ mw.messages.get( 'jquerymsg-escaped-single-quotes-attribute' ),
+ 'Escaped attributes are parsed correctly'
+ );
+
+ mw.messages.set( 'jquerymsg-wikitext-contents-parsed', '<i>[http://example.com Example]</i>' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-wikitext-contents-parsed' ),
+ '<i><a href="http://example.com">Example</a></i>',
+ 'Contents of valid tag are treated as wikitext, so external link is parsed'
+ );
+
+ mw.messages.set( 'jquerymsg-wikitext-contents-script', '<i><script>Script inside</script></i>' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-wikitext-contents-script' ),
+ '<i><span class="mediaWiki_htmlEmitter">&lt;script&gt;Script inside&lt;/script&gt;</span></i>',
+ 'Contents of valid tag are treated as wikitext, so invalid HTML element is treated as text'
+ );
+
+ mw.messages.set( 'jquerymsg-unclosed-tag', 'Foo<tag>bar' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-unclosed-tag' ),
+ 'Foo&lt;tag&gt;bar',
+ 'Nonsupported unclosed tags are escaped'
+ );
+
+ mw.messages.set( 'jquerymsg-self-closing-tag', 'Foo<tag/>bar' );
+ assert.htmlEqual(
+ formatParse( 'jquerymsg-self-closing-tag' ),
+ 'Foo&lt;tag/&gt;bar',
+ 'Self-closing tags don\'t cause a parse error'
+ );
} );
- QUnit.stop();
- process( queue, QUnit.start );
-} );
-
-// HTML in wikitext
-QUnit.test( 'HTML', 26, function ( assert ) {
- mw.messages.set( 'jquerymsg-italics-msg', '<i>Very</i> important' );
-
- assertBothModes( assert, ['jquerymsg-italics-msg'], mw.messages.get( 'jquerymsg-italics-msg' ), 'Simple italics unchanged' );
-
- mw.messages.set( 'jquerymsg-bold-msg', '<b>Strong</b> speaker' );
- assertBothModes( assert, ['jquerymsg-bold-msg'], mw.messages.get( 'jquerymsg-bold-msg' ), 'Simple bold unchanged' );
-
- mw.messages.set( 'jquerymsg-bold-italics-msg', 'It is <b><i>key</i></b>' );
- assertBothModes( assert, ['jquerymsg-bold-italics-msg'], mw.messages.get( 'jquerymsg-bold-italics-msg' ), 'Bold and italics nesting order preserved' );
-
- mw.messages.set( 'jquerymsg-italics-bold-msg', 'It is <i><b>vital</b></i>' );
- assertBothModes( assert, ['jquerymsg-italics-bold-msg'], mw.messages.get( 'jquerymsg-italics-bold-msg' ), 'Italics and bold nesting order preserved' );
-
- mw.messages.set( 'jquerymsg-italics-with-link', 'An <i>italicized [[link|wiki-link]]</i>' );
-
- assert.htmlEqual(
- formatParse( 'jquerymsg-italics-with-link' ),
- 'An <i>italicized <a title="link" href="' + mw.html.escape( mw.util.getUrl( 'link' ) ) + '">wiki-link</i>',
- 'Italics with link inside in parse mode'
- );
-
- assert.equal(
- formatText( 'jquerymsg-italics-with-link' ),
- mw.messages.get( 'jquerymsg-italics-with-link' ),
- 'Italics with link unchanged in text mode'
- );
-
- mw.messages.set( 'jquerymsg-italics-id-class', '<i id="foo" class="bar">Foo</i>' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-italics-id-class' ),
- mw.messages.get( 'jquerymsg-italics-id-class' ),
- 'ID and class are allowed'
- );
-
- mw.messages.set( 'jquerymsg-italics-onclick', '<i onclick="alert(\'foo\')">Foo</i>' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-italics-onclick' ),
- '&lt;i onclick=&quot;alert(\'foo\')&quot;&gt;Foo&lt;/i&gt;',
- 'element with onclick is escaped because it is not allowed'
- );
-
- mw.messages.set( 'jquerymsg-script-msg', '<script >alert( "Who put this tag here?" );</script>' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-script-msg' ),
- '&lt;script &gt;alert( &quot;Who put this tag here?&quot; );&lt;/script&gt;',
- 'Tag outside whitelist escaped in parse mode'
- );
-
- assert.equal(
- formatText( 'jquerymsg-script-msg' ),
- mw.messages.get( 'jquerymsg-script-msg' ),
- 'Tag outside whitelist unchanged in text mode'
- );
-
- mw.messages.set( 'jquerymsg-script-link-msg', '<script>[[Foo|bar]]</script>' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-script-link-msg' ),
- '&lt;script&gt;<a title="Foo" href="' + mw.html.escape( mw.util.getUrl( 'Foo' ) ) + '">bar</a>&lt;/script&gt;',
- 'Script tag text is escaped because that element is not allowed, but link inside is still HTML'
- );
-
- mw.messages.set( 'jquerymsg-mismatched-html', '<i class="important">test</b>' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-mismatched-html' ),
- '&lt;i class=&quot;important&quot;&gt;test&lt;/b&gt;',
- 'Mismatched HTML start and end tag treated as text'
- );
-
- // TODO (mattflaschen, 2013-03-18): It's not a security issue, but there's no real
- // reason the htmlEmitter span needs to be here. It's an artifact of how emitting works.
- mw.messages.set( 'jquerymsg-script-and-external-link', '<script>alert( "jquerymsg-script-and-external-link test" );</script> [http://example.com <i>Foo</i> bar]' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-script-and-external-link' ),
- '&lt;script&gt;alert( "jquerymsg-script-and-external-link test" );&lt;/script&gt; <a href="http://example.com"><span class="mediaWiki_htmlEmitter"><i>Foo</i> bar</span></a>',
- 'HTML tags in external links not interfering with escaping of other tags'
- );
-
- mw.messages.set( 'jquerymsg-link-script', '[http://example.com <script>alert( "jquerymsg-link-script test" );</script>]' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-link-script' ),
- '<a href="http://example.com"><span class="mediaWiki_htmlEmitter">&lt;script&gt;alert( "jquerymsg-link-script test" );&lt;/script&gt;</span></a>',
- 'Non-whitelisted HTML tag in external link anchor treated as text'
- );
-
- // Intentionally not using htmlEqual for the quote tests
- mw.messages.set( 'jquerymsg-double-quotes-preserved', '<i id="double">Double</i>' );
- assert.equal(
- formatParse( 'jquerymsg-double-quotes-preserved' ),
- mw.messages.get( 'jquerymsg-double-quotes-preserved' ),
- 'Attributes with double quotes are preserved as such'
- );
-
- mw.messages.set( 'jquerymsg-single-quotes-normalized-to-double', '<i id=\'single\'>Single</i>' );
- assert.equal(
- formatParse( 'jquerymsg-single-quotes-normalized-to-double' ),
- '<i id="single">Single</i>',
- 'Attributes with single quotes are normalized to double'
- );
-
- mw.messages.set( 'jquerymsg-escaped-double-quotes-attribute', '<i style="font-family:&quot;Arial&quot;">Styled</i>' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-escaped-double-quotes-attribute' ),
- mw.messages.get( 'jquerymsg-escaped-double-quotes-attribute' ),
- 'Escaped attributes are parsed correctly'
- );
-
- mw.messages.set( 'jquerymsg-escaped-single-quotes-attribute', '<i style=\'font-family:&#039;Arial&#039;\'>Styled</i>' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-escaped-single-quotes-attribute' ),
- mw.messages.get( 'jquerymsg-escaped-single-quotes-attribute' ),
- 'Escaped attributes are parsed correctly'
- );
-
- mw.messages.set( 'jquerymsg-wikitext-contents-parsed', '<i>[http://example.com Example]</i>' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-wikitext-contents-parsed' ),
- '<i><a href="http://example.com">Example</a></i>',
- 'Contents of valid tag are treated as wikitext, so external link is parsed'
- );
-
- mw.messages.set( 'jquerymsg-wikitext-contents-script', '<i><script>Script inside</script></i>' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-wikitext-contents-script' ),
- '<i><span class="mediaWiki_htmlEmitter">&lt;script&gt;Script inside&lt;/script&gt;</span></i>',
- 'Contents of valid tag are treated as wikitext, so invalid HTML element is treated as text'
- );
-
- mw.messages.set( 'jquerymsg-unclosed-tag', 'Foo<tag>bar' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-unclosed-tag' ),
- 'Foo&lt;tag&gt;bar',
- 'Nonsupported unclosed tags are escaped'
- );
-
- mw.messages.set( 'jquerymsg-self-closing-tag', 'Foo<tag/>bar' );
- assert.htmlEqual(
- formatParse( 'jquerymsg-self-closing-tag' ),
- 'Foo&lt;tag/&gt;bar',
- 'Self-closing tags don\'t cause a parse error'
- );
-} );
QUnit.test( 'Behavior in case of invalid wikitext', 3, function ( assert ) {
mw.messages.set( 'invalid-wikitext', '<b>{{FAIL}}</b>' );
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js
index 16f90df8..670914eb 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js
@@ -8,19 +8,32 @@
},
teardown: function () {
mw.language.data.values = this.liveLangData;
+ },
+ messages: {
+ // mw.language.listToText test
+ 'and': ' and',
+ 'comma-separator': ', ',
+ 'word-separator': ' '
}
} ) );
- QUnit.test( 'mw.language getData and setData', 2, function ( assert ) {
+ QUnit.test( 'mw.language getData and setData', 3, function ( assert ) {
mw.language.setData( 'en', 'testkey', 'testvalue' );
assert.equal( mw.language.getData( 'en', 'testkey' ), 'testvalue', 'Getter setter test for mw.language' );
assert.equal( mw.language.getData( 'en', 'invalidkey' ), undefined, 'Getter setter test for mw.language with invalid key' );
+ mw.language.setData( 'en-us', 'testkey', 'testvalue' );
+ assert.equal( mw.language.getData( 'en-US', 'testkey' ), 'testvalue', 'Case insensitive test for mw.language' );
} );
QUnit.test( 'mw.language.commafy test', 9, function ( assert ) {
+ mw.language.setData( 'en', 'digitGroupingPattern', null );
+ mw.language.setData( 'en', 'digitTransformTable', null );
+ mw.language.setData( 'en', 'separatorTransformTable', null );
+
+ mw.config.set( 'wgUserLanguage', 'en' );
// Number grouping patterns are as per http://cldr.unicode.org/translation/number-patterns
assert.equal( mw.language.commafy( 1234.567, '###0.#####' ), '1234.567', 'Pattern with no digit grouping separator defined' );
- assert.equal( mw.language.commafy( 123456789.567, '###0.#####' ), '123456789.567', 'Pattern with no digit grouping seperator defined, bigger decimal part' );
+ assert.equal( mw.language.commafy( 123456789.567, '###0.#####' ), '123456789.567', 'Pattern with no digit grouping separator defined, bigger decimal part' );
assert.equal( mw.language.commafy( 0.567, '###0.#####' ), '0.567', 'Decimal part 0' );
assert.equal( mw.language.commafy( '.567', '###0.#####' ), '0.567', 'Decimal part missing. replace with zero' );
assert.equal( mw.language.commafy( 1234, '##,#0.#####' ), '12,34', 'Pattern with no fractional part' );
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.messagePoster.factory.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.messagePoster.factory.test.js
new file mode 100644
index 00000000..61bab03f
--- /dev/null
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.messagePoster.factory.test.js
@@ -0,0 +1,28 @@
+( function ( mw ) {
+ var TEST_MODEL = 'test-content-model';
+
+ QUnit.module( 'mediawiki.messagePoster', QUnit.newMwEnvironment( {
+ teardown: function () {
+ mw.messagePoster.factory.unregister( TEST_MODEL );
+ }
+ } ) );
+
+ QUnit.test( 'register', 2, function ( assert ) {
+ var testMessagePosterConstructor = function () {};
+
+ mw.messagePoster.factory.register( TEST_MODEL, testMessagePosterConstructor );
+ assert.strictEqual(
+ mw.messagePoster.factory.contentModelToClass[TEST_MODEL],
+ testMessagePosterConstructor,
+ 'Constructor is registered'
+ );
+
+ assert.throws(
+ function () {
+ mw.messagePoster.factory.register( TEST_MODEL, testMessagePosterConstructor );
+ },
+ new RegExp( 'The content model \'' + TEST_MODEL + '\' is already registered.' ),
+ 'Throws exception is same model is registered a second time'
+ );
+ } );
+}( mediaWiki ) );
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.template.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.template.test.js
new file mode 100644
index 00000000..86fd828a
--- /dev/null
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.template.test.js
@@ -0,0 +1,63 @@
+( function ( mw ) {
+
+ QUnit.module( 'mediawiki.template', {
+ setup: function () {
+ var abcCompiler = {
+ compile: function () {
+ return 'abc default compiler';
+ }
+ };
+
+ // Register some template compiler languages
+ mw.template.registerCompiler( 'abc', abcCompiler );
+ mw.template.registerCompiler( 'xyz', {
+ compile: function () {
+ return 'xyz compiler';
+ }
+ } );
+
+ // Stub register some templates
+ this.sandbox.stub( mw.templates, 'get' ).returns( {
+ 'test_templates_foo.xyz': 'goodbye',
+ 'test_templates_foo.abc': 'thankyou'
+ } );
+ }
+ } );
+
+ QUnit.test( 'add', 1, function ( assert ) {
+ assert.throws(
+ function () {
+ mw.template.add( 'module', 'test_templates_foo', 'hello' );
+ },
+ 'When no prefix throw exception'
+ );
+ } );
+
+ QUnit.test( 'compile', 1, function ( assert ) {
+ assert.throws(
+ function () {
+ mw.template.compile( '{{foo}}', 'rainbow' );
+ },
+ 'Unknown compiler names throw exceptions'
+ );
+ } );
+
+ QUnit.test( 'get', 4, function ( assert ) {
+ assert.strictEqual( mw.template.get( 'test.mediawiki.template', 'test_templates_foo.xyz' ), 'xyz compiler' );
+ assert.strictEqual( mw.template.get( 'test.mediawiki.template', 'test_templates_foo.abc' ), 'abc default compiler' );
+ assert.throws(
+ function () {
+ mw.template.get( 'this.should.not.exist', 'hello' );
+ },
+ 'When bad module name given throw error.'
+ );
+
+ assert.throws(
+ function () {
+ mw.template.get( 'mediawiki.template', 'hello' );
+ },
+ 'The template hello should not exist in the mediawiki.templates module and should throw an exception.'
+ );
+ } );
+
+}( mediaWiki ) );
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.test.js
index 7e0ee917..cf36ea82 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.test.js
@@ -1,6 +1,8 @@
/*jshint -W024 */
( function ( mw, $ ) {
- var specialCharactersPageName;
+ var specialCharactersPageName,
+ // Can't mock SITENAME since jqueryMsg caches it at load
+ siteName = mw.config.get( 'wgSiteName' );
// Since QUnitTestResources.php loads both mediawiki and mediawiki.jqueryMsg as
// dependencies, this only tests the monkey-patched behavior with the two of them combined.
@@ -55,7 +57,7 @@
this.restoreWarnings();
} );
- QUnit.test( 'mw.Map', 28, function ( assert ) {
+ QUnit.test( 'mw.Map', 35, function ( assert ) {
var arry, conf, funky, globalConf, nummy, someValues;
conf = new mw.Map();
@@ -86,8 +88,10 @@
assert.strictEqual( conf.set( 'constructor', 42 ), true, 'Map.set for key "constructor"' );
assert.strictEqual( conf.get( 'constructor' ), 42, 'Map.get for key "constructor"' );
- assert.strictEqual( conf.set( 'ImUndefined', undefined ), true, 'Map.set allows setting value to `undefined`' );
- assert.equal( conf.get( 'ImUndefined', 'fallback' ), undefined, 'Map.get supports retreiving value of `undefined`' );
+ assert.strictEqual( conf.set( 'undef' ), false, 'Map.set requires explicit value (no undefined default)' );
+
+ assert.strictEqual( conf.set( 'undef', undefined ), true, 'Map.set allows setting value to `undefined`' );
+ assert.equal( conf.get( 'undef', 'fallback' ), undefined, 'Map.get supports retreiving value of `undefined`' );
assert.strictEqual( conf.set( funky, 'Funky' ), false, 'Map.set returns boolean false if key was invalid (Function)' );
assert.strictEqual( conf.set( arry, 'Arry' ), false, 'Map.set returns boolean false if key was invalid (Array)' );
@@ -99,7 +103,7 @@
conf.set( String( nummy ), 'I used to be a number' );
assert.strictEqual( conf.exists( 'doesNotExist' ), false, 'Map.exists where property does not exist' );
- assert.strictEqual( conf.exists( 'ImUndefined' ), true, 'Map.exists where value is `undefined`' );
+ assert.strictEqual( conf.exists( 'undef' ), true, 'Map.exists where value is `undefined`' );
assert.strictEqual( conf.exists( nummy ), false, 'Map.exists where key is invalid but looks like an existing key' );
// Multiple values at once
@@ -126,12 +130,31 @@
conf.set( 'globalMapChecker', 'Hi' );
- assert.ok( 'globalMapChecker' in window === false, 'new mw.Map did not store its values in the global window object by default' );
+ assert.ok( ( 'globalMapChecker' in window ) === false, 'Map does not its store values in the window object by default' );
globalConf = new mw.Map( true );
globalConf.set( 'anotherGlobalMapChecker', 'Hello' );
- assert.ok( 'anotherGlobalMapChecker' in window, 'new mw.Map( true ) did store its values in the global window object' );
+ assert.ok( 'anotherGlobalMapChecker' in window, 'global Map stores its values in the window object' );
+
+ assert.equal( globalConf.get( 'anotherGlobalMapChecker' ), 'Hello', 'get value from global Map via get()' );
+ this.suppressWarnings();
+ assert.equal( window.anotherGlobalMapChecker, 'Hello', 'get value from global Map via window object' );
+ this.restoreWarnings();
+
+ // Change value via global Map
+ globalConf.set('anotherGlobalMapChecker', 'Again');
+ assert.equal( globalConf.get( 'anotherGlobalMapChecker' ), 'Again', 'Change in global Map reflected via get()' );
+ this.suppressWarnings();
+ assert.equal( window.anotherGlobalMapChecker, 'Again', 'Change in global Map reflected window object' );
+ this.restoreWarnings();
+
+ // Change value via window object
+ this.suppressWarnings();
+ window.anotherGlobalMapChecker = 'World';
+ assert.equal( window.anotherGlobalMapChecker, 'World', 'Change in window object works' );
+ this.restoreWarnings();
+ assert.equal( globalConf.get( 'anotherGlobalMapChecker' ), 'Again', 'Change in window object not reflected in global Map' );
// Whitelist this global variable for QUnit's 'noglobal' mode
if ( QUnit.config.noglobals ) {
@@ -148,7 +171,9 @@
// Convenience method for asserting the same result for multiple formats
function assertMultipleFormats( messageArguments, formats, expectedResult, assertMessage ) {
- var len = formats.length, format, i;
+ var format, i,
+ len = formats.length;
+
for ( i = 0; i < len; i++ ) {
format = formats[i];
assert.equal( mw.message.apply( null, messageArguments )[format](), expectedResult, assertMessage + ' when format is ' + format );
@@ -178,9 +203,9 @@
assert.equal( hello.format, 'escaped', 'Message.escaped correctly updated the "format" property' );
assert.ok( mw.messages.set( 'multiple-curly-brace', '"{{SITENAME}}" is the home of {{int:other-message}}' ), 'mw.messages.set: Register' );
- assertMultipleFormats( ['multiple-curly-brace'], ['text', 'parse'], '"' + mw.config.get( 'wgSiteName') + '" is the home of Other Message', 'Curly brace format works correctly' );
+ assertMultipleFormats( ['multiple-curly-brace'], ['text', 'parse'], '"' + siteName + '" is the home of Other Message', 'Curly brace format works correctly' );
assert.equal( mw.message( 'multiple-curly-brace' ).plain(), mw.messages.get( 'multiple-curly-brace' ), 'Plain format works correctly for curly brace message' );
- assert.equal( mw.message( 'multiple-curly-brace' ).escaped(), mw.html.escape( '"' + mw.config.get( 'wgSiteName') + '" is the home of Other Message' ), 'Escaped format works correctly for curly brace message' );
+ assert.equal( mw.message( 'multiple-curly-brace' ).escaped(), mw.html.escape( '"' + siteName + '" is the home of Other Message' ), 'Escaped format works correctly for curly brace message' );
assert.ok( mw.messages.set( 'multiple-square-brackets-and-ampersand', 'Visit the [[Project:Community portal|community portal]] & [[Project:Help desk|help desk]]' ), 'mw.messages.set: Register' );
assertMultipleFormats( ['multiple-square-brackets-and-ampersand'], ['plain', 'text'], mw.messages.get( 'multiple-square-brackets-and-ampersand' ), 'Square bracket message is not processed' );
@@ -243,8 +268,8 @@
assert.equal( mw.message( 'gender-plural-msg', 'male', 1 ).plain(), '{{GENDER:male|he|she|they}} {{PLURAL:1|is|are}} awesome', 'Parameters are substituted, but gender and plural are not resolved in plain mode' );
assert.equal( mw.message( 'grammar-msg' ).plain(), mw.messages.get( 'grammar-msg' ), 'Grammar is not resolved in plain mode' );
- assertMultipleFormats( ['grammar-msg'], ['text', 'parse'], 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'Grammar is resolved' );
- assert.equal( mw.message( 'grammar-msg' ).escaped(), 'Przeszukaj ' + mw.html.escape( mw.config.get( 'wgSiteName' ) ), 'Grammar is resolved in escaped mode' );
+ assertMultipleFormats( ['grammar-msg'], ['text', 'parse'], 'Przeszukaj ' + siteName, 'Grammar is resolved' );
+ assert.equal( mw.message( 'grammar-msg' ).escaped(), 'Przeszukaj ' + siteName, 'Grammar is resolved in escaped mode' );
assertMultipleFormats( ['formatnum-msg', '987654321.654321'], ['text', 'parse', 'escaped'], '987,654,321.654', 'formatnum is resolved' );
assert.equal( mw.message( 'formatnum-msg' ).plain(), mw.messages.get( 'formatnum-msg' ), 'formatnum is not resolved in plain mode' );
@@ -304,7 +329,7 @@
assert.equal( mw.msg( 'gender-plural-msg', 'female', '1' ), 'she is awesome', 'Gender test for female, plural count 1' );
assert.equal( mw.msg( 'gender-plural-msg', 'unknown', 10 ), 'they are awesome', 'Gender test for neutral, plural count 10' );
- assert.equal( mw.msg( 'grammar-msg' ), 'Przeszukaj ' + mw.config.get( 'wgSiteName' ), 'Grammar is resolved' );
+ assert.equal( mw.msg( 'grammar-msg' ), 'Przeszukaj ' + siteName, 'Grammar is resolved' );
assert.equal( mw.msg( 'formatnum-msg', '987654321.654321' ), '987,654,321.654', 'formatnum is resolved' );
@@ -352,7 +377,7 @@
return;
}
// Otherwise, keep polling
- setTimeout( styleTestLoop, 150 );
+ setTimeout( styleTestLoop );
}
// Start the loop
@@ -396,6 +421,30 @@
} );
} );
+ QUnit.asyncTest( 'mw.loader with Object method as module name', 2, function ( assert ) {
+ var isAwesomeDone;
+
+ mw.loader.testCallback = function () {
+ QUnit.start();
+ assert.strictEqual( isAwesomeDone, undefined, 'Implementing module hasOwnProperty: isAwesomeDone should still be undefined' );
+ isAwesomeDone = true;
+ };
+
+ mw.loader.implement( 'hasOwnProperty', [QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/callMwLoaderTestCallback.js' )], {}, {} );
+
+ mw.loader.using( 'hasOwnProperty', function () {
+
+ // /sample/awesome.js declares the "mw.loader.testCallback" function
+ // which contains a call to start() and ok()
+ assert.strictEqual( isAwesomeDone, true, 'hasOwnProperty module should\'ve caused isAwesomeDone to be true' );
+ delete mw.loader.testCallback;
+
+ }, function () {
+ QUnit.start();
+ assert.ok( false, 'Error callback fired while loader.using "hasOwnProperty" module' );
+ } );
+ } );
+
QUnit.asyncTest( 'mw.loader.using( .. ).promise', 2, function ( assert ) {
var isAwesomeDone;
@@ -625,6 +674,11 @@
} );
+ QUnit.test( 'mw.loader.implement( only scripts )', 1, function ( assert ) {
+ mw.loader.implement( 'test.onlyscripts', function () {} );
+ assert.strictEqual( mw.loader.getState( 'test.onlyscripts' ), 'ready' );
+ } );
+
QUnit.asyncTest( 'mw.loader.implement( only messages )', 2, function ( assert ) {
assert.assertFalse( mw.messages.exists( 'bug_29107' ), 'Verify that the test message doesn\'t exist yet' );
@@ -638,7 +692,10 @@
} );
} );
- QUnit.test( 'mw.loader erroneous indirect dependency', 3, function ( assert ) {
+ QUnit.test( 'mw.loader erroneous indirect dependency', 4, function ( assert ) {
+ // don't emit an error event
+ this.sandbox.stub( mw, 'track' );
+
mw.loader.register( [
['test.module1', '0'],
['test.module2', '0', ['test.module1']],
@@ -650,6 +707,8 @@
assert.strictEqual( mw.loader.getState( 'test.module1' ), 'error', 'Expected "error" state for test.module1' );
assert.strictEqual( mw.loader.getState( 'test.module2' ), 'error', 'Expected "error" state for test.module2' );
assert.strictEqual( mw.loader.getState( 'test.module3' ), 'error', 'Expected "error" state for test.module3' );
+
+ assert.strictEqual( mw.track.callCount, 1 );
} );
QUnit.test( 'mw.loader out-of-order implementation', 9, function ( assert ) {
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.track.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.track.test.js
new file mode 100644
index 00000000..cdb26244
--- /dev/null
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.track.test.js
@@ -0,0 +1,42 @@
+( function ( mw ) {
+ QUnit.module( 'mediawiki.track' );
+
+ QUnit.test( 'track', 1, function ( assert ) {
+ var sequence = [];
+ mw.trackSubscribe( 'simple', function ( topic, data ) {
+ sequence.push( [ topic, data ] );
+ } );
+ mw.track( 'simple', { key: 1 } );
+ mw.track( 'simple', { key: 2 } );
+
+ assert.deepEqual( sequence, [
+ [ 'simple', { key: 1 } ],
+ [ 'simple', { key: 2 } ]
+ ], 'Events after subscribing' );
+ } );
+
+ QUnit.test( 'trackSubscribe', 4, function ( assert ) {
+ var now,
+ sequence = [];
+ mw.track( 'before', { key: 1 } );
+ mw.track( 'before', { key: 2 } );
+ mw.trackSubscribe( 'before', function ( topic, data ) {
+ sequence.push( [ topic, data ] );
+ } );
+ mw.track( 'before', { key: 3 } );
+
+ assert.deepEqual( sequence, [
+ [ 'before', { key: 1 } ],
+ [ 'before', { key: 2 } ],
+ [ 'before', { key: 3 } ]
+ ], 'Replay events from before subscribing' );
+
+ now = mw.now();
+ mw.track( 'context', { key: 0 } );
+ mw.trackSubscribe( 'context', function ( topic, data ) {
+ assert.strictEqual( this.topic, topic, 'thisValue has topic' );
+ assert.strictEqual( this.data, data, 'thisValue has data' );
+ assert.assertTrue( this.timeStamp >= now, 'thisValue has sane timestamp' );
+ } );
+ } );
+}( mediaWiki ) );
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.user.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.user.test.js
index 91321a2f..04e002dd 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.user.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.user.test.js
@@ -1,7 +1,17 @@
-( function ( mw ) {
+( function ( mw, $ ) {
QUnit.module( 'mediawiki.user', QUnit.newMwEnvironment( {
setup: function () {
this.server = this.sandbox.useFakeServer();
+ this.crypto = window.crypto;
+ this.msCrypto = window.msCrypto;
+ },
+ teardown: function () {
+ if ( this.crypto ) {
+ window.crypto = this.crypto;
+ }
+ if ( this.msCrypto ) {
+ window.msCrypto = this.msCrypto;
+ }
}
} ) );
@@ -51,4 +61,38 @@
this.server.respond();
} );
-}( mediaWiki ) );
+
+ QUnit.test( 'generateRandomSessionId', 4, function ( assert ) {
+ var result, result2;
+
+ result = mw.user.generateRandomSessionId();
+ assert.equal( typeof result, 'string', 'type' );
+ assert.equal( $.trim( result ), result, 'no whitespace at beginning or end' );
+ assert.equal( result.length, 16, 'size' );
+
+ result2 = mw.user.generateRandomSessionId();
+ assert.notEqual( result, result2, 'different when called multiple times' );
+
+ } );
+
+ QUnit.test( 'generateRandomSessionId (fallback)', 4, function ( assert ) {
+ var result, result2;
+
+ // Pretend crypto API is not there to test the Math.random fallback
+ if ( window.crypto ) {
+ window.crypto = undefined;
+ }
+ if ( window.msCrypto ) {
+ window.msCrypto = undefined;
+ }
+
+ result = mw.user.generateRandomSessionId();
+ assert.equal( typeof result, 'string', 'type' );
+ assert.equal( $.trim( result ), result, 'no whitespace at beginning or end' );
+ assert.equal( result.length, 16, 'size' );
+
+ result2 = mw.user.generateRandomSessionId();
+ assert.notEqual( result, result2, 'different when called multiple times' );
+
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
index 4401eadb..0b42af4b 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
@@ -1,4 +1,79 @@
( function ( mw, $ ) {
+ var
+ // Based on IPTest.php > testisIPv4
+ IPV4_CASES = [
+ [false, false, 'Boolean false is not an IP'],
+ [false, true, 'Boolean true is not an IP'],
+ [false, '', 'Empty string is not an IP'],
+ [false, 'abc', '"abc" is not an IP'],
+ [false, ':', 'Colon is not an IP'],
+ [false, '124.24.52', 'IPv4 not enough quads'],
+ [false, '24.324.52.13', 'IPv4 out of range'],
+ [false, '.24.52.13', 'IPv4 starts with period'],
+
+ [true, '124.24.52.13', '124.24.52.134 is a valid IP'],
+ [true, '1.24.52.13', '1.24.52.13 is a valid IP'],
+ [false, '74.24.52.13/20', 'IPv4 ranges are not recognized as valid IPs']
+ ],
+
+ // Based on IPTest.php > testisIPv6
+ IPV6_CASES = [
+ [false, ':fc:100::', 'IPv6 starting with lone ":"'],
+ [false, 'fc:100:::', 'IPv6 ending with a ":::"'],
+ [false, 'fc:300', 'IPv6 with only 2 words'],
+ [false, 'fc:100:300', 'IPv6 with only 3 words'],
+
+ [false, 'fc:100:a:d:1:e:ac:0::', 'IPv6 with 8 words ending with "::"'],
+ [false, 'fc:100:a:d:1:e:ac:0:1::', 'IPv6 with 9 words ending with "::"'],
+
+ [false, ':::'],
+ [false, '::0:', 'IPv6 ending in a lone ":"'],
+
+ [true, '::', 'IPv6 zero address'],
+
+ [false, '::fc:100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words'],
+ [false, '::fc:100:a:d:1:e:ac:0:1', 'IPv6 with 9 words'],
+
+ [false, ':fc::100', 'IPv6 starting with lone ":"'],
+ [false, 'fc::100:', 'IPv6 ending with lone ":"'],
+ [false, 'fc:::100', 'IPv6 with ":::" in the middle'],
+
+ [true, 'fc::100', 'IPv6 with "::" and 2 words'],
+ [true, 'fc::100:a', 'IPv6 with "::" and 3 words'],
+ [true, 'fc::100:a:d', 'IPv6 with "::" and 4 words'],
+ [true, 'fc::100:a:d:1', 'IPv6 with "::" and 5 words'],
+ [true, 'fc::100:a:d:1:e', 'IPv6 with "::" and 6 words'],
+ [true, 'fc::100:a:d:1:e:ac', 'IPv6 with "::" and 7 words'],
+ [true, '2001::df', 'IPv6 with "::" and 2 words'],
+ [true, '2001:5c0:1400:a::df', 'IPv6 with "::" and 5 words'],
+ [true, '2001:5c0:1400:a::df:2', 'IPv6 with "::" and 6 words'],
+
+ [false, 'fc::100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words'],
+ [false, 'fc::100:a:d:1:e:ac:0:1', 'IPv6 with 9 words']
+ ];
+
+ Array.prototype.push.apply( IPV6_CASES,
+ $.map( [
+ 'fc:100::',
+ 'fc:100:a::',
+ 'fc:100:a:d::',
+ 'fc:100:a:d:1::',
+ 'fc:100:a:d:1:e::',
+ 'fc:100:a:d:1:e:ac::',
+ '::0',
+ '::fc',
+ '::fc:100',
+ '::fc:100:a',
+ '::fc:100:a:d',
+ '::fc:100:a:d:1',
+ '::fc:100:a:d:1:e',
+ '::fc:100:a:d:1:e:ac',
+ 'fc:100:a:d:1:e:ac:0'
+ ], function ( el ) {
+ return [[ true, el, el + ' is a valid IP' ]];
+ } )
+ );
+
QUnit.module( 'mediawiki.util', QUnit.newMwEnvironment( {
setup: function () {
$.fn.updateTooltipAccessKeys.setTestMode( true );
@@ -35,24 +110,25 @@
} );
} );
- QUnit.test( 'getUrl', 4, function ( assert ) {
+ QUnit.test( 'getUrl', 5, function ( assert ) {
// Not part of startUp module
mw.config.set( 'wgArticlePath', '/wiki/$1' );
mw.config.set( 'wgPageName', 'Foobar' );
var href = mw.util.getUrl( 'Sandbox' );
- assert.equal( href, '/wiki/Sandbox', 'Simple title; Get link for "Sandbox"' );
+ assert.equal( href, '/wiki/Sandbox', 'simple title' );
- href = mw.util.getUrl( 'Foo:Sandbox ? 5+5=10 ! (test)/subpage' );
- assert.equal( href, '/wiki/Foo:Sandbox_%3F_5%2B5%3D10_!_(test)/subpage',
- 'Advanced title; Get link for "Foo:Sandbox ? 5+5=10 ! (test)/subpage"' );
+ href = mw.util.getUrl( 'Foo:Sandbox? 5+5=10! (test)/sub ' );
+ assert.equal( href, '/wiki/Foo:Sandbox%3F_5%2B5%3D10!_(test)/sub_', 'advanced title' );
href = mw.util.getUrl();
- assert.equal( href, '/wiki/Foobar', 'Default title; Get link for current page ("Foobar")' );
+ assert.equal( href, '/wiki/Foobar', 'default title' );
+
+ href = mw.util.getUrl( null, { action: 'edit' } );
+ assert.equal( href, '/wiki/Foobar?action=edit', 'default title with query string' );
href = mw.util.getUrl( 'Sandbox', { action: 'edit' } );
- assert.equal( href, '/wiki/Sandbox?action=edit',
- 'Simple title with query string; Get link for "Sandbox" with action=edit' );
+ assert.equal( href, '/wiki/Sandbox?action=edit', 'simple title with query string' );
} );
QUnit.test( 'wikiScript', 4, function ( assert ) {
@@ -189,7 +265,7 @@
);
assert.equal( $tbMW.closest( '.portlet' ).attr( 'id' ), 'p-test-tb', 'Link was inserted within correct portlet' );
- assert.strictEqual( $tbMW.next()[0], tbRL, 'Link is in the correct position (by passing nextnode)' );
+ assert.strictEqual( $tbMW.next()[0], tbRL, 'Link is in the correct position (nextnode as Node object)' );
cuQuux = mw.util.addPortletLink( 'p-test-custom', '#', 'Quux', null, 'Example [shift-x]', 'q' );
$cuQuux = $( cuQuux );
@@ -205,7 +281,7 @@
tbRLDM = mw.util.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
'Default modules', 't-rldm', 'List of all default modules ', 'd', '#t-rl' );
- assert.equal( $( tbRLDM ).next().attr( 'id' ), 't-rl', 'Link is in the correct position (by passing CSS selector)' );
+ assert.strictEqual( $( tbRLDM ).next()[0], tbRL, 'Link is in the correct position (CSS selector as nextnode)' );
caFoo = mw.util.addPortletLink( 'p-test-views', '#', 'Foo' );
@@ -213,26 +289,19 @@
assert.strictEqual( $( caFoo ).find( 'span' ).length, 1, 'A <span> element should be added for porlets with vectorTabs class.' );
addedAfter = mw.util.addPortletLink( 'p-test-tb', '#', 'After foo', 'post-foo', 'After foo', null, $( tbRL ) );
- assert.strictEqual( $( addedAfter ).next()[0], tbRL, 'Link is in the correct position (by passing a jQuery object as nextnode)' );
+ assert.strictEqual( $( addedAfter ).next()[0], tbRL, 'Link is in the correct position (jQuery object as nextnode)' );
// test case - nonexistent id as next node
tbRLDMnonexistentid = mw.util.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
'Default modules', 't-rldm-nonexistent', 'List of all default modules ', 'd', '#t-rl-nonexistent' );
- assert.equal( tbRLDMnonexistentid, $( '#p-test-tb li:last' )[0], 'Nonexistent id as nextnode adds the portlet at end' );
+ assert.equal( tbRLDMnonexistentid, $( '#p-test-tb li:last' )[0], 'Fallback to adding at the end (nextnode non-matching CSS selector)' );
// test case - empty jquery object as next node
tbRLDMemptyjquery = mw.util.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
'Default modules', 't-rldm-empty-jquery', 'List of all default modules ', 'd', $( '#t-rl-nonexistent' ) );
- assert.equal( tbRLDMemptyjquery, $( '#p-test-tb li:last' )[0], 'Empty jquery as nextnode adds the portlet at end' );
- } );
-
- QUnit.test( 'jsMessage', 1, function ( assert ) {
- this.suppressWarnings();
- var a = mw.util.jsMessage( 'MediaWiki is <b>Awesome</b>.' );
- this.restoreWarnings();
- assert.ok( a, 'Basic checking of return value' );
+ assert.equal( tbRLDMemptyjquery, $( '#p-test-tb li:last' )[0], 'Fallback to adding at the end (nextnode as empty jQuery object)' );
} );
QUnit.test( 'validateEmail', 6, function ( assert ) {
@@ -249,95 +318,24 @@
} );
QUnit.test( 'isIPv6Address', 40, function ( assert ) {
- // Shortcuts
- function assertFalseIPv6( addy, summary ) {
- return assert.strictEqual( mw.util.isIPv6Address( addy ), false, summary );
- }
-
- function assertTrueIPv6( addy, summary ) {
- return assert.strictEqual( mw.util.isIPv6Address( addy ), true, summary );
- }
-
- // Based on IPTest.php > testisIPv6
- assertFalseIPv6( ':fc:100::', 'IPv6 starting with lone ":"' );
- assertFalseIPv6( 'fc:100:::', 'IPv6 ending with a ":::"' );
- assertFalseIPv6( 'fc:300', 'IPv6 with only 2 words' );
- assertFalseIPv6( 'fc:100:300', 'IPv6 with only 3 words' );
-
- $.each(
- ['fc:100::',
- 'fc:100:a::',
- 'fc:100:a:d::',
- 'fc:100:a:d:1::',
- 'fc:100:a:d:1:e::',
- 'fc:100:a:d:1:e:ac::'], function ( i, addy ) {
- assertTrueIPv6( addy, addy + ' is a valid IP' );
- } );
-
- assertFalseIPv6( 'fc:100:a:d:1:e:ac:0::', 'IPv6 with 8 words ending with "::"' );
- assertFalseIPv6( 'fc:100:a:d:1:e:ac:0:1::', 'IPv6 with 9 words ending with "::"' );
-
- assertFalseIPv6( ':::' );
- assertFalseIPv6( '::0:', 'IPv6 ending in a lone ":"' );
-
- assertTrueIPv6( '::', 'IPv6 zero address' );
- $.each(
- ['::0',
- '::fc',
- '::fc:100',
- '::fc:100:a',
- '::fc:100:a:d',
- '::fc:100:a:d:1',
- '::fc:100:a:d:1:e',
- '::fc:100:a:d:1:e:ac',
-
- 'fc:100:a:d:1:e:ac:0'], function ( i, addy ) {
- assertTrueIPv6( addy, addy + ' is a valid IP' );
- } );
-
- assertFalseIPv6( '::fc:100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words' );
- assertFalseIPv6( '::fc:100:a:d:1:e:ac:0:1', 'IPv6 with 9 words' );
-
- assertFalseIPv6( ':fc::100', 'IPv6 starting with lone ":"' );
- assertFalseIPv6( 'fc::100:', 'IPv6 ending with lone ":"' );
- assertFalseIPv6( 'fc:::100', 'IPv6 with ":::" in the middle' );
-
- assertTrueIPv6( 'fc::100', 'IPv6 with "::" and 2 words' );
- assertTrueIPv6( 'fc::100:a', 'IPv6 with "::" and 3 words' );
- assertTrueIPv6( 'fc::100:a:d', 'IPv6 with "::" and 4 words' );
- assertTrueIPv6( 'fc::100:a:d:1', 'IPv6 with "::" and 5 words' );
- assertTrueIPv6( 'fc::100:a:d:1:e', 'IPv6 with "::" and 6 words' );
- assertTrueIPv6( 'fc::100:a:d:1:e:ac', 'IPv6 with "::" and 7 words' );
- assertTrueIPv6( '2001::df', 'IPv6 with "::" and 2 words' );
- assertTrueIPv6( '2001:5c0:1400:a::df', 'IPv6 with "::" and 5 words' );
- assertTrueIPv6( '2001:5c0:1400:a::df:2', 'IPv6 with "::" and 6 words' );
-
- assertFalseIPv6( 'fc::100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words' );
- assertFalseIPv6( 'fc::100:a:d:1:e:ac:0:1', 'IPv6 with 9 words' );
+ $.each( IPV6_CASES, function ( i, ipCase ) {
+ assert.strictEqual( mw.util.isIPv6Address( ipCase[1] ), ipCase[0], ipCase[2] );
+ } );
} );
QUnit.test( 'isIPv4Address', 11, function ( assert ) {
- // Shortcuts
- function assertFalseIPv4( addy, summary ) {
- assert.strictEqual( mw.util.isIPv4Address( addy ), false, summary );
- }
+ $.each( IPV4_CASES, function ( i, ipCase ) {
+ assert.strictEqual( mw.util.isIPv4Address( ipCase[1] ), ipCase[0], ipCase[2] );
+ } );
+ } );
- function assertTrueIPv4( addy, summary ) {
- assert.strictEqual( mw.util.isIPv4Address( addy ), true, summary );
- }
+ QUnit.test( 'isIPAddress', 51, function ( assert ) {
+ $.each( IPV4_CASES, function ( i, ipCase ) {
+ assert.strictEqual( mw.util.isIPv4Address( ipCase[1] ), ipCase[0], ipCase[2] );
+ } );
- // Based on IPTest.php > testisIPv4
- assertFalseIPv4( false, 'Boolean false is not an IP' );
- assertFalseIPv4( true, 'Boolean true is not an IP' );
- assertFalseIPv4( '', 'Empty string is not an IP' );
- assertFalseIPv4( 'abc', '"abc" is not an IP' );
- assertFalseIPv4( ':', 'Colon is not an IP' );
- assertFalseIPv4( '124.24.52', 'IPv4 not enough quads' );
- assertFalseIPv4( '24.324.52.13', 'IPv4 out of range' );
- assertFalseIPv4( '.24.52.13', 'IPv4 starts with period' );
-
- assertTrueIPv4( '124.24.52.13', '124.24.52.134 is a valid IP' );
- assertTrueIPv4( '1.24.52.13', '1.24.52.13 is a valid IP' );
- assertFalseIPv4( '74.24.52.13/20', 'IPv4 ranges are not recogzized as valid IPs' );
+ $.each( IPV6_CASES, function ( i, ipCase ) {
+ assert.strictEqual( mw.util.isIPv6Address( ipCase[1] ), ipCase[0], ipCase[2] );
+ } );
} );
}( mediaWiki, jQuery ) );
diff --git a/tests/qunit/suites/resources/startup.test.js b/tests/qunit/suites/resources/startup.test.js
index ed03418a..6011961a 100644
--- a/tests/qunit/suites/resources/startup.test.js
+++ b/tests/qunit/suites/resources/startup.test.js
@@ -96,6 +96,7 @@
'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.7) Gecko/20060928 (Debian|Debian-1.8.0.7-1) Epiphany/2.14',
'Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.8.1.6) Gecko/20070817 IceWeasel/2.0.0.6-g2',
// KHTML
+ 'Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.4 (like Gecko)',
'Mozilla/5.0 (compatible; Konqueror/4.3; Linux) KHTML/4.3.5 (like Gecko)',
// Text browsers
'Links (2.1pre33; Darwin 8.11.0 Power Macintosh; x)',
diff --git a/tests/testHelpers.inc b/tests/testHelpers.inc
index 62dccbf0..6d3ac2f5 100644
--- a/tests/testHelpers.inc
+++ b/tests/testHelpers.inc
@@ -471,7 +471,7 @@ class TestFileIterator implements Iterator {
$hooksResult = $this->delayedParserTest->unleash( $this->parserTest );
if ( !$hooksResult ) {
# Some hook reported an issue. Abort.
- throw new MWException( "Problem running hook" );
+ throw new MWException( "Problem running requested parser hook from the test file" );
}
$this->test = array(
@@ -558,7 +558,7 @@ class TestFileIterator implements Iterator {
$line = trim( $line );
if ( $line ) {
- $delayedParserTest->requireTransparentHook( $line );
+ $this->delayedParserTest->requireTransparentHook( $line );
}
}
@@ -618,6 +618,7 @@ class TestFileIterator implements Iterator {
* @param bool $fatal True iff an exception should be thrown if
* the section is not found.
* @return bool|string
+ * @throws MWException
*/
private function checkSection( $tokens, $fatal = true ) {
if ( is_null( $this->section ) ) {
@@ -691,6 +692,7 @@ class DelayedParserTest {
* Should be the case if we found the parserTest is not disabled
* @param ParserTest|NewParserTest $parserTest
* @return bool
+ * @throws MWException
*/
public function unleash( &$parserTest ) {
if ( !( $parserTest instanceof ParserTest || $parserTest instanceof NewParserTest ) ) {
@@ -805,7 +807,7 @@ class TidySupport {
global $wgTidyBin;
$this->internalTidy = extension_loaded( 'tidy' ) &&
- class_exists( 'tidy' );
+ class_exists( 'tidy' ) && !wfIsHHVM();
$this->externalTidy = is_executable( $wgTidyBin ) ||
Installer::locateExecutableInDefaultPaths( array( $wgTidyBin ) )