summaryrefslogtreecommitdiff
path: root/tests/phpunit/includes/registration
diff options
context:
space:
mode:
Diffstat (limited to 'tests/phpunit/includes/registration')
-rw-r--r--tests/phpunit/includes/registration/ExtensionProcessorTest.php374
-rw-r--r--tests/phpunit/includes/registration/ExtensionRegistryTest.php195
2 files changed, 569 insertions, 0 deletions
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,
+ )
+ ),
+ ),
+ )
+ );
+ }
+}