%PDF- %PDF-
Direktori : /www/varak.net/wiki.varak.net/extensions/MobileFrontend/tests/phpunit/ |
Current File : /www/varak.net/wiki.varak.net/extensions/MobileFrontend/tests/phpunit/MobileContextTest.php |
<?php use MediaWiki\MediaWikiServices; /** * @group MobileFrontend */ class MobileContextTest extends MediaWikiTestCase { /** * PHP 5.3.2 introduces the ReflectionMethod::setAccessible() method to allow the invocation of * protected and private methods directly through the Reflection API * * @param $name string * @return ReflectionMethod */ protected static function getMethod( $name ) { $class = new ReflectionClass( 'MobileContext' ); $method = $class->getMethod( $name ); $method->setAccessible( true ); return $method; } protected function tearDown() { parent::tearDown(); MobileContext::resetInstanceForTesting(); } /** * @param string $url * @param array $cookies * @return MobileContext */ private function makeContext( $url = '/', $cookies = [] ) { $query = []; if ( $url ) { $params = wfParseUrl( wfExpandUrl( $url ) ); if ( isset( $params['query'] ) ) { $query = wfCgiToArray( $params['query'] ); } } $request = new FauxRequest( $query ); $request->setRequestURL( $url ); $request->setCookies( $cookies, '' ); $context = new DerivativeContext( RequestContext::getMain() ); $context->setRequest( $request ); $context->setOutput( new OutputPage( $context ) ); $instance = unserialize( 'O:13:"MobileContext":0:{}' ); $instance->setContext( $context ); return $instance; } /** * @covers MobileContext::getMobileUrl */ public function testGetMobileUrl() { $this->setMwGlobals( [ 'wgMFMobileHeader' => 'X-Subdomain', 'wgMobileUrlTemplate' => '%h0.m.%h1.%h2', 'wgServer' => '//en.wikipedia.org', ] ); $invokes = 0; $context = $this->makeContext(); $asserter = $this; $this->setMwGlobals( 'wgHooks', [ 'GetMobileUrl' => [ function ( &$string, $hookCtx ) use ( $asserter, &$invokes, $context ) { $asserter->assertEquals( $context, $hookCtx ); $invokes++; } ] ] ); $context->getRequest()->setHeader( 'X-Subdomain', 'M' ); $this->assertEquals( 'http://en.m.wikipedia.org/wiki/Article', $context->getMobileUrl( 'http://en.wikipedia.org/wiki/Article' ) ); $this->assertEquals( '//en.m.wikipedia.org/wiki/Article', $context->getMobileUrl( '//en.wikipedia.org/wiki/Article' ) ); // test local Urls - task T107505 $this->assertEquals( 'http://en.m.wikipedia.org/wiki/Article', $context->getMobileUrl( '/wiki/Article' ) ); $this->assertEquals( 3, $invokes, 'Ensure that hook got the right context' ); } /** * @covers MobileContext::parseMobileUrlTemplate */ public function testParseMobileUrlTemplate() { $this->setMwGlobals( 'wgMobileUrlTemplate', '%h0.m.%h1.%h2/path/morepath' ); $context = $this->makeContext(); $this->assertEquals( '%h0.m.%h1.%h2', $context->parseMobileUrlTemplate( 'host' ) ); $this->assertEquals( '/path/morepath', $context->parseMobileUrlTemplate( 'path' ) ); $this->assertEquals( [ 'host' => '%h0.m.%h1.%h2', 'path' => '/path/morepath' ], $context->parseMobileUrlTemplate() ); } /** * @dataProvider updateMobileUrlHostProvider * @covers MobileContext::updateMobileUrlHost */ public function testUpdateMobileUrlHost( $url, $expected, $urlTemplate ) { $updateMobileUrlHost = self::getMethod( "updateMobileUrlHost" ); $this->setMwGlobals( 'wgMobileUrlTemplate', $urlTemplate ); $parsedUrl = wfParseUrl( $url ); $updateMobileUrlHost->invokeArgs( $this->makeContext(), [ &$parsedUrl ] ); $this->assertEquals( $expected, wfAssembleUrl( $parsedUrl ) ); } public function updateMobileUrlHostProvider() { return [ [ 'http://en.wikipedia.org/wiki/Gustavus_Airport', 'http://en.m.wikipedia.org/wiki/Gustavus_Airport', '%h0.m.%h1.%h2', ], [ 'https://127.0.0.1/wiki/Test', 'https://127.0.0.1/wiki/Test', '%h0.m.%h1.%h2', ], ]; } /** * @covers MobileContext::usingMobileDomain */ public function testUsingMobileDomain() { $this->setMwGlobals( [ 'wgMFMobileHeader' => 'X-Subdomain', 'wgMobileUrlTemplate' => '%h0.m.%h1.%h2', ] ); $context = $this->makeContext(); $this->assertFalse( $context->usingMobileDomain() ); $context->getRequest()->setHeader( 'X-Subdomain', 'M' ); $this->assertTrue( $context->usingMobileDomain() ); } /** * @dataProvider updateDesktopUrlQueryProvider * @covers MobileContext::updateDesktopUrlQuery */ public function testUpdateDesktopUrlQuery( $mobile, $desktop ) { $updateDesktopUrlQuery = self::getMethod( "updateDesktopUrlQuery" ); $parsedUrl = wfParseUrl( $mobile ); $updateDesktopUrlQuery->invokeArgs( $this->makeContext(), [ &$parsedUrl ] ); $url = wfAssembleUrl( $parsedUrl ); $this->assertEquals( $desktop, $url ); } public function updateDesktopUrlQueryProvider() { $baseUrl = 'http://en.m.wikipedia.org/wiki/Gustavus_Airport'; return [ [ $baseUrl . '?useformat=mobile&mobileaction=toggle_desktop_view', $baseUrl . '?mobileaction=toggle_desktop_view' ], ]; } /** * @dataProvider updateDesktopUrlHostProvider * @covers MobileContext::updateDesktopUrlHost */ public function testUpdateDesktopUrlHost( $mobile, $desktop, $server ) { $updateMobileUrlHost = self::getMethod( "updateDesktopUrlHost" ); $this->setMwGlobals( [ 'wgServer' => $server, 'wgMobileUrlTemplate' => '%h0.m.%h1.%h2', ] ); $parsedUrl = wfParseUrl( $mobile ); $updateMobileUrlHost->invokeArgs( $this->makeContext(), [ &$parsedUrl ] ); $this->assertEquals( $desktop, wfAssembleUrl( $parsedUrl ) ); } public function updateDesktopUrlHostProvider() { return [ [ 'http://bm.m.wikipedia.org/wiki/' . urlencode( 'Nyɛ_fɔlɔ' ), 'http://bm.wikipedia.org/wiki/' . urlencode( 'Nyɛ_fɔlɔ' ), '//bm.wikipedia.org', ], [ 'http://en.m.wikipedia.org/wiki/Gustavus_Airport', 'http://en.wikipedia.org/wiki/Gustavus_Airport', '//en.wikipedia.org', ], ]; } /** * @covers MobileContext::updateMobileUrlPath */ public function testUpdateMobileUrlPath() { $this->setMwGlobals( [ 'wgScriptPath' => '/wiki', 'wgMobileUrlTemplate' => "/mobile/%p", ] ); $updateMobileUrlHost = self::getMethod( "updateMobileUrlPath" ); // check for constructing a templated URL $parsedUrl = wfParseUrl( "http://en.wikipedia.org/wiki/Gustavus_Airport" ); $updateMobileUrlHost->invokeArgs( $this->makeContext(), [ &$parsedUrl ] ); $this->assertEquals( "http://en.wikipedia.org/wiki/mobile/Gustavus_Airport", wfAssembleUrl( $parsedUrl ) ); // check for maintaining an already templated URL $parsedUrl = wfParseUrl( "http://en.wikipedia.org/wiki/mobile/Gustavus_Airport" ); $updateMobileUrlHost->invokeArgs( $this->makeContext(), [ &$parsedUrl ] ); $this->assertEquals( "http://en.wikipedia.org/wiki/mobile/Gustavus_Airport", wfAssembleUrl( $parsedUrl ) ); } /** * A null title shouldn't result in a fatal exception - bug T142914 * @covers MobileContext::shouldDisplayMobileView * @covers MobileContext::setUseFormat */ public function testRedirectMobileEnabledPages() { $this->setMwGlobals( [ 'wgTitle' => null, ] ); $mobileContext = $this->makeContext(); $mobileContext->getRequest()->setVal( 'action', 'history' ); $mobileContext->setUseFormat( 'mobile' ); $this->assertTrue( $mobileContext->shouldDisplayMobileView() ); } /** * @dataProvider getMobileActionProvider * @covers MobileContext::getMobileAction */ public function testGetMobileAction( $mobileaction = null ) { $context = $this->makeContext(); if ( is_null( $mobileaction ) ) { $assert = ''; } else { $context->getRequest()->setVal( 'mobileaction', $mobileaction ); $assert = $mobileaction; } $this->assertEquals( $assert, $context->getMobileAction() ); } public function getMobileActionProvider() { return [ [ null ], [ 'view_normal_site' ], ]; } /** * @dataProvider getUseFormatProvider * @covers MobileContext::getUseFormat */ public function testGetUseFormat( $explicit, $requestParam, $expected ) { $context = $this->makeContext(); $context->getRequest()->setVal( 'useformat', $requestParam ); $context->setUseFormat( $explicit ); $this->assertEquals( $expected, $context->getUseFormat() ); } public function getUseFormatProvider() { return [ [ 'mobile', null, 'mobile' ], [ null, 'mobile', 'mobile' ], [ null, null, '' ], [ 'desktop', 'mobile', 'desktop' ], ]; } /** * @covers MobileContext::getUseFormatCookieExpiry */ public function testGetUseFormatCookieExpiry() { global $wgCookieExpiration; $getUseFormatCookieExpiry = self::getMethod( 'getUseFormatCookieExpiry' ); $context = $this->makeContext(); $startTime = time(); $this->setMwGlobals( 'wgMobileFrontendFormatCookieExpiry', 60 ); $mfCookieExpected = $startTime + 60; $this->assertTrue( $mfCookieExpected == $getUseFormatCookieExpiry->invokeArgs( $context, [ $startTime ] ), 'Using MobileFrontend expiry.' ); $this->setMwGlobals( 'wgMobileFrontendFormatCookieExpiry', null ); $defaultMWCookieExpected = $startTime + $wgCookieExpiration; $this->assertTrue( $defaultMWCookieExpected == $getUseFormatCookieExpiry->invokeArgs( $context, [ $startTime ] ), 'Using default MediaWiki cookie expiry.' ); } /** * @covers MobileContext::getStopMobileRedirectCookieDomain */ public function testGetStopMobileRedirectCookieDomain() { $context = $this->makeContext(); $this->setMwGlobals( [ 'wgMFStopRedirectCookieHost' => null, 'wgServer' => 'http://en.wikipedia.org', ] ); $this->assertEquals( $context->getStopMobileRedirectCookieDomain(), '.wikipedia.org' ); $this->setMwGlobals( 'wgMFStopRedirectCookieHost', 'foo.bar.baz' ); $this->assertEquals( $context->getStopMobileRedirectCookieDomain(), 'foo.bar.baz' ); } /** * @covers MobileContext::isLocalUrl */ public function testIsLocalUrl() { global $wgServer; $context = $this->makeContext(); $this->assertTrue( $context->isLocalUrl( $wgServer ) ); $this->assertFalse( $context->isLocalUrl( 'http://www.google.com' ) ); } /** * @dataProvider addAnalyticsLogItemProvider * @covers MobileContext::getAnalyticsLogItems */ public function testAddAnalyticsLogItem( $key, $val ) { $context = $this->makeContext(); $context->addAnalyticsLogItem( $key, $val ); $logItems = $context->getAnalyticsLogItems(); $trimmedKey = trim( $key ); $trimmedVal = trim( $val ); $this->assertTrue( isset( $logItems[$trimmedKey] ) ); $this->assertEquals( $logItems[$trimmedKey], $trimmedVal ); } public function addAnalyticsLogItemProvider() { return [ [ 'mf-m', 'a' ], [ ' mf-m', 'b ' ], ]; } /** * @dataProvider getXAnalyticsHeaderProvider * @covers MobileContext::getXAnalyticsHeader */ public function testGetXAnalyticsHeader( $existingHeader, $logItems, $expectedHeader ) { $context = $this->makeContext(); foreach ( $logItems as $key => $val ) { $context->addAnalyticsLogItem( $key, $val ); } if ( $existingHeader ) { $context->getRequest()->response()->header( 'X-Analytics: ' . $existingHeader, true ); } $this->assertEquals( $context->getXAnalyticsHeader(), $expectedHeader ); } public function getXAnalyticsHeaderProvider() { return [ [ null, [ 'mf-m' => 'a', 'zero' => '502-13' ], 'X-Analytics: mf-m=a;zero=502-13', ], // check key/val trimming [ null, [ ' foo' => ' bar ', 'baz' => ' blat ' ], 'X-Analytics: foo=bar;baz=blat' ], // check urlencoding key/val pairs [ null, [ 'foo' => 'bar baz', 'blat' => '$blammo' ], 'X-Analytics: foo=bar+baz;blat=%24blammo' ], // check handling of existing header value [ 'existing=value; another=item', [ 'mf-m' => 'a', 'zero' => '502-13' ], 'X-Analytics: existing=value;another=item;mf-m=a;zero=502-13', ], ]; } /** * @dataProvider addAnalyticsLogItemFromXAnalyticsProvider * @covers MobileContext::addAnalyticsLogItemFromXanalytics */ public function testAddAnalyticsLogItemFromXAnalytics( $analyticsItem, $key, $val ) { $context = $this->makeContext(); $context->addAnalyticsLogItemFromXanalytics( $analyticsItem ); $logItems = $context->getAnalyticsLogItems(); $this->assertTrue( isset( $logItems[$key] ) ); $this->assertEquals( $logItems[$key], $val ); } public function addAnalyticsLogItemFromXAnalyticsProvider() { return [ [ 'mf-m=a', 'mf-m', 'a' ], // check key/val trimming [ ' mf-m=a ', 'mf-m', 'a' ], // check urldecode [ 'foo=bar+%24blat', 'foo', 'bar $blat' ], ]; } /** * @dataProvider getMobileHostTokenProvider * @covers MobileContext::getMobileHostToken */ public function testGetMobileHostToken( $domainTemplate, $result ) { $context = $this->makeContext(); $this->assertEquals( $context->getMobileHostToken( $domainTemplate ), $result ); } public function getMobileHostTokenProvider() { return [ [ '%h1.m.%h2.%h3', 'm.' ], [ '', '' ], [ 'bananas.%h2.%h3', 'bananas.' ], ]; } /** * @dataProvider optInProvider * @covers MobileContext::isBetaGroupMember */ public function testOptIn( array $cookies, $isBeta, $enabledInSettings ) { $this->setMwGlobals( 'wgMFEnableBeta', $enabledInSettings ); $mobileContext = $this->makeContext( '/', $cookies ); $this->assertEquals( $isBeta, $mobileContext->isBetaGroupMember() ); } public function optInProvider() { return [ [ [], false, true ], [ [ MobileContext::OPTIN_COOKIE_NAME => MobileContext::MODE_BETA ], true, true ], [ [ MobileContext::OPTIN_COOKIE_NAME => 'foobar' ], false, true ], [ [], false, false ], [ [ MobileContext::OPTIN_COOKIE_NAME => MobileContext::MODE_BETA ], false, false ], [ [ MobileContext::OPTIN_COOKIE_NAME => 'foobar' ], false, false ], ]; } /** * @dataProvider provideToggleView * @covers MobileContext::checkToggleView * @covers MobileContext::doToggling */ public function testToggleView( $page, $url, $urlTemplate, $expectedLocation ) { $this->setMwGlobals( [ 'wgMobileUrlTemplate' => $urlTemplate, 'wgServer' => '//en.wikipedia.org', // 'wgArticlePath' => '/wiki/$1', 'wgScriptPath' => '/wiki', ] ); $context = $this->makeContext( $url ); $context->getContext()->setTitle( Title::newFromText( $page ) ); $context->checkToggleView(); $context->doToggling(); $location = $context->getOutput()->getRedirect(); $this->assertEquals( $expectedLocation, $location ); } public function provideToggleView() { $token = '%h0.m.%h1.%h2'; return [ [ 'Foo', '/', '', '' ], [ 'Foo', '/', $token, '' ], [ 'Main Page', '/wiki/Main_Page', '', '' ], [ 'Main Page', '/wiki/Main_Page', $token, '' ], [ 'Main Page', '/wiki/Main_Page?useformat=mobile', '', '' ], [ 'Main Page', '/wiki/Main_Page?useformat=mobile', $token, '' ], [ 'Main Page', '/wiki/Main_Page?useformat=desktop', '', '' ], [ 'Main Page', '/wiki/Main_Page?useformat=desktop', $token, '' ], [ 'Foo', '/?mobileaction=toggle_view_desktop', '', '' ], [ 'Foo', '/?mobileaction=toggle_view_mobile', '', '' ], [ 'Page', '/wiki/Page?mobileaction=toggle_view_desktop', '', '' ], /* FIXME: works locally but fails in Jerkins array( 'Main Page', '/?mobileaction=toggle_view_desktop', $token, 'http://en.wikipedia.org/wiki/Main_Page' ), array( 'Main Page', '/?mobileaction=toggle_view_mobile', $token, 'http://en.m.wikipedia.org/wiki/Main_Page' ), array( 'Page', '/wiki/Page?mobileaction=toggle_view_mobile', $token, 'http://en.m.wikipedia.org/wiki/Page' ), array( 'Page', '/wiki/Page?mobileaction=toggle_view_desktop', $token, 'http://en.wikipedia.org/wiki/Page' ), array( 'Special:Foo', '/wiki/index.php?title=Special:Foo&bar=baz&mobileaction=toggle_view_desktop', $token, 'http://en.wikipedia.org/w/index.php?title=Special:Foo&bar=baz' ), array( 'Special:Foo', '/wiki/index.php?title=Special%3AFoo&bar=baz&mobileaction=toggle_view_mobile', $token, 'http://en.m.wikipedia.org/w/index.php?title=Special:Foo&bar=baz' ), array( 'Page', '/wiki/index.php?title=Page&mobileaction=toggle_view_desktop', $token, 'http://en.wikipedia.org/wiki/Page', ), array( 'Page', '/wiki/index.php?title=Page&mobileaction=toggle_view_mobile', $token, 'http://en.m.wikipedia.org/wiki/Page', ), */ ]; } /** * @codeCoverageIgnore * @coversNothing */ public function testBug71329() { $services = MediaWikiServices::getInstance(); $services->resetServiceForTesting( 'SpecialPageFactory' ); RequestContext::resetMain(); $req = new FauxRequest( [ 'title' => 'Special:Search', 'mobileaction' => 'toggle_view_mobile' ] ); $req->setRequestURL( '/w/index.php?title=Special:Search&mobileaction=toggle_view_mobile' ); RequestContext::getMain()->setRequest( $req ); MobileContext::resetInstanceForTesting(); $this->setMwGlobals( 'wgTitle', null ); SpecialPage::getTitleFor( 'Search' ); $this->assertTrue( true, 'In case of failure this test just crashes' ); } /** * @dataProvider provideShouldStripResponsiveImages * @covers MobileContext::shouldStripResponsiveImages * @covers MobileContext::setForceMobileView */ public function testShouldStripResponsiveImages( $expected, $forceMobileView, $wgMFStripResponsiveImages, $stripResponsiveImages = null ) { $context = MobileContext::singleton(); $context->setForceMobileView( $forceMobileView ); $this->setMwGlobals( 'wgMFStripResponsiveImages', $wgMFStripResponsiveImages ); $context->setStripResponsiveImages( $stripResponsiveImages ); $this->assertEquals( $expected, $context->shouldStripResponsiveImages() ); } public static function provideShouldStripResponsiveImages() { return [ [ true, true, true ], [ false, true, false ], [ false, false, true ], [ false, true, true, false ], ]; } }