diff --git a/phpBB/adm/style/acp_ext_details.html b/phpBB/adm/style/acp_ext_details.html new file mode 100644 index 0000000000..e7532691ad --- /dev/null +++ b/phpBB/adm/style/acp_ext_details.html @@ -0,0 +1,97 @@ + + + + + « {L_BACK} + +
{L_EXTENSIONS_EXPLAIN}
+{L_DISABLE_EXPLAIN}
+ + +{L_DISABLE_CONFIRM}
+{L_DISABLE_IN_PROGRESS}
+{L_EXTENSIONS_EXPLAIN}
+{L_ENABLE_EXPLAIN}
+ + +{L_ENABLE_CONFIRM}
+{L_ENABLE_IN_PROGRESS}
+{L_EXTENSIONS_EXPLAIN}
+ +{L_EXTENSION_NAME} | +{L_EXTENSION_OPTIONS} | +{L_EXTENSION_ACTIONS} | +
---|---|---|
+ {L_ENABLED} {L_EXTENSIONS} + | +||
{enabled.META_DISPLAY_NAME} | +{L_DETAILS} | ++ + {enabled.actions.L_ACTION} + | + + | +
{L_DISABLED} {L_EXTENSIONS} | +||
{disabled.META_DISPLAY_NAME} | ++ {L_DETAILS} + | ++ + {disabled.actions.L_ACTION} + | + + | +
{L_EXTENSIONS_EXPLAIN}
+{L_PURGE_EXPLAIN}
+ + +{L_PURGE_CONFIRM}
+{L_PURGE_IN_PROGRESS}
+%s
', + 'EXTENSION_NOT_AVAILABLE' => 'The selected extension is not available for this board, please verify your phpBB and PHP versions are allowed (see the details page).', + + 'DETAILS' => 'Details', + + 'AVAILABLE' => 'Available', + 'ENABLED' => 'Enabled', + 'DISABLED' => 'Disabled', + 'PURGED' => 'Purged', + 'UPLOADED' => 'Uploaded', + + 'ENABLE' => 'Enable', + 'DISABLE' => 'Disable', + 'PURGE' => 'Purge', + + 'ENABLE_EXPLAIN' => 'Enabling an extension allows you to use it on your board.', + 'DISABLE_EXPLAIN' => 'Disabling an extension retains its files and settings but removes any functionality added by the extension.', + 'PURGE_EXPLAIN' => 'Purging an extension clears an extensions data while retaining its files.', + 'DELETE_EXPLAIN' => 'Deleting an extension removes all of its files and settings. Log entries will remain, although any language variables added by the extension will not be available.', + + 'DISABLE_IN_PROGRESS' => 'The extension is currently being disabled, please do not leave this page or refresh until it is completed.', + 'ENABLE_IN_PROGRESS' => 'The extension is currently being installed, please do not leave this page or refresh until it is completed.', + 'PURGE_IN_PROGRESS' => 'The extension is currently being purged, please do not leave this page or refresh until it is completed.', + 'ENABLE_SUCCESS' => 'The extension was enabled successfully', + 'DISABLE_SUCCESS' => 'The extension was disabled successfully', + 'PURGE_SUCCESS' => 'The extension was purged successfully', + + 'ENABLE_FAIL' => 'The extension could not be enabled', + 'DISABLE_FAIL' => 'The extension could not be disabled', + 'PURGE_FAIL' => 'The extension could not be purged', + + 'EXTENSION_NAME' => 'Extension Name', + 'EXTENSION_ACTIONS' => 'Actions', + 'EXTENSION_OPTIONS' => 'Options', + + 'ENABLE_CONFIRM' => 'Are you sure that you wish to enable this extension?', + 'DISABLE_CONFIRM' => 'Are you sure that you wish to disable this extension?', + 'PURGE_CONFIRM' => 'Are you sure that you wish to purge this extension's data? This will remove all settings stored for this extension and cannot be undone!', + + 'WARNING' => 'Warning', + 'RETURN' => 'Return', + + 'EXT_DETAILS' => 'Extension Details', + 'DISPLAY_NAME' => 'Display Name', + 'CLEAN_NAME' => 'Clean Name', + 'TYPE' => 'Type', + 'DESCRIPTION' => 'Description', + 'VERSION' => 'Version', + 'HOMEPAGE' => 'Homepage', + 'PATH' => 'File Path', + 'TIME' => 'Release Time', + 'LICENCE' => 'Licence', + + 'REQUIREMENTS' => 'Requirements', + 'PHPBB_VERSION' => 'phpBB Version', + 'PHP_VERSION' => 'PHP Version', + 'AUTHOR_INFORMATION' => 'Author Information', + 'AUTHOR_NAME' => 'Name', + 'AUTHOR_EMAIL' => 'Email', + 'AUTHOR_HOMEPAGE' => 'Homepage', + 'AUTHOR_ROLE' => 'Role', +)); diff --git a/phpBB/language/en/acp/permissions_phpbb.php b/phpBB/language/en/acp/permissions_phpbb.php index 17649693fa..bb068e625f 100644 --- a/phpBB/language/en/acp/permissions_phpbb.php +++ b/phpBB/language/en/acp/permissions_phpbb.php @@ -226,6 +226,7 @@ $lang = array_merge($lang, array( 'acl_a_switchperm' => array('lang' => 'Can use others permissions', 'cat' => 'permissions'), 'acl_a_styles' => array('lang' => 'Can manage styles', 'cat' => 'misc'), + 'acl_a_extensions' => array('lang' => 'Can manage extensions', 'cat' => 'misc'), 'acl_a_viewlogs' => array('lang' => 'Can view logs', 'cat' => 'misc'), 'acl_a_clearlogs' => array('lang' => 'Can clear logs', 'cat' => 'misc'), 'acl_a_modules' => array('lang' => 'Can manage modules', 'cat' => 'misc'), diff --git a/tests/extension/acp.php b/tests/extension/acp.php new file mode 100644 index 0000000000..790df77c0d --- /dev/null +++ b/tests/extension/acp.php @@ -0,0 +1,205 @@ +copy_dir($phpbb_root_path . 'ext/', $phpbb_root_path . 'store/temp_ext/'); + + // Then empty the ext/ directory on the board (for accurate test cases) + self::$helper->empty_dir($phpbb_root_path . 'ext/'); + + // Copy our ext/ files from the test case to the board + self::$copied_files = array_merge(self::$copied_files, self::$helper->copy_dir(dirname(__FILE__) . '/ext/', $phpbb_root_path . 'ext/')); + } + + public function setUp() + { + parent::setUp(); + + $this->get_db(); + + // Clear the phpbb_ext table + $this->db->sql_query('DELETE FROM phpbb_ext'); + + // Insert our base data + $insert_rows = array( + array( + 'ext_name' => 'foo', + 'ext_active' => true, + 'ext_state' => 'b:0;', + ), + array( + 'ext_name' => 'vendor/moo', + 'ext_active' => false, + 'ext_state' => 'b:0;', + ), + + // do not exist + array( + 'ext_name' => 'test2', + 'ext_active' => true, + 'ext_state' => 'b:0;', + ), + array( + 'ext_name' => 'test3', + 'ext_active' => false, + 'ext_state' => 'b:0;', + ), + ); + $this->db->sql_multi_insert('phpbb_ext', $insert_rows); + + $this->login(); + $this->admin_login(); + + $this->add_lang('acp/extensions'); + } + + /** + * This should only be called once after the tests are run. + * This is used to remove the files copied to the phpBB install + */ + static public function tearDownAfterClass() + { + global $phpbb_root_path; + + // Copy back the board installed extensions from the temp directory + self::$helper->copy_dir($phpbb_root_path . 'store/temp_ext/', $phpbb_root_path . 'ext/'); + + self::$copied_files[] = $phpbb_root_path . 'store/temp_ext/'; + + // Remove all of the files we copied around (from board ext -> temp_ext, from test ext -> board ext) + self::$helper->remove_files(self::$copied_files); + } + + public function test_list() + { + $crawler = $this->request('GET', 'adm/index.php?i=acp_extensions&mode=main&sid=' . $this->sid); + + $this->assertCount(1, $crawler->filter('.ext_enabled')); + $this->assertCount(4, $crawler->filter('.ext_disabled')); + + $this->assertContains('phpBB Foo Extension', $crawler->filter('.ext_enabled')->eq(0)->text()); + $this->assertContainsLang('PURGE', $crawler->filter('.ext_enabled')->eq(0)->text()); + + $this->assertContains('The "test2" extension is not valid.', $crawler->filter('.ext_disabled')->eq(0)->text()); + + $this->assertContains('The "test3" extension is not valid.', $crawler->filter('.ext_disabled')->eq(1)->text()); + + $this->assertContains('phpBB Moo Extension', $crawler->filter('.ext_disabled')->eq(2)->text()); + $this->assertContainsLang('DETAILS', $crawler->filter('.ext_disabled')->eq(2)->text()); + $this->assertContainsLang('ENABLE', $crawler->filter('.ext_disabled')->eq(2)->text()); + $this->assertContainsLang('PURGE', $crawler->filter('.ext_disabled')->eq(2)->text()); + + $this->assertContains('The "bar" extension is not valid.', $crawler->filter('.ext_disabled')->eq(3)->text()); + } + + public function test_details() + { + $crawler = $this->request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=details&ext_name=foo&sid=' . $this->sid); + + $validation = array( + 'DISPLAY_NAME' => 'phpBB Foo Extension', + 'CLEAN_NAME' => 'foo/example', + 'DESCRIPTION' => 'An example/sample extension to be used for testing purposes in phpBB Development.', + 'VERSION' => '1.0.0', + 'TIME' => '2012-02-15 01:01:01', + 'LICENCE' => 'GPL-2.0', + 'PHPBB_VERSION' => '3.1.0-dev', + 'PHP_VERSION' => '>=5.3', + 'AUTHOR_NAME' => 'Nathan Guse', + 'AUTHOR_EMAIL' => 'email@phpbb.com', + 'AUTHOR_HOMEPAGE' => 'http://lithiumstudios.org', + 'AUTHOR_ROLE' => 'N/A', + ); + + for ($i = 0; $i < $crawler->filter('dl')->count(); $i++) + { + $text = $crawler->filter('dl')->eq($i)->text(); + + $match = false; + + foreach ($validation as $language_key => $expected) + { + if (strpos($text, $this->lang($language_key)) === 0) + { + $match = true; + + $this->assertContains($expected, $text); + } + } + + if (!$match) + { + $this->fail('Unexpected field: "' . $text . '"'); + } + } + } + + public function test_enable_pre() + { + // Foo is already enabled (redirect to list) + $crawler = $this->request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=enable_pre&ext_name=foo&sid=' . $this->sid); + $this->assertContainsLang('EXTENSION_NAME', $crawler->filter('html')->text()); + $this->assertContainsLang('EXTENSION_OPTIONS', $crawler->filter('html')->text()); + $this->assertContainsLang('EXTENSION_ACTIONS', $crawler->filter('html')->text()); + + $crawler = $this->request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=enable_pre&ext_name=vendor%2Fmoo&sid=' . $this->sid); + $this->assertContainsLang('ENABLE_CONFIRM', $crawler->filter('html')->text()); + } + + public function test_disable_pre() + { + // Moo is not enabled (redirect to list) + $crawler = $this->request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=disable_pre&ext_name=vendor%2Fmoo&sid=' . $this->sid); + $this->assertContainsLang('EXTENSION_NAME', $crawler->filter('html')->text()); + $this->assertContainsLang('EXTENSION_OPTIONS', $crawler->filter('html')->text()); + $this->assertContainsLang('EXTENSION_ACTIONS', $crawler->filter('html')->text()); + + $crawler = $this->request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=disable_pre&ext_name=foo&sid=' . $this->sid); + $this->assertContainsLang('DISABLE_CONFIRM', $crawler->filter('html')->text()); + } + + public function test_purge_pre() + { + // test2 is not available (error) + $crawler = $this->request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=purge_pre&ext_name=test2&sid=' . $this->sid); + $this->assertContains('The required file does not exist', $crawler->filter('html')->text()); + + $crawler = $this->request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=purge_pre&ext_name=foo&sid=' . $this->sid); + $this->assertContainsLang('PURGE_CONFIRM', $crawler->filter('html')->text()); + } + + public function test_actions() + { + $crawler = $this->request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=enable&ext_name=vendor%2Fmoo&sid=' . $this->sid); + $this->assertContainsLang('ENABLE_SUCCESS', $crawler->filter('html')->text()); + + $crawler = $this->request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=disable&ext_name=vendor%2Fmoo&sid=' . $this->sid); + $this->assertContainsLang('DISABLE_SUCCESS', $crawler->filter('html')->text()); + + $crawler = $this->request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=purge&ext_name=vendor%2Fmoo&sid=' . $this->sid); + $this->assertContainsLang('PURGE_SUCCESS', $crawler->filter('html')->text()); + } +} \ No newline at end of file diff --git a/tests/extension/ext/foo/composer.json b/tests/extension/ext/foo/composer.json new file mode 100644 index 0000000000..744f7be625 --- /dev/null +++ b/tests/extension/ext/foo/composer.json @@ -0,0 +1,22 @@ +{ + "name": "foo/example", + "type": "phpbb3-extension", + "description": "An example/sample extension to be used for testing purposes in phpBB Development.", + "version": "1.0.0", + "time": "2012-02-15 01:01:01", + "licence": "GPL-2.0", + "authors": [{ + "name": "Nathan Guse", + "username": "EXreaction", + "email": "email@phpbb.com", + "homepage": "http://lithiumstudios.org", + "role": "N/A" + }], + "require": { + "php": ">=5.3", + "phpbb": "3.1.0-dev" + }, + "extra": { + "display-name": "phpBB Foo Extension" + } +} diff --git a/tests/extension/ext/vendor/moo/composer.json b/tests/extension/ext/vendor/moo/composer.json new file mode 100644 index 0000000000..c91a5e027b --- /dev/null +++ b/tests/extension/ext/vendor/moo/composer.json @@ -0,0 +1,22 @@ +{ + "name": "moo/example", + "type": "phpbb3-extension", + "description": "An example/sample extension to be used for testing purposes in phpBB Development.", + "version": "1.0.0", + "time": "2012-02-15 01:01:01", + "licence": "GNU GPL v2", + "authors": [{ + "name": "Nathan Guse", + "username": "EXreaction", + "email": "email@phpbb.com", + "homepage": "http://lithiumstudios.org", + "role": "N/A" + }], + "require": { + "php": ">=5.3", + "phpbb": "3.1.0-dev" + }, + "extra": { + "display-name": "phpBB Moo Extension" + } +} diff --git a/tests/extension/manager_test.php b/tests/extension/manager_test.php index 45bed247ae..5cde5bccdb 100644 --- a/tests/extension/manager_test.php +++ b/tests/extension/manager_test.php @@ -27,6 +27,7 @@ class phpbb_extension_manager_test extends phpbb_database_test_case $this->extension_manager = new phpbb_extension_manager( $this->new_dbal(), + new phpbb_config(array()), 'phpbb_ext', dirname(__FILE__) . '/', '.php', @@ -90,6 +91,7 @@ class phpbb_extension_manager_test extends phpbb_database_test_case { $extension_manager = new phpbb_extension_manager( $this->new_dbal(), + new phpbb_config(array()), 'phpbb_ext', dirname(__FILE__) . '/', '.php' diff --git a/tests/extension/metadata_manager_test.php b/tests/extension/metadata_manager_test.php new file mode 100644 index 0000000000..9865f14314 --- /dev/null +++ b/tests/extension/metadata_manager_test.php @@ -0,0 +1,430 @@ +createXMLDataSet(dirname(__FILE__) . '/fixtures/extensions.xml'); + } + + protected function setUp() + { + parent::setUp(); + + $this->cache = new phpbb_mock_cache(); + $this->config = new phpbb_config(array( + 'version' => '3.1.0', + )); + $this->db = $this->new_dbal(); + $this->phpbb_root_path = dirname(__FILE__) . '/'; + $this->phpEx = '.php'; + $this->user = new phpbb_user(); + + $this->template = new phpbb_template( + $this->phpbb_root_path, + $this->phpEx, + $this->config, + $this->user, + new phpbb_style_resource_locator() + ); + + $this->extension_manager = new phpbb_extension_manager( + $this->db, + $this->config, + 'phpbb_ext', + $this->phpbb_root_path, + $this->phpEx, + $this->cache + ); + } + + // Should fail from missing composer.json + public function test_bar() + { + $ext_name = 'bar'; + + $manager = $this->get_metadata_manager($ext_name); + + try + { + $manager->get_metadata(); + } + catch(phpbb_extension_exception $e){} + + $this->assertEquals((string) $e, 'The required file does not exist: ' . $this->phpbb_root_path . $this->extension_manager->get_extension_path($ext_name) . 'composer.json'); + } + + // Should be the same as a direct json_decode of the composer.json file + public function test_foo() + { + $ext_name = 'foo'; + + $manager = $this->get_metadata_manager($ext_name); + + try + { + $metadata = $manager->get_metadata(); + } + catch(phpbb_extension_exception $e) + { + $this->fail($e); + } + + $json = json_decode(file_get_contents($this->phpbb_root_path . 'ext/foo/composer.json'), true); + + $this->assertEquals($metadata, $json); + } + + public function test_validator_non_existant() + { + $ext_name = 'validator'; + + $manager = $this->get_metadata_manager($ext_name); + + // Non-existant data + try + { + $manager->validate('name'); + + $this->fail('Exception not triggered'); + } + catch(phpbb_extension_exception $e) + { + $this->assertEquals((string) $e, 'Required meta field \'name\' has not been set.'); + } + + try + { + $manager->validate('type'); + + $this->fail('Exception not triggered'); + } + catch(phpbb_extension_exception $e) + { + $this->assertEquals((string) $e, 'Required meta field \'type\' has not been set.'); + } + + try + { + $manager->validate('licence'); + + $this->fail('Exception not triggered'); + } + catch(phpbb_extension_exception $e) + { + $this->assertEquals((string) $e, 'Required meta field \'licence\' has not been set.'); + } + + try + { + $manager->validate('version'); + + $this->fail('Exception not triggered'); + } + catch(phpbb_extension_exception $e) + { + $this->assertEquals((string) $e, 'Required meta field \'version\' has not been set.'); + } + + try + { + $manager->validate_authors(); + + $this->fail('Exception not triggered'); + } + catch(phpbb_extension_exception $e) + { + $this->assertEquals((string) $e, 'Required meta field \'authors\' has not been set.'); + } + + $manager->merge_metadata(array( + 'authors' => array( + array(), + ), + )); + + try + { + $manager->validate_authors(); + + $this->fail('Exception not triggered'); + } + catch(phpbb_extension_exception $e) + { + $this->assertEquals((string) $e, 'Required meta field \'author name\' has not been set.'); + } + } + + + public function test_validator_invalid() + { + $ext_name = 'validator'; + + $manager = $this->get_metadata_manager($ext_name); + + // Invalid data + $manager->set_metadata(array( + 'name' => 'asdf', + 'type' => 'asdf', + 'licence' => '', + 'version' => '', + )); + + try + { + $manager->validate('name'); + + $this->fail('Exception not triggered'); + } + catch(phpbb_extension_exception $e) + { + $this->assertEquals((string) $e, 'Meta field \'name\' is invalid.'); + } + + try + { + $manager->validate('type'); + + $this->fail('Exception not triggered'); + } + catch(phpbb_extension_exception $e) + { + $this->assertEquals((string) $e, 'Meta field \'type\' is invalid.'); + } + + try + { + $manager->validate('licence'); + + $this->fail('Exception not triggered'); + } + catch(phpbb_extension_exception $e) + { + $this->assertEquals((string) $e, 'Meta field \'licence\' is invalid.'); + } + + try + { + $manager->validate('version'); + + $this->fail('Exception not triggered'); + } + catch(phpbb_extension_exception $e) + { + $this->assertEquals((string) $e, 'Meta field \'version\' is invalid.'); + } + } + + public function test_validator_valid() + { + $ext_name = 'validator'; + + $manager = $this->get_metadata_manager($ext_name); + + // Valid data + $manager->set_metadata(array( + 'name' => 'test/foo', + 'type' => 'phpbb3-extension', + 'licence' => 'GPL v2', + 'version' => '1.0.0', + )); + + try + { + $this->assertEquals(true, $manager->validate('enable')); + } + catch(phpbb_extension_exception $e) + { + $this->fail($e); + } + } + + + public function test_validator_requirements() + { + $ext_name = 'validator'; + + $manager = $this->get_metadata_manager($ext_name); + // Too high of requirements + $manager->merge_metadata(array( + 'require' => array( + 'php' => '10.0.0', + 'phpbb' => '3.2.0', // config is set to 3.1.0 + ), + )); + + try + { + $this->assertEquals(false, $manager->validate_require_php()); + $this->assertEquals(false, $manager->validate_require_phpbb()); + } + catch(phpbb_extension_exception $e) + { + $this->fail($e); + } + + + // Too high of requirements + $manager->merge_metadata(array( + 'require' => array( + 'php' => '5.3.0', + 'phpbb' => '3.1.0-beta', // config is set to 3.1.0 + ), + )); + + try + { + $this->assertEquals(true, $manager->validate_require_php()); + $this->assertEquals(true, $manager->validate_require_phpbb()); + } + catch(phpbb_extension_exception $e) + { + $this->fail($e); + } + + + // Too high of requirements + $manager->merge_metadata(array( + 'require' => array( + 'php' => '>' . phpversion(), + 'phpbb' => '>3.1.0', // config is set to 3.1.0 + ), + )); + + try + { + $this->assertEquals(false, $manager->validate_require_php()); + $this->assertEquals(false, $manager->validate_require_phpbb()); + } + catch(phpbb_extension_exception $e) + { + $this->fail($e); + } + + + // Too high of current install + $manager->merge_metadata(array( + 'require' => array( + 'php' => '<' . phpversion(), + 'phpbb' => '<3.1.0', // config is set to 3.1.0 + ), + )); + + try + { + $this->assertEquals(false, $manager->validate_require_php()); + $this->assertEquals(false, $manager->validate_require_phpbb()); + } + catch(phpbb_extension_exception $e) + { + $this->fail($e); + } + + + // Matching requirements + $manager->merge_metadata(array( + 'require' => array( + 'php' => phpversion(), + 'phpbb' => '3.1.0', // config is set to 3.1.0 + ), + )); + + try + { + $this->assertEquals(true, $manager->validate_require_php()); + $this->assertEquals(true, $manager->validate_require_phpbb()); + } + catch(phpbb_extension_exception $e) + { + $this->fail($e); + } + + + // Matching requirements + $manager->merge_metadata(array( + 'require' => array( + 'php' => '>=' . phpversion(), + 'phpbb' => '>=3.1.0', // config is set to 3.1.0 + ), + )); + + try + { + $this->assertEquals(true, $manager->validate_require_php()); + $this->assertEquals(true, $manager->validate_require_phpbb()); + } + catch(phpbb_extension_exception $e) + { + $this->fail($e); + } + + + // Matching requirements + $manager->merge_metadata(array( + 'require' => array( + 'php' => '<=' . phpversion(), + 'phpbb' => '<=3.1.0', // config is set to 3.1.0 + ), + )); + + try + { + $this->assertEquals(true, $manager->validate_require_php()); + $this->assertEquals(true, $manager->validate_require_phpbb()); + } + catch(phpbb_extension_exception $e) + { + $this->fail($e); + } + } + + /** + * Get an instance of the metadata manager + * + * @param string $ext_name + * @return phpbb_extension_metadata_manager_test + */ + private function get_metadata_manager($ext_name) + { + return new phpbb_extension_metadata_manager_test( + $ext_name, + $this->db, + $this->extension_manager, + $this->phpbb_root_path, + $this->phpEx, + $this->template, + $this->config + ); + } +} + +class phpbb_extension_metadata_manager_test extends phpbb_extension_metadata_manager +{ + public function set_metadata($metadata) + { + $this->metadata = $metadata; + } + + public function merge_metadata($metadata) + { + $this->metadata = array_merge($this->metadata, $metadata); + } +} \ No newline at end of file diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index fca66516ba..d002615e8c 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -125,6 +125,7 @@ class phpbb_functional_test_case extends phpbb_test_case { $this->extension_manager = new phpbb_extension_manager( $this->get_db(), + new phpbb_config(), self::$config['table_prefix'] . 'ext', $phpbb_root_path, ".$phpEx", @@ -251,6 +252,48 @@ class phpbb_functional_test_case extends phpbb_test_case } } + /** + * Login to the ACP + * You must run login() before calling this. + */ + protected function admin_login() + { + $this->add_lang('acp/common'); + + // Requires login first! + if (empty($this->sid)) + { + $this->fail('$this->sid is empty. Make sure you call login() before admin_login()'); + return; + } + + $crawler = $this->request('GET', 'adm/index.php?sid=' . $this->sid); + $this->assertContains($this->lang('LOGIN_ADMIN_CONFIRM'), $crawler->filter('html')->text()); + + $form = $crawler->selectButton($this->lang('LOGIN'))->form(); + + foreach ($form->getValues() as $field => $value) + { + if (strpos($field, 'password_') === 0) + { + $login = $this->client->submit($form, array('username' => 'admin', $field => 'admin')); + + $cookies = $this->cookieJar->all(); + + // The session id is stored in a cookie that ends with _sid - we assume there is only one such cookie + foreach ($cookies as $cookie); + { + if (substr($cookie->getName(), -4) == '_sid') + { + $this->sid = $cookie->getValue(); + } + } + + break; + } + } + } + protected function add_lang($lang_file) { if (is_array($lang_file)) @@ -287,4 +330,16 @@ class phpbb_functional_test_case extends phpbb_test_case return call_user_func_array('sprintf', $args); } + + /** + * assertContains for language strings + * + * @param string $needle Search string + * @param string $haystack Search this + * @param string $message Optional failure message + */ + public function assertContainsLang($needle, $haystack, $message = null) + { + $this->assertContains(html_entity_decode($this->lang($needle), ENT_QUOTES), $haystack, $message); + } } diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 46feef550a..d10645a732 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -115,4 +115,112 @@ class phpbb_test_case_helpers return $config; } + + /** + * Recursive directory copying function + * + * @param string $source + * @param string $dest + * @return array list of files copied + */ + public function copy_dir($source, $dest) + { + $source = (substr($source, -1) == '/') ? $source : $source . '/'; + $dest = (substr($dest, -1) == '/') ? $dest : $dest . '/'; + + $copied_files = array(); + + if (!is_dir($dest)) + { + $this->makedirs($dest); + } + + $files = scandir($source); + foreach ($files as $file) + { + if ($file == '.' || $file == '..') + { + continue; + } + + if (is_dir($source . $file)) + { + $created_dir = false; + if (!is_dir($dest . $file)) + { + $created_dir = true; + $this->makedirs($dest . $file); + } + + $copied_files = array_merge($copied_files, self::copy_dir($source . $file, $dest . $file)); + + if ($created_dir) + { + $copied_files[] = $dest . $file; + } + } + else + { + if (!file_exists($dest . $file)) + { + copy($source . $file, $dest . $file); + + $copied_files[] = $dest . $file; + } + } + } + + return $copied_files; + } + + /** + * Remove files/directories that are listed in an array + * Designed for use with $this->copy_dir() + * + * @param array $file_list + */ + public function remove_files($file_list) + { + foreach ($file_list as $file) + { + if (is_dir($file)) + { + rmdir($file); + } + else + { + unlink($file); + } + } + } + + /** + * Empty directory (remove any subdirectories/files below) + * + * @param array $file_list + */ + public function empty_dir($path) + { + $path = (substr($path, -1) == '/') ? $path : $path . '/'; + + $files = scandir($path); + foreach ($files as $file) + { + if ($file == '.' || $file == '..') + { + continue; + } + + if (is_dir($path . $file)) + { + $this->empty_dir($path . $file); + + rmdir($path . $file); + } + else + { + unlink($path . $file); + } + } + } }