diff --git a/src/JoomlaBrowser.php b/src/JoomlaBrowser.php index 78bd996..93913a9 100644 --- a/src/JoomlaBrowser.php +++ b/src/JoomlaBrowser.php @@ -1,102 +1,120 @@ config['username']; - } - - if (is_null($password)) - { - $password = $this->config['password']; - } - - - $this->debug('I open Joomla Administrator Login Page'); - $I->amOnPage('/administrator/index.php'); + /** + * The module required fields, to be set in the suite .yml configuration file. + * + * @var array + */ + protected $requiredFields = array( + 'url', + 'browser', + 'username', + 'password', + 'database type', + 'database host', + 'database user', + 'database password', + 'database name', + 'database type', + 'database prefix', + 'admin email', + 'language' + ); + + /** + * Function to Do Admin Login In Joomla! + * + * @param string|null $user Optional Username. If not passed the one in acceptance.suite.yml will be used + * @param string|null $password Optional password. If not passed the one in acceptance.suite.yml will be used + * + * @return void + */ + public function doAdministratorLogin($user = null, $password = null) + { + $I = $this; + + if (is_null($user)) + { + $user = $this->config['username']; + } + + if (is_null($password)) + { + $password = $this->config['password']; + } + + $this->debug('I open Joomla Administrator Login Page'); + $I->amOnPage('/administrator/index.php'); $I->waitForElement(['id' => 'mod-login-username'], 60); $this->debug('Fill Username Text Field'); - $I->fillField(['id' => 'mod-login-username'], $user); - $this->debug('Fill Password Text Field'); - $I->fillField(['id' => 'mod-login-password'], $password); - // @todo: update login button in joomla login screen to make this xPath more friendly - $this->debug('I click Login button'); - $I->click(['xpath' => "//button[contains(normalize-space(), 'Log in')]"]); - $this->debug('I wait to see Administrator Control Panel'); - $I->waitForText('Control Panel', 4, ['css' => 'h1.page-title']); - } - - /** - * Function to Do Frontend Login In Joomla! - * - * @param string|null $user Optional username. If not passed the one in acceptance.suite.yml will be used - * @param string|null $password Optional password. If not passed the one in acceptance.suite.yml will be used - */ - public function doFrontEndLogin($user = null, $password = null) - { - $I = $this; - - if (is_null($user)) - { - $user = $this->config['username']; - } - - if (is_null($password)) - { - $password = $this->config['password']; - } - - $this->debug('I open Joomla Frontend Login Page'); - $I->amOnPage('/index.php?option=com_users&view=login'); - $this->debug('Fill Username Text Field'); - $I->fillField(['id' => 'username'], $user); - $this->debug('Fill Password Text Field'); - $I->fillField(['id' => 'password'], $password); - // @todo: update login button in joomla login screen to make this xPath more friendly - $this->debug('I click Login button'); - $I->click(['xpath' => "//div[@class='login']/form/fieldset/div[4]/div/button"]); - $this->debug('I wait to see Frontend Member Profile Form with the Logout button in the module'); - $I->waitForElement(['xpath' => "//form[@id='login-form']/div[@class='logout-button']"], 60); - } + $I->fillField(['id' => 'mod-login-username'], $user); + $this->debug('Fill Password Text Field'); + $I->fillField(['id' => 'mod-login-password'], $password); + + // @todo: update login button in joomla login screen to make this xPath more friendly + $this->debug('I click Login button'); + $I->click(['xpath' => "//button[contains(normalize-space(), 'Log in')]"]); + $this->debug('I wait to see Administrator Control Panel'); + $I->waitForText('Control Panel', 4, ['css' => 'h1.page-title']); + } + + /** + * Function to Do Frontend Login In Joomla! + * + * @param string|null $user Optional username. If not passed the one in acceptance.suite.yml will be used + * @param string|null $password Optional password. If not passed the one in acceptance.suite.yml will be used + * + * @return void + */ + public function doFrontEndLogin($user = null, $password = null) + { + $I = $this; + + if (is_null($user)) + { + $user = $this->config['username']; + } + + if (is_null($password)) + { + $password = $this->config['password']; + } + + $this->debug('I open Joomla Frontend Login Page'); + $I->amOnPage('/index.php?option=com_users&view=login'); + $this->debug('Fill Username Text Field'); + $I->fillField(['id' => 'username'], $user); + $this->debug('Fill Password Text Field'); + $I->fillField(['id' => 'password'], $password); + + // @todo: update login button in joomla login screen to make this xPath more friendly + $this->debug('I click Login button'); + $I->click(['xpath' => "//div[@class='login']/form/fieldset/div[4]/div/button"]); + $this->debug('I wait to see Frontend Member Profile Form with the Logout button in the module'); + $I->waitForElement(['xpath' => "//form[@id='login-form']/div[@class='logout-button']"], 60); + } /** * Function to Do frontend Logout in Joomla! + * + * @return void */ public function doFrontendLogout() { @@ -110,191 +128,192 @@ public function doFrontendLogout() $I->seeElement(['xpath' => "//div[@class='login']//button[contains(text(), 'Log in')]"]); } - /** - * Installs Joomla - */ - public function installJoomla() - { - $I = $this; - - // Install Joomla CMS'); - - // @todo: activate the filesystem module - //$I->expect('no configuration.php is in the Joomla CMS folder'); - //$I->dontSeeFileFound('configuration.php', $this->config['Joomla folder')]; - $this->debug('I open Joomla Installation Configuration Page'); - $I->amOnPage('/installation/index.php'); - $this->debug('I check that FTP tab is not present in installation. Otherwise it means that I have not enough permissions to install joomla and execution will be stoped'); - $I->dontSeeElement(['id' => 'ftp']); - // I Wait for the text Main Configuration, meaning that the page is loaded - $this->debug('I wait for Main Configuration'); - $I->waitForElement('#jform_language', 10); + /** + * Installs Joomla + * + * @return void + */ + public function installJoomla() + { + $I = $this; + + // Install Joomla CMS'); + + // @todo: activate the filesystem module + + $this->debug('I open Joomla Installation Configuration Page'); + $I->amOnPage('/installation/index.php'); + $this->debug('I check that FTP tab is not present in installation. Otherwise it means that I have not enough permissions to install joomla and execution will be stoped'); + $I->dontSeeElement(['id' => 'ftp']); + + // I Wait for the text Main Configuration, meaning that the page is loaded + $this->debug('I wait for Main Configuration'); + $I->waitForElement('#jform_language', 10); $I->debug('Wait for chosen to render the Languages list field'); $I->wait(2); - $I->debug('I select dk-DK as installation language'); - // Select a random language to force reloading of the lang strings after selecting English - $I->selectOptionInChosen('#jform_language', 'Danish (DK)'); - $I->waitForText('Generel konfiguration', 60, 'h3'); - // Wait for chosen to render the field - $I->debug('I select en-GB as installation language'); + $I->debug('I select dk-DK as installation language'); + + // Select a random language to force reloading of the lang strings after selecting English + $I->selectOptionInChosen('#jform_language', 'Danish (DK)'); + $I->waitForText('Generel konfiguration', 60, 'h3'); + + // Wait for chosen to render the field + $I->debug('I select en-GB as installation language'); $I->debug('Wait for chosen to render the Languages list field'); $I->wait(2); - $I->selectOptionInChosen('#jform_language', 'English (United Kingdom)'); - $I->waitForText('Main Configuration', 60, 'h3'); - $this->debug('I fill Site Name'); - $I->fillField(['id' => 'jform_site_name'], 'Joomla CMS test'); - $this->debug('I fill Site Description'); - $I->fillField(['id' => 'jform_site_metadesc'], 'Site for testing Joomla CMS'); - - // I get the configuration from acceptance.suite.yml (see: tests/_support/acceptancehelper.php) - $this->debug('I fill Admin Email'); - $I->fillField(['id' => 'jform_admin_email'], $this->config['admin email']); - $this->debug('I fill Admin Username'); - $I->fillField(['id' => 'jform_admin_user'], $this->config['username']); - $this->debug('I fill Admin Password'); - $I->fillField(['id' => 'jform_admin_password'], $this->config['password']); - $this->debug('I fill Admin Password Confirmation'); - $I->fillField(['id' => 'jform_admin_password2'], $this->config['password']); - $this->debug('I click Site Offline: no'); - $I->click(['xpath' => "//fieldset[@id='jform_site_offline']/label[@for='jform_site_offline1']"]); // ['No Site Offline'] - $this->debug('I click Next'); - $I->click(['link' => 'Next']); - - $this->debug('I Fill the form for creating the Joomla site Database'); - $I->waitForText('Database Configuration',60,['css' => 'h3']); - - $this->debug('I select MySQLi'); - $I->selectOption(['id' => 'jform_db_type'], $this->config['database type']); - $this->debug('I fill Database Host'); - $I->fillField(['id' => 'jform_db_host'], $this->config['database host']); - $this->debug('I fill Database User'); - $I->fillField(['id' => 'jform_db_user'], $this->config['database user']); - $this->debug('I fill Database Password'); - $I->fillField(['id' => 'jform_db_pass'], $this->config['database password']); - $this->debug('I fill Database Name'); - $I->fillField(['id' => 'jform_db_name'], $this->config['database name']); - $this->debug('I fill Database Prefix'); - $I->fillField(['id' => 'jform_db_prefix'], $this->config['database prefix']); - $this->debug('I click Remove Old Database '); - $I->selectOptionInRadioField('Old Database Process', 'Remove'); - $this->debug('I click Next'); - $I->click(['link' => 'Next']); - $this->debug('I wait Joomla to remove the old database if exist'); - $I->waitForElementVisible(['id' => 'jform_sample_file-lbl'],30); - - $this->debug('I install joomla with or without sample data'); - $I->waitForText('Finalisation',60, ['xpath' => '//h3']); - // @todo: installation of sample data needs to be created - //if ($this->config['install sample data']) : - // $this->debug('I install Sample Data:' . $this->config['sample data']); - // $I->selectOption('#jform_sample_file', $this->config['sample data']); - //else : - // $this->debug('I install Joomla without Sample Data'); - // $I->selectOption('#jform_sample_file', '#jform_sample_file0'); // No sample data - //endif; - $I->selectOption(['id' => 'jform_sample_file'], ['id' => 'jform_sample_file0']); // No sample data - $I->click(['link' => 'Install']); - - // Wait while Joomla gets installed - $this->debug('I wait for Joomla being installed'); - $I->waitForText('Congratulations! Joomla! is now installed.', 60, ['xpath' => '//h3']); - } - - /** - * Install Joomla removing the Installation folder at the end of the execution - */ - public function installJoomlaRemovingInstallationFolder() - { - $I = $this; - - $I->installJoomla(); - - $this->debug('Removing Installation Folder'); - $I->click(['xpath' => "//input[@value='Remove installation folder']"]); - - $I->debug('I wait for Removing Installation Folder button to become disabled'); - $I->waitForJS("return jQuery('form#adminForm input[name=instDefault]').attr('disabled') == 'disabled';", 60); - - $I->debug('Joomla is now installed'); - $I->see('Congratulations! Joomla! is now installed.',['xpath' => '//h3']); - } - - /** - * Installs Joomla with Multilingual Feature active - * - * @param array $languages Array containing the language names to be installed - * - * @example: $I->installJoomlaMultilingualSite(['Spanish', 'French']); - */ - public function installJoomlaMultilingualSite($languages = array()) - { - if (!$languages) - { - // If no language is passed French will be installed by default - $languages[] = 'French'; - } - - $I = $this; - - $I->installJoomla(); - - $this->debug('I go to Install Languages page'); - $I->click(['id' => 'instLangs']); - $I->waitForText('Install Language packages', 60, ['xpath' => '//h3']); - - foreach ($languages as $language) : - $I->debug('I mark the checkbox of the language: ' . $language); - $I->click(['xpath' => "//label[contains(text()[normalize-space()], '$language')]/input"]); - endforeach; - - $I->click(['link' => 'Next']); - $I->waitForText('Multilingual', 60, ['xpath' => '//h3']); - $I->selectOptionInRadioField('Activate the multilingual feature', 'Yes'); - $I->waitForElementVisible(['id' => 'jform_activatePluginLanguageCode-lbl']); - $I->selectOptionInRadioField('Install localised content', 'Yes'); - $I->selectOptionInRadioField('Enable the language code plugin', 'Yes'); - $I->click(['link' => 'Next']); - - $I->waitForText('Congratulations! Joomla! is now installed.', 60, ['xpath' => '//h3']); - $this->debug('Removing Installation Folder'); - $I->click(['xpath' => "//input[@value='Remove installation folder']"]); - // @todo https://github.com/joomla-projects/joomla-browser/issues/45 - $I->wait(2); - /* - $I->waitForElementChange( - ['xpath' => "//input[@name='instDefault']"], - function(WebDriverElement $el) { - return !$el->isEnabled(); - }, - 60 - ); - */ - $this->debug('Joomla is now installed'); - $I->see('Congratulations! Joomla! is now installed.',['xpath' => '//h3']); - } - - /** - * Sets in Adminitrator->Global Configuration the Error reporting to Development - * - * @note: doAdminLogin() before - */ - public function setErrorReportingToDevelopment() - { - $I = $this; - $this->debug('I open Joomla Global Configuration Page'); - $I->amOnPage('/administrator/index.php?option=com_config'); - $this->debug('I wait for Global Configuration title'); - $I->waitForText('Global Configuration',60,['css' => '.page-title']); - $this->debug('I open the Server Tab'); - $I->click(['link' => 'Server']); - $this->debug('I wait for error reporting dropdown'); - $I->selectOptionInChosen('Error Reporting', 'Development'); - $this->debug('I click on save'); - $I->click(['xpath' => "//button[@onclick=\"Joomla.submitbutton('config.save.application.apply')\"]"]); - $this->debug('I wait for global configuration being saved'); - $I->waitForText('Global Configuration',60,['css' => '.page-title']); - $I->see('Configuration successfully saved.',['id' => 'system-message-container']); - } + $I->selectOptionInChosen('#jform_language', 'English (United Kingdom)'); + $I->waitForText('Main Configuration', 60, 'h3'); + $this->debug('I fill Site Name'); + $I->fillField(['id' => 'jform_site_name'], 'Joomla CMS test'); + $this->debug('I fill Site Description'); + $I->fillField(['id' => 'jform_site_metadesc'], 'Site for testing Joomla CMS'); + + // I get the configuration from acceptance.suite.yml (see: tests/_support/acceptancehelper.php) + $this->debug('I fill Admin Email'); + $I->fillField(['id' => 'jform_admin_email'], $this->config['admin email']); + $this->debug('I fill Admin Username'); + $I->fillField(['id' => 'jform_admin_user'], $this->config['username']); + $this->debug('I fill Admin Password'); + $I->fillField(['id' => 'jform_admin_password'], $this->config['password']); + $this->debug('I fill Admin Password Confirmation'); + $I->fillField(['id' => 'jform_admin_password2'], $this->config['password']); + $this->debug('I click Site Offline: no'); + + // ['No Site Offline'] + $I->click(['xpath' => "//fieldset[@id='jform_site_offline']/label[@for='jform_site_offline1']"]); + $this->debug('I click Next'); + $I->click(['link' => 'Next']); + + $this->debug('I Fill the form for creating the Joomla site Database'); + $I->waitForText('Database Configuration', 60, ['css' => 'h3']); + + $this->debug('I select MySQLi'); + $I->selectOption(['id' => 'jform_db_type'], $this->config['database type']); + $this->debug('I fill Database Host'); + $I->fillField(['id' => 'jform_db_host'], $this->config['database host']); + $this->debug('I fill Database User'); + $I->fillField(['id' => 'jform_db_user'], $this->config['database user']); + $this->debug('I fill Database Password'); + $I->fillField(['id' => 'jform_db_pass'], $this->config['database password']); + $this->debug('I fill Database Name'); + $I->fillField(['id' => 'jform_db_name'], $this->config['database name']); + $this->debug('I fill Database Prefix'); + $I->fillField(['id' => 'jform_db_prefix'], $this->config['database prefix']); + $this->debug('I click Remove Old Database '); + $I->selectOptionInRadioField('Old Database Process', 'Remove'); + $this->debug('I click Next'); + $I->click(['link' => 'Next']); + $this->debug('I wait Joomla to remove the old database if exist'); + $I->waitForElementVisible(['id' => 'jform_sample_file-lbl'], 30); + + $this->debug('I install joomla with or without sample data'); + $I->waitForText('Finalisation', 60, ['xpath' => '//h3']); + + // @todo: installation of sample data needs to be created + + // No sample data + $I->selectOption(['id' => 'jform_sample_file'], ['id' => 'jform_sample_file0']); + $I->click(['link' => 'Install']); + + // Wait while Joomla gets installed + $this->debug('I wait for Joomla being installed'); + $I->waitForText('Congratulations! Joomla! is now installed.', 60, ['xpath' => '//h3']); + } + + /** + * Install Joomla removing the Installation folder at the end of the execution + * + * @return void + */ + public function installJoomlaRemovingInstallationFolder() + { + $I = $this; + + $I->installJoomla(); + + $this->debug('Removing Installation Folder'); + $I->click(['xpath' => "//input[@value='Remove installation folder']"]); + + $I->debug('I wait for Removing Installation Folder button to become disabled'); + $I->waitForJS("return jQuery('form#adminForm input[name=instDefault]').attr('disabled') == 'disabled';", 60); + + $I->debug('Joomla is now installed'); + $I->see('Congratulations! Joomla! is now installed.', ['xpath' => '//h3']); + } + + /** + * Installs Joomla with Multilingual Feature active + * + * @param array $languages Array containing the language names to be installed + * + * @example: $I->installJoomlaMultilingualSite(['Spanish', 'French']); + * + * @return void + */ + public function installJoomlaMultilingualSite($languages = array()) + { + if (!$languages) + { + // If no language is passed French will be installed by default + $languages[] = 'French'; + } + + $I = $this; + + $I->installJoomla(); + + $this->debug('I go to Install Languages page'); + $I->click(['id' => 'instLangs']); + $I->waitForText('Install Language packages', 60, ['xpath' => '//h3']); + + foreach ($languages as $language) + { + $I->debug('I mark the checkbox of the language: ' . $language); + $I->click(['xpath' => "//label[contains(text()[normalize-space()], '$language')]/input"]); + } + + $I->click(['link' => 'Next']); + $I->waitForText('Multilingual', 60, ['xpath' => '//h3']); + $I->selectOptionInRadioField('Activate the multilingual feature', 'Yes'); + $I->waitForElementVisible(['id' => 'jform_activatePluginLanguageCode-lbl']); + $I->selectOptionInRadioField('Install localised content', 'Yes'); + $I->selectOptionInRadioField('Enable the language code plugin', 'Yes'); + $I->click(['link' => 'Next']); + + $I->waitForText('Congratulations! Joomla! is now installed.', 60, ['xpath' => '//h3']); + $this->debug('Removing Installation Folder'); + $I->click(['xpath' => "//input[@value='Remove installation folder']"]); + + // @todo https://github.com/joomla-projects/joomla-browser/issues/45 + $I->wait(2); + + $this->debug('Joomla is now installed'); + $I->see('Congratulations! Joomla! is now installed.', ['xpath' => '//h3']); + } + + /** + * Sets in Adminitrator->Global Configuration the Error reporting to Development + * {@internal doAdminLogin() before} + * + * @return void + */ + public function setErrorReportingToDevelopment() + { + $I = $this; + $this->debug('I open Joomla Global Configuration Page'); + $I->amOnPage('/administrator/index.php?option=com_config'); + $this->debug('I wait for Global Configuration title'); + $I->waitForText('Global Configuration', 60, ['css' => '.page-title']); + $this->debug('I open the Server Tab'); + $I->click(['link' => 'Server']); + $this->debug('I wait for error reporting dropdown'); + $I->selectOptionInChosen('Error Reporting', 'Development'); + $this->debug('I click on save'); + $this->clickToolbarButton('save'); + $this->debug('I wait for global configuration being saved'); + $I->waitForText('Global Configuration', 60, ['css' => '.page-title']); + $I->see('Configuration successfully saved.', ['id' => 'system-message-container']); + } /** * Installs a Extension in Joomla that is located in a folder inside the server @@ -305,12 +324,13 @@ public function setErrorReportingToDevelopment() * @note: doAdminLogin() before * * @deprecated since Joomla 3.4.4-dev. Use installExtensionFromFolder($path, $type = 'Extension') instead. + * @return void */ public function installExtensionFromDirectory($path, $type = 'Extension') - { - $this->debug('Suggested to use installExtensionFromFolder instead of installExtensionFromDirectory'); - $this->installExtensionFromFolder($path, $type); - } + { + $this->debug('Suggested to use installExtensionFromFolder instead of installExtensionFromDirectory'); + $this->installExtensionFromFolder($path, $type); + } /** * Installs a Extension in Joomla that is located in a folder inside the server @@ -318,134 +338,155 @@ public function installExtensionFromDirectory($path, $type = 'Extension') * @param String $path Path for the Extension * @param string $type Type of Extension * - * @note: doAdminLogin() before + * {@internal doAdminLogin() before} + * + * @return void */ public function installExtensionFromFolder($path, $type = 'Extension') { $I = $this; $I->amOnPage('/administrator/index.php?option=com_installer'); - $I->waitForText('Extensions: Install','30', ['css' => 'H1']); + $I->waitForText('Extensions: Install', '30', ['css' => 'H1']); $I->click(['link' => 'Install from Folder']); $this->debug('I enter the Path'); $I->fillField(['id' => 'install_directory'], $path); + // @todo: we need to find a better locator for the following Install button - $I->click(['xpath' => "//button[contains(@onclick,'Joomla.submitbutton3()')]"]); // Install button - $I->waitForText('was successful','60', ['id' => 'system-message-container']); + + // Install button + $I->click(['xpath' => "//button[contains(@onclick,'Joomla.submitbutton3()')]"]); + $I->waitForText('was successful', '60', ['id' => 'system-message-container']); $this->debug("$type successfully installed from $path"); } - /** - * Installs a Extension in Joomla that is located in a url - * - * @param String $url Url address to the .zip file - * @param string $type Type of Extension - * - * @note: doAdminLogin() before - */ - public function installExtensionFromUrl($url, $type = 'Extension') - { - $I = $this; - $I->amOnPage('/administrator/index.php?option=com_installer'); - $I->waitForText('Extensions: Install','30', ['css' => 'H1']); - $I->click(['link' => 'Install from URL']); - $this->debug('I enter the url'); - $I->fillField(['id' => 'install_url'], $url); - // @todo: we need to find a better locator for the following Install button - $I->click(['xpath' => "//button[contains(@onclick,'Joomla.submitbutton4()')]"]); // Install button - $I->waitForText('was successful','30', ['id' => 'system-message-container']); - if ($type == 'Extension') - { - $this->debug('Extension successfully installed from ' . $url); - } - if ($type == 'Plugin') - { - $this->debug('Installing plugin was successful.' . $url); - } - if ($type == 'Package') - { - $this->debug('Installation of the package was successful.' . $url); - } - } - - /** - * Function to check for PHP Notices or Warnings - * - * @param string $page Optional, if not given checks will be done in the current page - * - * @note: doAdminLogin() before - */ - public function checkForPhpNoticesOrWarnings($page = null) - { - $I = $this; - - if($page) - { - $I->amOnPage($page); - } - - $I->dontSeeInPageSource('Notice:'); - $I->dontSeeInPageSource('Notice:'); - $I->dontSeeInPageSource('Warning:'); - $I->dontSeeInPageSource('Warning:'); - $I->dontSeeInPageSource('Strict standards:'); - $I->dontSeeInPageSource('Strict standards:'); - $I->dontSeeInPageSource('The requested page can\'t be found'); - } - - /** - * Selects an option in a Joomla Radio Field based on its label - * - * @return void - */ - public function selectOptionInRadioField($label, $option) - { - $I = $this; - $I->debug("Trying to select the $option from the $label"); - $label = $I->findField(['xpath' => "//label[contains(normalize-space(string(.)), '$label')]"]); - $radioId = $label->getAttribute('for'); - - $I->click("//fieldset[@id='$radioId']/label[contains(normalize-space(string(.)), '$option')]"); - } - - /** - * Selects an option in a Chosen Selector based on its label - * - * @param string $label The text in the