aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_framework/phpbb_functional_test_case.php
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_framework/phpbb_functional_test_case.php')
-rw-r--r--tests/test_framework/phpbb_functional_test_case.php697
1 files changed, 600 insertions, 97 deletions
diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php
index 9b64600c7d..8107e45dc7 100644
--- a/tests/test_framework/phpbb_functional_test_case.php
+++ b/tests/test_framework/phpbb_functional_test_case.php
@@ -1,16 +1,18 @@
<?php
/**
*
-* @package testing
-* @copyright (c) 2011 phpBB Group
-* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
*
*/
use Symfony\Component\BrowserKit\CookieJar;
require_once __DIR__ . '/../../phpBB/includes/functions_install.php';
-require_once __DIR__ . '/../../phpBB/includes/acm/acm_file.php';
-require_once __DIR__ . '/../../phpBB/includes/cache.php';
class phpbb_functional_test_case extends phpbb_test_case
{
@@ -20,6 +22,7 @@ class phpbb_functional_test_case extends phpbb_test_case
protected $cache = null;
protected $db = null;
+ protected $extension_manager = null;
/**
* Session ID for current test's session (each test makes its own)
@@ -35,6 +38,7 @@ class phpbb_functional_test_case extends phpbb_test_case
static protected $config = array();
static protected $already_installed = false;
+ static protected $last_post_timestamp = 0;
static public function setUpBeforeClass()
{
@@ -43,6 +47,12 @@ class phpbb_functional_test_case extends phpbb_test_case
self::$config = phpbb_test_case_helpers::get_test_config();
self::$root_url = self::$config['phpbb_functional_url'];
+ // Important: this is used both for installation and by
+ // test cases for querying the tables.
+ // Therefore table prefix must be set before a board is
+ // installed, and also before each test case is run.
+ self::$config['table_prefix'] = 'phpbb_';
+
if (!isset(self::$config['phpbb_functional_url']))
{
self::markTestSkipped('phpbb_functional_url was not set in test_config and wasn\'t set as PHPBB_FUNCTIONAL_URL environment variable either.');
@@ -55,6 +65,14 @@ class phpbb_functional_test_case extends phpbb_test_case
}
}
+ /**
+ * @return array List of extensions that should be set up
+ */
+ static protected function setup_extensions()
+ {
+ return array();
+ }
+
public function setUp()
{
parent::setUp();
@@ -71,7 +89,36 @@ class phpbb_functional_test_case extends phpbb_test_case
// that were added in other tests are gone
$this->lang = array();
$this->add_lang('common');
- $this->purge_cache();
+
+ $db = $this->get_db();
+
+ foreach (static::setup_extensions() as $extension)
+ {
+ $this->purge_cache();
+
+ $sql = 'SELECT ext_active
+ FROM ' . EXT_TABLE . "
+ WHERE ext_name = '" . $db->sql_escape($extension). "'";
+ $result = $db->sql_query($sql);
+ $status = (bool) $db->sql_fetchfield('ext_active');
+ $db->sql_freeresult($result);
+
+ if (!$status)
+ {
+ $this->install_ext($extension);
+ }
+ }
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+
+ if ($this->db instanceof \phpbb\db\driver\driver_interface)
+ {
+ // Close the database connections again this test
+ $this->db->sql_close();
+ }
}
/**
@@ -132,18 +179,23 @@ class phpbb_functional_test_case extends phpbb_test_case
{
}
+ public function __construct($name = NULL, array $data = array(), $dataName = '')
+ {
+ parent::__construct($name, $data, $dataName);
+
+ $this->backupStaticAttributesBlacklist += array(
+ 'phpbb_functional_test_case' => array('config', 'already_installed'),
+ );
+ }
+
protected function get_db()
{
global $phpbb_root_path, $phpEx;
// so we don't reopen an open connection
- if (!($this->db instanceof dbal))
+ if (!($this->db instanceof \phpbb\db\driver\driver_interface))
{
- if (!class_exists('dbal_' . self::$config['dbms']))
- {
- include($phpbb_root_path . 'includes/db/' . self::$config['dbms'] . ".$phpEx");
- }
- $sql_db = 'dbal_' . self::$config['dbms'];
- $this->db = new $sql_db();
+ $dbms = self::$config['dbms'];
+ $this->db = new $dbms();
$this->db->sql_connect(self::$config['dbhost'], self::$config['dbuser'], self::$config['dbpasswd'], self::$config['dbname'], self::$config['dbport']);
}
return $this->db;
@@ -153,7 +205,7 @@ class phpbb_functional_test_case extends phpbb_test_case
{
if (!$this->cache)
{
- $this->cache = new cache();
+ $this->cache = new \phpbb\cache\driver\file;
}
return $this->cache;
@@ -168,20 +220,50 @@ class phpbb_functional_test_case extends phpbb_test_case
$cache->load();
}
- public function __construct($name = NULL, array $data = array(), $dataName = '')
+ protected function get_extension_manager()
{
- parent::__construct($name, $data, $dataName);
+ global $phpbb_root_path, $phpEx;
- $this->backupStaticAttributesBlacklist += array(
- 'phpbb_functional_test_case' => array('config', 'already_installed'),
+ $config = new \phpbb\config\config(array());
+ $db = $this->get_db();
+ $db_tools = new \phpbb\db\tools($db);
+
+ $container = new phpbb_mock_container_builder();
+ $migrator = new \phpbb\db\migrator(
+ $container,
+ $config,
+ $db,
+ $db_tools,
+ self::$config['table_prefix'] . 'migrations',
+ $phpbb_root_path,
+ $phpEx,
+ self::$config['table_prefix'],
+ array(),
+ new \phpbb\db\migration\helper()
);
+ $container->set('migrator', $migrator);
+ $container->set('dispatcher', new phpbb_mock_event_dispatcher());
+ $user = new \phpbb\user('\phpbb\datetime');
+
+ $extension_manager = new \phpbb\extension\manager(
+ $container,
+ $db,
+ $config,
+ new phpbb\filesystem(),
+ $user,
+ self::$config['table_prefix'] . 'ext',
+ dirname(__FILE__) . '/',
+ $phpEx,
+ $this->get_cache_driver()
+ );
+
+ return $extension_manager;
}
static protected function install_board()
{
global $phpbb_root_path, $phpEx;
- self::$config['table_prefix'] = 'phpbb_';
self::recreate_database(self::$config);
$config_file = $phpbb_root_path . "config.$phpEx";
@@ -216,7 +298,7 @@ class phpbb_functional_test_case extends phpbb_test_case
$parseURL = parse_url(self::$config['phpbb_functional_url']);
- $crawler = self::request('GET', 'install/index.php?mode=install');
+ $crawler = self::request('GET', 'install/index.php?mode=install&language=en');
self::assertContains('Welcome to Installation', $crawler->filter('#main')->text());
$form = $crawler->selectButton('submit')->form();
@@ -230,7 +312,7 @@ class phpbb_functional_test_case extends phpbb_test_case
self::assertContains('Database configuration', $crawler->filter('#main')->text());
$form = $crawler->selectButton('submit')->form(array(
// Installer uses 3.0-style dbms name
- 'dbms' => str_replace('phpbb_db_driver_', '', self::$config['dbms']),
+ 'dbms' => str_replace('phpbb\db\driver\\', '', self::$config['dbms']),
'dbhost' => self::$config['dbhost'],
'dbport' => self::$config['dbport'],
'dbname' => self::$config['dbname'],
@@ -252,8 +334,7 @@ class phpbb_functional_test_case extends phpbb_test_case
'admin_name' => 'admin',
'admin_pass1' => 'adminadmin',
'admin_pass2' => 'adminadmin',
- 'board_email1' => 'nobody@example.com',
- 'board_email2' => 'nobody@example.com',
+ 'board_email' => 'nobody@example.com',
));
// install/index.php?mode=install&sub=administrator
@@ -265,7 +346,7 @@ class phpbb_functional_test_case extends phpbb_test_case
// because that step will create a config.php file if phpBB has the
// permission to do so. We have to create the config file on our own
// in order to get the DEBUG constants defined.
- $config_php_data = phpbb_create_config_file_data(self::$config, self::$config['dbms'], array(), true, true);
+ $config_php_data = phpbb_create_config_file_data(self::$config, self::$config['dbms'], true, false, true);
$config_created = file_put_contents($config_file, $config_php_data) !== false;
if (!$config_created)
{
@@ -317,6 +398,36 @@ class phpbb_functional_test_case extends phpbb_test_case
copy($config_file, $config_file_test);
}
+ public function install_ext($extension)
+ {
+ $this->login();
+ $this->admin_login();
+
+ $ext_path = str_replace('/', '%2F', $extension);
+
+ $crawler = self::request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=enable_pre&ext_name=' . $ext_path . '&sid=' . $this->sid);
+ $this->assertGreaterThan(0, $crawler->filter('.submit-buttons')->count());
+
+ $form = $crawler->selectButton('Enable')->form();
+ $crawler = self::submit($form);
+ $this->add_lang('acp/extensions');
+
+ $meta_refresh = $crawler->filter('meta[http-equiv="refresh"]');
+
+ // Wait for extension to be fully enabled
+ while (sizeof($meta_refresh))
+ {
+ preg_match('#url=.+/(adm+.+)#', $meta_refresh->attr('content'), $match);
+ $url = $match[1];
+ $crawler = self::request('POST', $url);
+ $meta_refresh = $crawler->filter('meta[http-equiv="refresh"]');
+ }
+
+ $this->assertContainsLang('EXTENSION_ENABLE_SUCCESS', $crawler->filter('div.successbox')->text());
+
+ $this->logout();
+ }
+
static private function recreate_database($config)
{
$db_conn_mgr = new phpbb_database_test_connection_manager($config);
@@ -336,51 +447,67 @@ class phpbb_functional_test_case extends phpbb_test_case
global $phpbb_root_path;
$db = $this->get_db();
- $sql = 'INSERT INTO ' . STYLES_TABLE . ' ' . $db->sql_build_array('INSERT', array(
- 'style_id' => $style_id,
- 'style_name' => $style_path,
- 'style_copyright' => '',
- 'style_active' => 1,
- 'template_id' => $style_id,
- 'theme_id' => $style_id,
- 'imageset_id' => $style_id,
- ));
- $db->sql_query($sql);
-
- $sql = 'INSERT INTO ' . STYLES_IMAGESET_TABLE . ' ' . $db->sql_build_array('INSERT', array(
- 'imageset_id' => $style_id,
- 'imageset_name' => $style_path,
- 'imageset_copyright' => '',
- 'imageset_path' => $style_path,
- ));
- $db->sql_query($sql);
-
- $sql = 'INSERT INTO ' . STYLES_TEMPLATE_TABLE . ' ' . $db->sql_build_array('INSERT', array(
- 'template_id' => $style_id,
- 'template_name' => $style_path,
- 'template_copyright' => '',
- 'template_path' => $style_path,
- 'bbcode_bitfield' => 'kNg=',
- 'template_inherits_id' => $parent_style_id,
- 'template_inherit_path' => $parent_style_path,
- ));
- $db->sql_query($sql);
-
- $sql = 'INSERT INTO ' . STYLES_THEME_TABLE . ' ' . $db->sql_build_array('INSERT', array(
- 'theme_id' => $style_id,
- 'theme_name' => $style_path,
- 'theme_copyright' => '',
- 'theme_path' => $style_path,
- 'theme_storedb' => 0,
- 'theme_mtime' => 0,
- 'theme_data' => '',
- ));
- $db->sql_query($sql);
-
- if ($style_path != 'prosilver' && $style_path != 'subsilver2')
+ if (version_compare(PHPBB_VERSION, '3.1.0-dev', '<'))
+ {
+ $sql = 'INSERT INTO ' . STYLES_TABLE . ' ' . $db->sql_build_array('INSERT', array(
+ 'style_id' => $style_id,
+ 'style_name' => $style_path,
+ 'style_copyright' => '',
+ 'style_active' => 1,
+ 'template_id' => $style_id,
+ 'theme_id' => $style_id,
+ 'imageset_id' => $style_id,
+ ));
+ $db->sql_query($sql);
+
+ $sql = 'INSERT INTO ' . STYLES_IMAGESET_TABLE . ' ' . $db->sql_build_array('INSERT', array(
+ 'imageset_id' => $style_id,
+ 'imageset_name' => $style_path,
+ 'imageset_copyright' => '',
+ 'imageset_path' => $style_path,
+ ));
+ $db->sql_query($sql);
+
+ $sql = 'INSERT INTO ' . STYLES_TEMPLATE_TABLE . ' ' . $db->sql_build_array('INSERT', array(
+ 'template_id' => $style_id,
+ 'template_name' => $style_path,
+ 'template_copyright' => '',
+ 'template_path' => $style_path,
+ 'bbcode_bitfield' => 'kNg=',
+ 'template_inherits_id' => $parent_style_id,
+ 'template_inherit_path' => $parent_style_path,
+ ));
+ $db->sql_query($sql);
+
+ $sql = 'INSERT INTO ' . STYLES_THEME_TABLE . ' ' . $db->sql_build_array('INSERT', array(
+ 'theme_id' => $style_id,
+ 'theme_name' => $style_path,
+ 'theme_copyright' => '',
+ 'theme_path' => $style_path,
+ 'theme_storedb' => 0,
+ 'theme_mtime' => 0,
+ 'theme_data' => '',
+ ));
+ $db->sql_query($sql);
+
+ if ($style_path != 'prosilver' && $style_path != 'subsilver2')
+ {
+ @mkdir($phpbb_root_path . 'styles/' . $style_path, 0777);
+ @mkdir($phpbb_root_path . 'styles/' . $style_path . '/template', 0777);
+ }
+ }
+ else
{
- @mkdir($phpbb_root_path . 'styles/' . $style_path, 0777);
- @mkdir($phpbb_root_path . 'styles/' . $style_path . '/template', 0777);
+ $db->sql_multi_insert(STYLES_TABLE, array(array(
+ 'style_id' => $style_id,
+ 'style_name' => $style_path,
+ 'style_copyright' => '',
+ 'style_active' => 1,
+ 'style_path' => $style_path,
+ 'bbcode_bitfield' => 'kNg=',
+ 'style_parent_id' => $parent_style_id,
+ 'style_parent_tree' => $parent_style_path,
+ )));
}
}
@@ -396,14 +523,17 @@ class phpbb_functional_test_case extends phpbb_test_case
$db = $this->get_db();
$db->sql_query('DELETE FROM ' . STYLES_TABLE . ' WHERE style_id = ' . $style_id);
- $db->sql_query('DELETE FROM ' . STYLES_IMAGESET_TABLE . ' WHERE imageset_id = ' . $style_id);
- $db->sql_query('DELETE FROM ' . STYLES_TEMPLATE_TABLE . ' WHERE template_id = ' . $style_id);
- $db->sql_query('DELETE FROM ' . STYLES_THEME_TABLE . ' WHERE theme_id = ' . $style_id);
-
- if ($style_path != 'prosilver' && $style_path != 'subsilver2')
+ if (version_compare(PHPBB_VERSION, '3.1.0-dev', '<'))
{
- @rmdir($phpbb_root_path . 'styles/' . $style_path . '/template');
- @rmdir($phpbb_root_path . 'styles/' . $style_path);
+ $db->sql_query('DELETE FROM ' . STYLES_IMAGESET_TABLE . ' WHERE imageset_id = ' . $style_id);
+ $db->sql_query('DELETE FROM ' . STYLES_TEMPLATE_TABLE . ' WHERE template_id = ' . $style_id);
+ $db->sql_query('DELETE FROM ' . STYLES_THEME_TABLE . ' WHERE theme_id = ' . $style_id);
+
+ if ($style_path != 'prosilver' && $style_path != 'subsilver2')
+ {
+ @rmdir($phpbb_root_path . 'styles/' . $style_path . '/template');
+ @rmdir($phpbb_root_path . 'styles/' . $style_path);
+ }
}
}
@@ -418,10 +548,7 @@ class phpbb_functional_test_case extends phpbb_test_case
// Required by unique_id
global $config;
- if (!is_array($config))
- {
- $config = array();
- }
+ $config = new \phpbb\config\config(array());
/*
* Add required config entries to the config array to prevent
@@ -436,7 +563,7 @@ class phpbb_functional_test_case extends phpbb_test_case
$config['rand_seed_last_update'] = time() + 600;
// Required by user_add
- global $db, $cache;
+ global $db, $cache, $phpbb_dispatcher, $phpbb_container;
$db = $this->get_db();
if (!function_exists('phpbb_mock_null_cache'))
{
@@ -444,6 +571,12 @@ class phpbb_functional_test_case extends phpbb_test_case
}
$cache = new phpbb_mock_null_cache;
+ $cache_driver = new \phpbb\cache\driver\null();
+ $phpbb_container = new phpbb_mock_container_builder();
+ $phpbb_container->set('cache.driver', $cache_driver);
+ $phpbb_notifications = new phpbb_mock_notification_manager();
+ $phpbb_container->set('notification_manager', $phpbb_notifications);
+
if (!function_exists('utf_clean_string'))
{
require_once(__DIR__ . '/../../phpBB/includes/utf/utf_tools.php');
@@ -452,6 +585,10 @@ class phpbb_functional_test_case extends phpbb_test_case
{
require_once(__DIR__ . '/../../phpBB/includes/functions_user.php');
}
+ set_config(null, null, null, $config);
+ set_config_count(null, null, null, $config);
+ $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
+ $passwords_manager = $this->get_passwords_manager();
$user_row = array(
'username' => $username,
@@ -459,13 +596,94 @@ class phpbb_functional_test_case extends phpbb_test_case
'user_email' => 'nobody@example.com',
'user_type' => 0,
'user_lang' => 'en',
- 'user_timezone' => 0,
- 'user_dateformat' => '',
- 'user_password' => phpbb_hash($username . $username),
+ 'user_timezone' => 'UTC',
+ 'user_dateformat' => 'r',
+ 'user_password' => $passwords_manager->hash($username . $username),
);
return user_add($user_row);
}
+ protected function remove_user_group($group_name, $usernames)
+ {
+ global $db, $cache, $auth, $config, $phpbb_dispatcher, $phpbb_log, $phpbb_container, $phpbb_root_path, $phpEx;
+
+ $config = new \phpbb\config\config(array());
+ $config['coppa_enable'] = 0;
+
+ $db = $this->get_db();
+ $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
+ $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ $auth = $this->getMock('\phpbb\auth\auth');
+
+ $phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE);
+ $cache = new phpbb_mock_null_cache;
+
+ $cache_driver = new \phpbb\cache\driver\null();
+ $phpbb_container = new phpbb_mock_container_builder();
+ $phpbb_container->set('cache.driver', $cache_driver);
+ $phpbb_container->set('notification_manager', new phpbb_mock_notification_manager());
+
+ if (!function_exists('utf_clean_string'))
+ {
+ require_once(__DIR__ . '/../../phpBB/includes/utf/utf_tools.php');
+ }
+ if (!function_exists('group_user_del'))
+ {
+ require_once(__DIR__ . '/../../phpBB/includes/functions_user.php');
+ }
+
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = '" . $db->sql_escape($group_name) . "'";
+ $result = $db->sql_query($sql);
+ $group_id = (int) $db->sql_fetchfield('group_id');
+ $db->sql_freeresult($result);
+
+ return group_user_del($group_id, false, $usernames, $group_name);
+ }
+
+ protected function add_user_group($group_name, $usernames, $default = false, $leader = false)
+ {
+ global $db, $cache, $auth, $config, $phpbb_dispatcher, $phpbb_log, $phpbb_container, $phpbb_root_path, $phpEx;
+
+ $config = new \phpbb\config\config(array());
+ $config['coppa_enable'] = 0;
+
+ $db = $this->get_db();
+ $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
+ $user = $this->getMock('\phpbb\user', array(), array('\phpbb\datetime'));
+ $auth = $this->getMock('\phpbb\auth\auth');
+
+ $phpbb_log = new \phpbb\log\log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE);
+ $cache = new phpbb_mock_null_cache;
+
+ $cache_driver = new \phpbb\cache\driver\null();
+ $phpbb_container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+ $phpbb_container
+ ->expects($this->any())
+ ->method('get')
+ ->with('cache.driver')
+ ->will($this->returnValue($cache_driver));
+
+ if (!function_exists('utf_clean_string'))
+ {
+ require_once(__DIR__ . '/../../phpBB/includes/utf/utf_tools.php');
+ }
+ if (!function_exists('group_user_del'))
+ {
+ require_once(__DIR__ . '/../../phpBB/includes/functions_user.php');
+ }
+
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = '" . $db->sql_escape($group_name) . "'";
+ $result = $db->sql_query($sql);
+ $group_id = (int) $db->sql_fetchfield('group_id');
+ $db->sql_freeresult($result);
+
+ return group_user_add($group_id, false, $usernames, $group_name, $default, $leader);
+ }
+
protected function login($username = 'admin')
{
$this->add_lang('ucp');
@@ -475,7 +693,7 @@ class phpbb_functional_test_case extends phpbb_test_case
$form = $crawler->selectButton($this->lang('LOGIN'))->form();
$crawler = self::submit($form, array('username' => $username, 'password' => $username . $username));
- $this->assertContains($this->lang('LOGIN_REDIRECT'), $crawler->filter('html')->text());
+ $this->assertNotContains($this->lang('LOGIN'), $crawler->filter('.navbar')->text());
$cookies = self::$cookieJar->all();
@@ -489,6 +707,16 @@ class phpbb_functional_test_case extends phpbb_test_case
}
}
+ protected function logout()
+ {
+ $this->add_lang('ucp');
+
+ $crawler = self::request('GET', 'ucp.php?sid=' . $this->sid . '&mode=logout');
+ $this->assertContains($this->lang('REGISTER'), $crawler->filter('.navbar')->text());
+ unset($this->sid);
+
+ }
+
/**
* Login to the ACP
* You must run login() before calling this.
@@ -514,7 +742,7 @@ class phpbb_functional_test_case extends phpbb_test_case
if (strpos($field, 'password_') === 0)
{
$crawler = self::submit($form, array('username' => $username, $field => $username . $username));
- $this->assertContains($this->lang('LOGIN_ADMIN_SUCCESS'), $crawler->filter('html')->text());
+ $this->assertContains($this->lang('ADMIN_PANEL'), $crawler->filter('h1')->text());
$cookies = self::$cookieJar->all();
@@ -554,6 +782,30 @@ class phpbb_functional_test_case extends phpbb_test_case
$this->lang = array_merge($this->lang, $lang);
}
+ protected function add_lang_ext($ext_name, $lang_file)
+ {
+ if (is_array($lang_file))
+ {
+ foreach ($lang_file as $file)
+ {
+ $this->add_lang_ext($ext_name, $file);
+ }
+
+ return;
+ }
+
+ $lang_path = __DIR__ . "/../../phpBB/ext/{$ext_name}/language/en/$lang_file.php";
+
+ $lang = array();
+
+ if (file_exists($lang_path))
+ {
+ include($lang_path);
+ }
+
+ $this->lang = array_merge($this->lang, $lang);
+ }
+
protected function lang()
{
$args = func_get_args();
@@ -570,6 +822,30 @@ class phpbb_functional_test_case extends phpbb_test_case
}
/**
+ * 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);
+ }
+
+ /**
+ * assertNotContains for language strings
+ *
+ * @param string $needle Search string
+ * @param string $haystack Search this
+ * @param string $message Optional failure message
+ */
+ public function assertNotContainsLang($needle, $haystack, $message = null)
+ {
+ $this->assertNotContains(html_entity_decode($this->lang($needle), ENT_QUOTES), $haystack, $message);
+ }
+
+ /*
* Perform some basic assertions for the page
*
* Checks for debug/error output before the actual page content and the status code
@@ -579,15 +855,36 @@ class phpbb_functional_test_case extends phpbb_test_case
*/
static public function assert_response_html($status_code = 200)
{
+ // Any output before the doc type means there was an error
+ $content = self::$client->getResponse()->getContent();
+ self::assertNotContains('[phpBB Debug]', $content);
+ self::assertStringStartsWith('<!DOCTYPE', trim($content), 'Output found before DOCTYPE specification.');
+
if ($status_code !== false)
{
self::assert_response_status_code($status_code);
}
+ }
- // Any output before the doc type means there was an error
+ /*
+ * Perform some basic assertions for an xml page
+ *
+ * Checks for debug/error output before the actual page content and the status code
+ *
+ * @param mixed $status_code Expected status code, false to disable check
+ * @return null
+ */
+ static public function assert_response_xml($status_code = 200)
+ {
+ // Any output before the xml opening means there was an error
$content = self::$client->getResponse()->getContent();
self::assertNotContains('[phpBB Debug]', $content);
- self::assertStringStartsWith('<!DOCTYPE', trim($content), 'Output found before DOCTYPE specification.');
+ self::assertStringStartsWith('<?xml', trim($content), 'Output found before XML specification.');
+
+ if ($status_code !== false)
+ {
+ self::assert_response_status_code($status_code);
+ }
}
/**
@@ -604,6 +901,86 @@ class phpbb_functional_test_case extends phpbb_test_case
self::assertEquals($status_code, self::$client->getResponse()->getStatus(), 'HTTP status code does not match');
}
+ public function assert_filter($crawler, $expr, $msg = null)
+ {
+ $nodes = $crawler->filter($expr);
+ if ($msg)
+ {
+ $msg .= "\n";
+ }
+ else
+ {
+ $msg = '';
+ }
+ $msg .= "`$expr` not found in DOM.";
+ $this->assertGreaterThan(0, count($nodes), $msg);
+ return $nodes;
+ }
+
+ /**
+ * Asserts that exactly one checkbox with name $name exists within the scope
+ * of $crawler and that the checkbox is checked.
+ *
+ * @param Symfony\Component\DomCrawler\Crawler $crawler
+ * @param string $name
+ * @param string $message
+ *
+ * @return null
+ */
+ public function assert_checkbox_is_checked($crawler, $name, $message = '')
+ {
+ $this->assertSame(
+ 'checked',
+ $this->assert_find_one_checkbox($crawler, $name)->attr('checked'),
+ $message ?: "Failed asserting that checkbox $name is checked."
+ );
+ }
+
+ /**
+ * Asserts that exactly one checkbox with name $name exists within the scope
+ * of $crawler and that the checkbox is unchecked.
+ *
+ * @param Symfony\Component\DomCrawler\Crawler $crawler
+ * @param string $name
+ * @param string $message
+ *
+ * @return null
+ */
+ public function assert_checkbox_is_unchecked($crawler, $name, $message = '')
+ {
+ $this->assertSame(
+ '',
+ $this->assert_find_one_checkbox($crawler, $name)->attr('checked'),
+ $message ?: "Failed asserting that checkbox $name is unchecked."
+ );
+ }
+
+ /**
+ * Searches for an input element of type checkbox with the name $name using
+ * $crawler. Contains an assertion that only one such checkbox exists within
+ * the scope of $crawler.
+ *
+ * @param Symfony\Component\DomCrawler\Crawler $crawler
+ * @param string $name
+ * @param string $message
+ *
+ * @return Symfony\Component\DomCrawler\Crawler
+ */
+ public function assert_find_one_checkbox($crawler, $name, $message = '')
+ {
+ $query = sprintf('//input[@type="checkbox" and @name="%s"]', $name);
+ $result = $crawler->filterXPath($query);
+
+ $this->assertEquals(
+ 1,
+ sizeof($result),
+ $message ?: 'Failed asserting that exactly one checkbox with name' .
+ " $name exists in crawler scope."
+ );
+
+ return $result;
+ }
+
/**
* Creates a topic
*
@@ -613,9 +990,10 @@ class phpbb_functional_test_case extends phpbb_test_case
* @param string $subject
* @param string $message
* @param array $additional_form_data Any additional form data to be sent in the request
- * @return array post_id, topic_id
+ * @param string $expected Lang var of expected message after posting
+ * @return array|null post_id, topic_id if message is empty
*/
- public function create_topic($forum_id, $subject, $message, $additional_form_data = array())
+ public function create_topic($forum_id, $subject, $message, $additional_form_data = array(), $expected = '')
{
$posting_url = "posting.php?mode=post&f={$forum_id}&sid={$this->sid}";
@@ -625,7 +1003,7 @@ class phpbb_functional_test_case extends phpbb_test_case
'post' => true,
), $additional_form_data);
- return self::submit_post($posting_url, 'POST_TOPIC', $form_data);
+ return self::submit_post($posting_url, 'POST_TOPIC', $form_data, $expected);
}
/**
@@ -638,9 +1016,10 @@ class phpbb_functional_test_case extends phpbb_test_case
* @param string $subject
* @param string $message
* @param array $additional_form_data Any additional form data to be sent in the request
- * @return array post_id, topic_id
+ * @param string $expected Lang var of expected message after posting
+ * @return array|null post_id, topic_id if message is empty
*/
- public function create_post($forum_id, $topic_id, $subject, $message, $additional_form_data = array())
+ public function create_post($forum_id, $topic_id, $subject, $message, $additional_form_data = array(), $expected = '')
{
$posting_url = "posting.php?mode=reply&f={$forum_id}&t={$topic_id}&sid={$this->sid}";
@@ -650,7 +1029,7 @@ class phpbb_functional_test_case extends phpbb_test_case
'post' => true,
), $additional_form_data);
- return self::submit_post($posting_url, 'POST_REPLY', $form_data);
+ return self::submit_post($posting_url, 'POST_REPLY', $form_data, $expected);
}
/**
@@ -659,16 +1038,29 @@ class phpbb_functional_test_case extends phpbb_test_case
* @param string $posting_url
* @param string $posting_contains
* @param array $form_data
- * @return array post_id, topic_id
+ * @param string $expected Lang var of expected message after posting
+ * @return array|null post_id, topic_id if message is empty
*/
- protected function submit_post($posting_url, $posting_contains, $form_data)
+ protected function submit_post($posting_url, $posting_contains, $form_data, $expected = '')
{
$this->add_lang('posting');
$crawler = $this->submit_message($posting_url, $posting_contains, $form_data);
- $this->assertContains($this->lang('POST_STORED'), $crawler->filter('html')->text());
- $url = $crawler->selectLink($this->lang('VIEW_MESSAGE', '', ''))->link()->getUri();
+ if ($expected !== '')
+ {
+ if (isset($this->lang[$expected]))
+ {
+ $this->assertContainsLang($expected, $crawler->filter('html')->text());
+ }
+ else
+ {
+ $this->assertContains($expected, $crawler->filter('html')->text());
+ }
+ return null;
+ }
+
+ $url = $crawler->selectLink($form_data['subject'])->link()->getUri();
return array(
'topic_id' => $this->get_parameter_from_link($url, 't'),
@@ -722,10 +1114,33 @@ class phpbb_functional_test_case extends phpbb_test_case
*/
protected function submit_message($posting_url, $posting_contains, $form_data)
{
+ if (time() == self::$last_post_timestamp)
+ {
+ // Travis is too fast, so we have to wait to not mix up the post/topic order
+ sleep(1);
+ }
+ self::$last_post_timestamp = time();
$crawler = self::request('GET', $posting_url);
$this->assertContains($this->lang($posting_contains), $crawler->filter('html')->text());
+ if (!empty($form_data['upload_files']))
+ {
+ for ($i = 0; $i < $form_data['upload_files']; $i++)
+ {
+ $file = array(
+ 'tmp_name' => __DIR__ . '/../functional/fixtures/files/valid.jpg',
+ 'name' => 'valid.jpg',
+ 'type' => 'image/jpeg',
+ 'size' => filesize(__DIR__ . '/../functional/fixtures/files/valid.jpg'),
+ 'error' => UPLOAD_ERR_OK,
+ );
+
+ $crawler = self::$client->request('POST', $posting_url, array('add_file' => $this->lang('ADD_FILE')), array('fileupload' => $file));
+ }
+ unset($form_data['upload_files']);
+ }
+
$hidden_fields = array(
$crawler->filter('[type="hidden"]')->each(function ($node, $i) {
return array('name' => $node->attr('name'), 'value' => $node->attr('value'));
@@ -751,6 +1166,48 @@ class phpbb_functional_test_case extends phpbb_test_case
}
/**
+ * Deletes a topic
+ *
+ * Be sure to login before creating
+ *
+ * @param int $topic_id
+ * @return null
+ */
+ public function delete_topic($topic_id)
+ {
+ $this->add_lang('posting');
+ $crawler = $this->get_quickmod_page($topic_id, 'DELETE_TOPIC');
+ $this->assertContainsLang('DELETE_PERMANENTLY', $crawler->text());
+
+ $this->add_lang('mcp');
+ $form = $crawler->selectButton('Yes')->form();
+ $form['delete_permanent'] = 1;
+ $crawler = self::submit($form);
+ $this->assertContainsLang('TOPIC_DELETED_SUCCESS', $crawler->text());
+ }
+
+ /**
+ * Deletes a post
+ *
+ * Be sure to login before creating
+ *
+ * @param int $forum_id
+ * @param int $topic_id
+ * @return null
+ */
+ public function delete_post($forum_id, $post_id)
+ {
+ $this->add_lang('posting');
+ $crawler = self::request('GET', "posting.php?mode=delete&f={$forum_id}&p={$post_id}&sid={$this->sid}");
+ $this->assertContainsLang('DELETE_PERMANENTLY', $crawler->text());
+
+ $form = $crawler->selectButton('Yes')->form();
+ $form['delete_permanent'] = 1;
+ $crawler = self::submit($form);
+ $this->assertContainsLang('POST_DELETED', $crawler->text());
+ }
+
+ /**
* Returns the requested parameter from a URL
*
* @param string $url
@@ -785,4 +1242,50 @@ class phpbb_functional_test_case extends phpbb_test_case
}
return null;
}
+
+ /**
+ * Return a passwords manager instance
+ *
+ * @return phpbb\passwords\manager
+ */
+ public function get_passwords_manager()
+ {
+ // Prepare dependencies for manager and driver
+ $config = new \phpbb\config\config(array());
+ $driver_helper = new \phpbb\passwords\driver\helper($config);
+
+ $passwords_drivers = array(
+ 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper),
+ 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper),
+ 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $driver_helper),
+ 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper),
+ );
+
+ $passwords_helper = new \phpbb\passwords\helper;
+ // Set up passwords manager
+ $manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers));
+
+ return $manager;
+ }
+
+ /**
+ * Get quickmod page
+ *
+ * @param int $topic_id
+ * @param string $action Language key for the quickmod action
+ * @param Symfony\Component\DomCrawler\Crawler Optional crawler object to use instead of creating new one.
+ * @return Symfony\Component\DomCrawler\Crawler
+ */
+ public function get_quickmod_page($topic_id, $action, $crawler = false)
+ {
+ $this->add_lang('viewtopic');
+
+ if ($crawler === false)
+ {
+ $crawler = self::request('GET', "viewtopic.php?t={$topic_id}&sid={$this->sid}");
+ }
+ $link = $crawler->filter('#quickmod')->selectLink($this->lang($action))->link()->getUri();
+
+ return self::request('GET', substr($link, strpos($link, 'mcp.')));
+ }
}