2012-04-21 04:37:57 -05:00
< ? php
/**
*
* @ package testing
* @ copyright ( c ) 2011 phpBB Group
* @ license http :// opensource . org / licenses / gpl - 2.0 . php GNU General Public License v2
*
*/
2012-04-23 17:16:16 -04:00
use Symfony\Component\BrowserKit\CookieJar ;
2012-04-21 04:37:57 -05:00
require_once __DIR__ . '/../../phpBB/includes/functions_install.php' ;
2012-11-11 10:44:47 +00:00
require_once __DIR__ . '/../../phpBB/includes/acm/acm_file.php' ;
require_once __DIR__ . '/../../phpBB/includes/cache.php' ;
2012-04-21 04:37:57 -05:00
class phpbb_functional_test_case extends phpbb_test_case
{
2013-05-27 22:09:44 +02:00
static protected $client ;
2013-05-27 22:25:25 +02:00
static protected $cookieJar ;
2013-05-27 22:09:44 +02:00
static protected $root_url ;
2013-05-26 21:12:32 +02:00
2012-11-11 10:44:47 +00:00
protected $cache = null ;
2012-12-06 22:45:12 -05:00
protected $db = null ;
2012-05-22 10:46:36 -04:00
2012-04-23 17:16:16 -04:00
/**
2012-05-22 12:06:27 -03:00
* Session ID for current test ' s session ( each test makes its own )
* @ var string
2012-04-23 17:16:16 -04:00
*/
protected $sid ;
2012-05-22 10:46:36 -04:00
2012-04-23 17:16:16 -04:00
/**
2012-05-22 12:06:27 -03:00
* Language array used by phpBB
* @ var array
2012-04-23 17:16:16 -04:00
*/
2012-05-22 10:46:36 -04:00
protected $lang = array ();
2012-04-21 04:37:57 -05:00
static protected $config = array ();
static protected $already_installed = false ;
2012-12-04 17:19:25 -05:00
static public function setUpBeforeClass ()
2012-04-21 04:37:57 -05:00
{
2012-12-04 17:19:25 -05:00
parent :: setUpBeforeClass ();
self :: $config = phpbb_test_case_helpers :: get_test_config ();
2013-05-27 22:09:44 +02:00
self :: $root_url = self :: $config [ 'phpbb_functional_url' ];
2012-12-04 17:19:25 -05:00
2012-04-21 04:37:57 -05:00
if ( ! isset ( self :: $config [ 'phpbb_functional_url' ]))
{
2012-12-04 17:19:25 -05:00
self :: markTestSkipped ( 'phpbb_functional_url was not set in test_config and wasn\'t set as PHPBB_FUNCTIONAL_URL environment variable either.' );
2012-04-21 04:37:57 -05:00
}
2012-12-10 06:42:43 -05:00
if ( ! self :: $already_installed )
{
self :: install_board ();
self :: $already_installed = true ;
}
2012-12-04 17:19:25 -05:00
}
public function setUp ()
{
parent :: setUp ();
2012-12-04 17:37:46 -05:00
$this -> bootstrap ();
2012-04-21 04:37:57 -05:00
2013-05-27 22:25:25 +02:00
self :: $cookieJar = new CookieJar ;
self :: $client = new Goutte\Client ( array (), null , self :: $cookieJar );
2012-07-16 17:45:43 +01:00
// Reset the curl handle because it is 0 at this point and not a valid
// resource
2013-05-27 22:09:44 +02:00
self :: $client -> getClient () -> getCurlMulti () -> reset ( true );
2012-04-23 17:16:16 -04:00
// Clear the language array so that things
// that were added in other tests are gone
$this -> lang = array ();
$this -> add_lang ( 'common' );
2012-11-11 10:44:47 +00:00
$this -> purge_cache ();
2012-04-21 04:37:57 -05:00
}
2013-05-27 22:09:44 +02:00
/**
* Perform a request to page
*
* @ param string $method HTTP Method
* @ param string $path Page path , relative from phpBB root path
* @ param array $form_data An array of form field values
* @ param bool $skip_assert_response_success Should we skip the basic response assertions ?
* @ return Symfony\Component\DomCrawler\Crawler
*/
static public function request ( $method , $path , $form_data = array (), $skip_assert_response_success = false )
2012-04-21 04:37:57 -05:00
{
2013-05-27 22:09:44 +02:00
$crawler = self :: $client -> request ( $method , self :: $root_url . $path , $form_data );
if ( ! $skip_assert_response_success )
{
self :: assert_response_success ();
}
return $crawler ;
2012-04-21 04:37:57 -05:00
}
2013-05-27 22:09:44 +02:00
/**
* Submits a form
*
* @ param Symfony\Component\DomCrawler\Form $form A Form instance
* @ param array $values An array of form field values
* @ param bool $skip_assert_response_success Should we skip the basic response assertions ?
* @ return Symfony\Component\DomCrawler\Crawler
*/
static public function submit ( Symfony\Component\DomCrawler\Form $form , array $values = array (), $skip_assert_response_success = false )
2013-05-26 21:12:32 +02:00
{
2013-05-27 22:09:44 +02:00
$crawler = self :: $client -> submit ( $form , $values );
if ( ! $skip_assert_response_success )
{
self :: assert_response_success ();
}
return $crawler ;
2013-05-26 21:12:32 +02:00
}
2012-04-21 04:37:57 -05:00
// bootstrap, called after board is set up
// once per test case class
// test cases can override this
protected function bootstrap ()
{
}
2012-12-06 22:45:12 -05:00
protected function get_db ()
{
global $phpbb_root_path , $phpEx ;
// so we don't reopen an open connection
if ( ! ( $this -> db instanceof dbal ))
{
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 ();
$this -> db -> sql_connect ( self :: $config [ 'dbhost' ], self :: $config [ 'dbuser' ], self :: $config [ 'dbpasswd' ], self :: $config [ 'dbname' ], self :: $config [ 'dbport' ]);
}
return $this -> db ;
}
2012-11-11 10:44:47 +00:00
protected function get_cache_driver ()
{
if ( ! $this -> cache )
{
$this -> cache = new cache ();
}
return $this -> cache ;
}
protected function purge_cache ()
{
$cache = $this -> get_cache_driver ();
$cache -> purge ();
$cache -> unload ();
$cache -> load ();
}
2012-04-21 04:37:57 -05:00
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' ),
);
}
2012-12-04 17:37:46 -05:00
static protected function install_board ()
2012-04-21 04:37:57 -05:00
{
global $phpbb_root_path , $phpEx ;
self :: $config [ 'table_prefix' ] = 'phpbb_' ;
2012-12-04 17:37:46 -05:00
self :: recreate_database ( self :: $config );
2012-04-21 04:37:57 -05:00
if ( file_exists ( $phpbb_root_path . " config. $phpEx " ))
{
if ( ! file_exists ( $phpbb_root_path . " config_dev. $phpEx " ))
{
rename ( $phpbb_root_path . " config. $phpEx " , $phpbb_root_path . " config_dev. $phpEx " );
}
else
{
unlink ( $phpbb_root_path . " config. $phpEx " );
}
}
2013-05-27 22:25:25 +02:00
self :: $cookieJar = new CookieJar ;
self :: $client = new Goutte\Client ( array (), null , self :: $cookieJar );
2013-05-26 21:16:49 +02:00
// Set client manually so we can increase the cURL timeout
2013-05-27 22:09:44 +02:00
self :: $client -> setClient ( new Guzzle\Http\Client ( '' , array (
2013-05-26 21:16:49 +02:00
Guzzle\Http\Client :: DISABLE_REDIRECTS => true ,
'curl.options' => array (
CURLOPT_TIMEOUT => 120
),
)));
2012-04-21 04:37:57 -05:00
2013-05-26 21:12:32 +02:00
// Reset the curl handle because it is 0 at this point and not a valid
// resource
2013-05-27 22:09:44 +02:00
self :: $client -> getClient () -> getCurlMulti () -> reset ( true );
2012-04-21 04:37:57 -05:00
2013-05-26 21:12:32 +02:00
$parseURL = parse_url ( self :: $config [ 'phpbb_functional_url' ]);
2013-05-27 22:09:44 +02:00
$crawler = self :: request ( 'GET' , 'install/index.php?mode=install' );
2013-05-26 21:12:32 +02:00
self :: assertContains ( 'Welcome to Installation' , $crawler -> filter ( '#main' ) -> text ());
$form = $crawler -> selectButton ( 'submit' ) -> form ();
2013-05-27 22:09:44 +02:00
$crawler = self :: submit ( $form );
2013-05-26 21:12:32 +02:00
self :: assertContains ( 'Installation compatibility' , $crawler -> filter ( '#main' ) -> text ());
$form = $crawler -> selectButton ( 'submit' ) -> form ();
2013-05-27 22:09:44 +02:00
$crawler = self :: submit ( $form );
2013-05-26 21:12:32 +02:00
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' ]),
'dbhost' => self :: $config [ 'dbhost' ],
'dbport' => self :: $config [ 'dbport' ],
'dbname' => self :: $config [ 'dbname' ],
'dbuser' => self :: $config [ 'dbuser' ],
'dbpasswd' => self :: $config [ 'dbpasswd' ],
'table_prefix' => self :: $config [ 'table_prefix' ],
));
2013-05-27 22:09:44 +02:00
$crawler = self :: submit ( $form );
2013-05-26 21:12:32 +02:00
self :: assertContains ( 'Successful connection' , $crawler -> filter ( '#main' ) -> text ());
$form = $crawler -> selectButton ( 'submit' ) -> form ();
2013-05-27 22:09:44 +02:00
$crawler = self :: submit ( $form );
2013-05-26 21:12:32 +02:00
self :: assertContains ( 'Administrator configuration' , $crawler -> filter ( '#main' ) -> text ());
$form = $crawler -> selectButton ( 'submit' ) -> form ( array (
2012-04-21 04:37:57 -05:00
'default_lang' => 'en' ,
'admin_name' => 'admin' ,
2013-05-26 21:12:32 +02:00
'admin_pass1' => 'adminadmin' ,
'admin_pass2' => 'adminadmin' ,
'board_email1' => 'nobody@example.com' ,
'board_email2' => 'nobody@example.com' ,
2012-04-21 04:37:57 -05:00
));
2013-05-27 22:09:44 +02:00
$crawler = self :: submit ( $form );
2013-05-26 21:12:32 +02:00
self :: assertContains ( 'Tests passed' , $crawler -> filter ( '#main' ) -> text ());
$form = $crawler -> selectButton ( 'submit' ) -> form ();
2013-05-27 22:09:44 +02:00
$crawler = self :: submit ( $form );
2013-05-26 21:12:32 +02:00
self :: assertContains ( 'The configuration file has been written.' , $crawler -> filter ( '#main' ) -> text ());
file_put_contents ( $phpbb_root_path . " config. $phpEx " , phpbb_create_config_file_data ( self :: $config , self :: $config [ 'dbms' ], array (), true , true ));
$form = $crawler -> selectButton ( 'submit' ) -> form ();
2013-05-27 22:09:44 +02:00
$crawler = self :: submit ( $form );
2013-05-26 21:12:32 +02:00
self :: assertContains ( 'The settings on this page are only necessary to set if you know that you require something different from the default.' , $crawler -> filter ( '#main' ) -> text ());
$form = $crawler -> selectButton ( 'submit' ) -> form ( array (
'email_enable' => true ,
'smtp_delivery' => true ,
'smtp_host' => 'nxdomain.phpbb.com' ,
'smtp_auth' => 'PLAIN' ,
'smtp_user' => 'nxuser' ,
'smtp_pass' => 'nxpass' ,
2012-04-21 04:37:57 -05:00
'cookie_secure' => false ,
'force_server_vars' => false ,
'server_protocol' => $parseURL [ 'scheme' ] . '://' ,
'server_name' => 'localhost' ,
'server_port' => isset ( $parseURL [ 'port' ]) ? ( int ) $parseURL [ 'port' ] : 80 ,
'script_path' => $parseURL [ 'path' ],
));
2013-05-26 21:12:32 +02:00
2013-05-27 22:09:44 +02:00
$crawler = self :: submit ( $form );
2013-05-26 21:12:32 +02:00
self :: assertContains ( 'The database tables used by phpBB' , $crawler -> filter ( '#main' ) -> text ());
self :: assertContains ( 'have been created and populated with some initial data.' , $crawler -> filter ( '#main' ) -> text ());
$form = $crawler -> selectButton ( 'submit' ) -> form ();
2013-05-27 22:09:44 +02:00
$crawler = self :: submit ( $form );
2013-05-26 21:12:32 +02:00
self :: assertContains ( 'You have successfully installed' , $crawler -> text ());
2012-07-30 12:54:00 +01:00
copy ( $phpbb_root_path . " config. $phpEx " , $phpbb_root_path . " config_test. $phpEx " );
2012-04-21 04:37:57 -05:00
}
2012-12-04 17:37:46 -05:00
static private function do_request ( $sub , $post_data = null )
2012-04-21 04:37:57 -05:00
{
$context = null ;
if ( $post_data )
{
$context = stream_context_create ( array (
'http' => array (
'method' => 'POST' ,
'header' => 'Content-Type: application/x-www-form-urlencoded' ,
'content' => http_build_query ( $post_data ),
'ignore_errors' => true ,
),
));
}
return file_get_contents ( self :: $config [ 'phpbb_functional_url' ] . 'install/index.php?mode=install&sub=' . $sub , false , $context );
}
2012-12-12 21:47:48 -05:00
static private function recreate_database ( $config )
2012-04-21 04:37:57 -05:00
{
$db_conn_mgr = new phpbb_database_test_connection_manager ( $config );
$db_conn_mgr -> recreate_db ();
}
2012-04-23 17:16:16 -04:00
2012-07-08 20:22:19 +01:00
/**
* Creates a new user with limited permissions
*
* @ param string $username Also doubles up as the user ' s password
2012-12-06 23:43:22 -05:00
* @ return int ID of created user
2012-07-08 20:22:19 +01:00
*/
protected function create_user ( $username )
{
// Required by unique_id
global $config ;
if ( ! is_array ( $config ))
{
$config = array ();
}
$config [ 'rand_seed' ] = '' ;
$config [ 'rand_seed_last_update' ] = time () + 600 ;
2012-12-06 23:43:22 -05:00
// Required by user_add
global $db , $cache ;
2012-07-08 20:22:19 +01:00
$db = $this -> get_db ();
2012-12-06 23:43:22 -05:00
if ( ! function_exists ( 'phpbb_mock_null_cache' ))
{
require_once ( __DIR__ . '/../mock/null_cache.php' );
}
$cache = new phpbb_mock_null_cache ;
2012-07-08 20:22:19 +01:00
2012-12-06 23:43:22 -05:00
if ( ! function_exists ( 'utf_clean_string' ))
{
require_once ( __DIR__ . '/../../phpBB/includes/utf/utf_tools.php' );
}
if ( ! function_exists ( 'user_add' ))
{
require_once ( __DIR__ . '/../../phpBB/includes/functions_user.php' );
}
$user_row = array (
'username' => $username ,
'group_id' => 2 ,
'user_email' => 'nobody@example.com' ,
'user_type' => 0 ,
'user_lang' => 'en' ,
'user_timezone' => 0 ,
'user_dateformat' => '' ,
2013-05-26 21:12:32 +02:00
'user_password' => phpbb_hash ( $username . $username ),
2012-12-06 23:43:22 -05:00
);
return user_add ( $user_row );
2012-07-08 20:22:19 +01:00
}
protected function login ( $username = 'admin' )
2012-04-23 17:16:16 -04:00
{
$this -> add_lang ( 'ucp' );
$crawler = $this -> request ( 'GET' , 'ucp.php' );
$this -> assertContains ( $this -> lang ( 'LOGIN_EXPLAIN_UCP' ), $crawler -> filter ( 'html' ) -> text ());
$form = $crawler -> selectButton ( $this -> lang ( 'LOGIN' )) -> form ();
2013-05-27 22:09:44 +02:00
$crawler = $this -> submit ( $form , array ( 'username' => $username , 'password' => $username . $username ));
2012-12-06 23:43:22 -05:00
$this -> assert_response_success ();
$this -> assertContains ( $this -> lang ( 'LOGIN_REDIRECT' ), $crawler -> filter ( 'html' ) -> text ());
2012-04-23 17:16:16 -04:00
2013-05-27 22:25:25 +02:00
$cookies = self :: $cookieJar -> all ();
2012-11-15 08:19:40 -05:00
2012-05-22 10:46:36 -04:00
// The session id is stored in a cookie that ends with _sid - we assume there is only one such cookie
2012-07-16 17:45:43 +01:00
foreach ( $cookies as $cookie );
2012-04-23 17:16:16 -04:00
{
2012-07-16 17:45:43 +01:00
if ( substr ( $cookie -> getName (), - 4 ) == '_sid' )
2012-04-23 17:16:16 -04:00
{
$this -> sid = $cookie -> getValue ();
}
}
}
2013-05-14 22:51:10 +02:00
/**
* Login to the ACP
* You must run login () before calling this .
*/
protected function admin_login ( $username = 'admin' )
{
$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 )
{
2013-05-27 22:09:44 +02:00
$crawler = $this -> submit ( $form , array ( 'username' => $username , $field => $username . $username ));
2013-05-14 22:51:10 +02:00
$this -> assert_response_success ();
$this -> assertContains ( $this -> lang ( 'LOGIN_ADMIN_SUCCESS' ), $crawler -> filter ( 'html' ) -> text ());
2013-05-27 22:25:25 +02:00
$cookies = self :: $cookieJar -> all ();
2013-05-14 22:51:10 +02:00
// 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 ;
}
}
}
2012-04-23 17:16:16 -04:00
protected function add_lang ( $lang_file )
{
if ( is_array ( $lang_file ))
{
foreach ( $lang_file as $file )
{
$this -> add_lang ( $file );
}
}
2012-05-22 10:52:49 -04:00
$lang_path = __DIR__ . " /../../phpBB/language/en/ $lang_file .php " ;
2012-04-23 17:16:16 -04:00
$lang = array ();
if ( file_exists ( $lang_path ))
{
include ( $lang_path );
}
$this -> lang = array_merge ( $this -> lang , $lang );
}
protected function lang ()
{
$args = func_get_args ();
$key = $args [ 0 ];
if ( empty ( $this -> lang [ $key ]))
{
2012-04-24 14:10:50 -04:00
throw new RuntimeException ( 'Language key "' . $key . '" could not be found.' );
2012-04-23 17:16:16 -04:00
}
$args [ 0 ] = $this -> lang [ $key ];
return call_user_func_array ( 'sprintf' , $args );
}
2012-11-15 08:19:40 -05:00
/**
* Heuristic function to check that the response is success .
*
* When php decides to die with a fatal error , it still sends 200 OK
* status code . This assertion tries to catch that .
*
2012-11-15 08:40:29 -05:00
* @ return null
2012-11-15 08:19:40 -05:00
*/
2013-05-27 22:09:44 +02:00
static public function assert_response_success ()
2013-05-26 21:12:32 +02:00
{
2013-05-27 22:09:44 +02:00
self :: assertEquals ( 200 , self :: $client -> getResponse () -> getStatus ());
$content = self :: $client -> getResponse () -> getContent ();
2013-05-26 23:57:50 +02:00
// Any output before the doc type means there was an error
2013-05-28 14:10:27 +02:00
self :: assertStringStartsWith ( '<!DOCTYPE' , trim ( $content ), 'Output found before DOCTYPE specification.' );
2013-05-26 21:12:32 +02:00
}
2012-04-21 04:37:57 -05:00
}