language_hierarchy.test in Language Hierarchy 7
Tests for Language Hierarchy module.
File
tests/language_hierarchy.testView source
<?php
/**
* @file
* Tests for Language Hierarchy module.
*/
/**
* Base class for Language Hierarchy module tests.
*/
abstract class LanguageHierarchyBaseTestCase extends DrupalWebTestCase {
protected $current_user;
protected $admin_user;
protected $translator_user;
protected $admin_user_permissions = array(
'administer languages',
'access administration pages',
);
protected $translator_user_permissions = array(
'translate interface',
'access administration pages',
);
// Hierarchical list of languages used in this test.
protected $languages = array(
// Portuguese, International
array(
'langcode' => 'pt',
'parent' => '',
),
// Portuguese, Brazil
array(
'langcode' => 'pt-br',
'parent' => 'pt',
),
// Portuguese, Portugal
array(
'langcode' => 'pt-pt',
'parent' => 'pt',
),
);
function setUp() {
$args = func_get_args();
call_user_func_array(array(
'parent',
'setUp',
), $args);
// Reset user fields to make test object reusable.
unset($this->current_user);
unset($this->admin_user);
unset($this->translator_user);
}
/**
* Get a language object from a language code.
*/
public function getLanguage($langcode) {
if (is_object($langcode)) {
return $langcode;
}
else {
$language_list = language_list();
return $language_list[$langcode];
}
}
/**
* Install a specified language if it has not been already, otherwise make
* sure that the language is enabled.
*
* @param $langcode
* Langcode of language to be added.
* @param string|null $parent
* Langcode of parent language, NULL if there is no parent language.
*/
public function addLanguage($langcode, $parent = NULL) {
// Check to make sure that language has not already been installed.
$this
->drupalGet('admin/config/regional/language');
if (strpos($this
->drupalGetContent(), 'enabled[' . $langcode . ']') === FALSE) {
// Doesn't have language installed so add it.
$edit = array();
if ($parent) {
$edit['parent_language_list'] = $parent;
}
$edit['langcode'] = $langcode;
$this
->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
// Make sure we are not using a stale list.
drupal_static_reset('language_list');
$languages = language_list('language');
$this
->assertTrue(array_key_exists($langcode, $languages), t('Language was installed successfully.'));
if (array_key_exists($langcode, $languages)) {
$this
->assertRaw(t('The language %language has been created and can now be used. More information is available on the <a href="@locale-help">help screen</a>.', array(
'%language' => $languages[$langcode]->name,
'@locale-help' => url('admin/help/locale'),
)), t('Language has been created.'));
}
}
elseif ($this
->xpath('//input[@type="checkbox" and @name=:name and @checked="checked"]', array(
':name' => 'enabled[' . $langcode . ']',
))) {
// It is installed and enabled. No need to do anything.
$this
->assertTrue(TRUE, 'Language [' . $langcode . '] already installed and enabled.');
}
else {
// It is installed but not enabled. Enable it.
$this
->assertTrue(TRUE, 'Language [' . $langcode . '] already installed.');
$this
->drupalPost(NULL, array(
'enabled[' . $langcode . ']' => TRUE,
), t('Save configuration'));
$this
->assertRaw(t('Configuration saved.'), t('Language successfully enabled.'));
}
}
/**
* Add required languages.
*/
public function addLanguages() {
foreach ($this->languages as $language) {
// Add language.
$this
->addLanguage($language['langcode'], $language['parent']);
}
}
/**
* Translates given string into language of choice.
*
* @param string $string
* String to translate.
* @param string $translation
* Translation of that string.
* @param string $langcode
* Target language of translation.
*/
public function addStringTranslation($string, $translation, $langcode) {
$search = array(
'string' => $string,
'language' => 'all',
'translation' => 'all',
'group' => 'all',
);
$this
->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
// assertText() seems to remove the input field where $string always could be
// found, so this is not a false assert. See how assertNoText succeeds
// later.
$this
->assertText($string, 'Search found the string.');
$this
->assertRaw($this
->getLanguageIndicator($langcode), 'String is untranslated.');
// Assume this is the only result, given the random string.
$this
->clickLink(t('edit'));
// No t() here, it's surely not translated yet.
$this
->assertText($string, 'String found on edit screen.');
$edit = array(
"translations[{$langcode}]" => $translation,
);
$this
->drupalPost(NULL, $edit, t('Save translations'));
$this
->assertText(t('The string has been saved.'), 'The string has been saved.');
$this
->assertEqual($this
->getUrl(), url('admin/config/regional/translate/translate', array(
'absolute' => TRUE,
)), 'Correct page redirection.');
}
/**
* Get a language indicator used on translate interface page.
*
* @param $langcode
*
* @return string
*/
public function getLanguageIndicator($langcode) {
// This is the language indicator on the translation search screen for
// untranslated strings. Copied straight from locale.inc.
return "<em class=\"locale-untranslated\">{$langcode}</em> ";
}
/**
* Enable URL language detection.
*/
function enableUrlLanguageDetection($types = array(
'language',
'language_content',
)) {
// Enable URL language detection and selection.
// In some cases language_content is not available.
$edit = array();
if (is_array($types) && in_array('language', $types) || is_string($types) && $types == 'language') {
$edit['language[enabled][locale-url]'] = TRUE;
}
if (is_array($types) && in_array('language_content', $types) || is_string($types) && $types == 'language_content') {
$edit['language_content[enabled][locale-interface]'] = TRUE;
}
$this
->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings'));
$this
->assertRaw(t('Language negotiation configuration saved.'), t('URL language detection enabled.'));
$this
->drupalGet('admin/config/regional/language/configure');
// Reset caches.
drupal_static_reset('locale_url_outbound_alter');
drupal_static_reset('language_list');
}
/**
* Retrieves a Drupal path or an absolute path with language.
*
* @param $language
* Language code or language object.
*/
function get($language, $path = '', array $options = array(), array $headers = array()) {
$options['language'] = $this
->getLanguage($language);
return $this
->drupalGet($path, $options, $headers);
}
/**
* Posts to a Drupal path with language.
*/
function post($language, $path, $edit, $submit, array $options = array(), array $headers = array(), $form_html_id = NULL, $extra_post = NULL) {
$options['language'] = $this
->getLanguage($language);
$this
->drupalPost($path, $edit, $submit, $options, $headers, $form_html_id, $extra_post);
}
/**
* Login the given user only if she has not changed.
*/
function drupalLogin(stdClass $account) {
if (!isset($this->current_user) || $this->current_user->uid != $account->uid) {
$this->current_user = $account;
parent::drupalLogin($account);
}
}
/**
* Create a "Basic page" in the specified language.
*
* @param $title
* Title of the basic page in the specified language.
* @param $body
* Body of the basic page in the specified language.
* @param $langcode
* The language code to be assigned to the specified values.
*/
function createPageNode($title, $body, $langcode) {
$edit = array();
$edit["title"] = $title;
// Language code on field of a new node is initially the current language.
$edit["body[en][0][value]"] = $body;
$edit['language'] = $langcode;
$this
->drupalPost('node/add/page', $edit, t('Save'));
$this
->assertRaw(t('Basic page %title has been created.', array(
'%title' => $title,
)), t('Basic page created.'));
// Check to make sure the node was created.
$node = $this
->drupalGetNodeByTitle($title);
$this
->assertTrue($node, t('Node found in database.'));
return $node;
}
/**
* Returns a user with administration rights.
*
* @param $permissions
* Additional permissions for administrative user.
*/
function getAdminUser(array $permissions = array()) {
if (!isset($this->admin_user)) {
$this->admin_user = $this
->drupalCreateUser(array_merge($this->admin_user_permissions, $permissions));
}
return $this->admin_user;
}
/**
* Returns a user with minimal translation rights.
*
* @param $permissions
* Additional permissions for administrative user.
*/
public function getTranslatorUser(array $permissions = array()) {
if (!isset($this->translator_user)) {
$this->translator_user = $this
->drupalCreateUser(array_merge($this->translator_user_permissions, $permissions));
}
return $this->translator_user;
}
/**
* Log in as admin user.
*/
public function loginAdminUser() {
$this
->drupalLogin($this
->getAdminUser());
}
/**
* Log in as translator user.
*/
public function loginTranslatorUser() {
$this
->drupalLogin($this
->getTranslatorUser());
}
/**
* Move block to region, from block.test
*/
function moveBlockToRegion($block, $region = 'sidebar_first') {
// Set the created block to a specific region.
$edit = array();
$edit['blocks[' . $block['module'] . '_' . $block['delta'] . '][region]'] = $region;
$this
->drupalPost('admin/structure/block', $edit, t('Save blocks'));
// Confirm that the block was moved to the proper region.
$this
->assertText(t('The block settings have been updated.'), t('Block successfully moved to %region_name region.', array(
'%region_name' => $region,
)));
// Confirm that the block is being displayed.
$this
->drupalGet('node');
$this
->assertText(check_plain($block['title']), 'Block successfully being displayed on the page.');
// Confirm that the custom block was found at the proper region.
$xpath = $this
->buildXPathQuery('//div[@class=:region-class]//div[@id=:block-id]/*', array(
':region-class' => 'region region-' . str_replace('_', '-', $region),
':block-id' => 'block-' . $block['module'] . '-' . $block['delta'],
));
$this
->assertFieldByXPath($xpath, NULL, format_string('Custom block found in %region_name region.', array(
'%region_name' => $region,
)));
}
}
/**
* Functional tests for string (interface) translation.
*/
class LanguageHierarchyStringTranslationWebTestCase extends LanguageHierarchyBaseTestCase {
public static function getInfo() {
return array(
'name' => 'String translation hierarchy',
'description' => 'Test string translation with language inheritance.',
'group' => 'Language Hierarchy',
);
}
public function setUp() {
parent::setUp('language_hierarchy');
}
/**
* Adds a language and tests string translation by users with the appropriate permissions.
*/
public function testStringTranslation() {
// This will be the string to be translated.
$string = $this
->randomName(16);
// This will be the translation of $string.
$translation = $this
->randomName(16);
$this
->loginAdminUser();
// Add languages used by this test case.
$this
->addLanguages();
$this
->drupalLogout();
// Search for the string and translate it.
$this
->loginTranslatorUser();
// Add strings to database.
foreach ($this->languages as $language) {
t($string, array(), array(
'langcode' => $language['langcode'],
));
}
// Reset locale cache.
locale_reset();
$parent_langcode = $this->languages[0]['langcode'];
$child_langcode = $this->languages[1]['langcode'];
$child_langcode2 = $this->languages[2]['langcode'];
// Translate $string for parent language.
$this
->addStringTranslation($string, $translation, $parent_langcode);
// Translate $string for one of child languages.
$translation2 = $this
->randomName(16);
$this
->addStringTranslation($string, $translation2, $child_langcode2);
// Check if t() works as expected.
$parent_translation = t($string, array(), array(
'langcode' => $parent_langcode,
));
$this
->assertTrue($string != $translation && $parent_translation == $translation, 't() works for parent.');
// Check if inheritance of t() works as expected.
$child_translation = t($string, array(), array(
'langcode' => $child_langcode,
));
$this
->assertTrue($string != $translation && $child_translation == $translation, 't() inherited from parent.');
// Check if translated string for child language works as expected.
$child_translation2 = t($string, array(), array(
'langcode' => $child_langcode2,
));
$this
->assertTrue($string != $translation2 && $child_translation2 == $translation2, 't() with translation for child.');
}
public function tearDown() {
parent::tearDown();
unset($this->admin_user);
unset($this->translator_user);
unset($this->current_user);
}
}
/**
* Functional tests for i18n_string (user-defined strings) translation.
*/
class LanguageHierarchyI18nStringTranslationWebTestCase extends LanguageHierarchyBaseTestCase {
public static function getInfo() {
return array(
'name' => 'User-defined string translation hierarchy',
'description' => 'Test i18n_string translation with language inheritance.',
'group' => 'Language Hierarchy',
);
}
public function setUp() {
// We can use any of the modules that define a text group, to use it for testing
parent::setUp('language_hierarchy', 'i18n_menu');
$this->translator_user_permissions[] = 'translate user-defined strings';
}
/**
* Adds a language and tests i18n_string translation by users with the appropriate permissions.
*/
public function testI18nStringTranslation() {
// This will be the string to be translated.
$string = $this
->randomName(16);
// This will be the translation of $string.
$translation = $this
->randomName(16);
$this
->loginAdminUser();
// Add languages used by this test case.
$this
->addLanguages();
$this
->drupalLogout();
// Search for the string and translate it.
$this
->loginTranslatorUser();
$textgroup = 'menu';
// Save source string and store translation.
$name = "{$textgroup}:item:1:title";
i18n_string_update($name, $string);
// Reset cache for text group
i18n_string_textgroup($textgroup)
->cache_reset();
$parent_langcode = $this->languages[0]['langcode'];
$child_langcode = $this->languages[1]['langcode'];
$child_langcode2 = $this->languages[2]['langcode'];
$translation2 = $this
->randomName(16);
$translations = array(
// Translate $string for parent language.
$parent_langcode => $translation,
// Translate $string for one of child languages.
$child_langcode2 => $translation2,
);
$this
->addI18nStringTranslation($textgroup, $string, $translations);
// Check if i18n_string() works as expected: a translation should be found
// for the parent language.
$parent_translation = i18n_string_translate($name, 'NOT FOUND', array(
'langcode' => $parent_langcode,
));
$this
->assertTrue($string != $translation && $parent_translation == $translation, 'i18n_string() works for parent.');
// Check if inheritance of i18n_string() works as expected: no specific
// translation for this child language, so translation in parent language
// returned.
$child_translation = i18n_string_translate($name, 'NOT FOUND', array(
'langcode' => $child_langcode,
));
$this
->assertTrue($string != $translation && $child_translation == $translation, 'i18n_string() inherited from parent.');
// Check if translated string for child language works as expected: a
// specific translation for this child language should be found.
$child_translation2 = i18n_string_translate($name, 'NOT FOUND', array(
'langcode' => $child_langcode2,
));
$this
->assertTrue($string != $translation2 && $child_translation2 == $translation2, 'i18n_string() with translation for child.');
}
/**
* Create translation for string in textgroup
*
* Adapted from Drupali18nTestCase::createStringTranslation().
*
* @param $translations
* Optional array of langcode => translation. If not present, it will be generated.
*/
function addI18nStringTranslation($textgroup, $name, $translations) {
// This is the language indicator on the translation search screen for
// untranslated strings. Copied straight from locale.inc.
$language_indicator = "<em class=\"locale-untranslated\">";
// Search for the name and translate it.
$search = array(
'string' => $name,
'language' => 'all',
'translation' => 'all',
'group' => $textgroup,
);
$this
->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
// assertText() seems to remove the input field where $name always could be
// found, so this is not a false assert. See how assertNoText succeeds
// later.
$this
->assertText(check_plain($name), t('Search found the name.'));
$this
->assertRaw($language_indicator, t('Name is untranslated.'));
// Assume this is the only result, given the random name.
$this
->clickLink(t('edit'));
// We save the lid from the path.
$matches = array();
preg_match('!admin/config/regional/translate/edit/(\\d+)!', $this
->getUrl(), $matches);
$lid = $matches[1];
// No t() here, it's surely not translated yet.
$this
->assertText(check_plain($name), t('name found on edit screen.'));
foreach ($translations as $langcode => $translation) {
$edit["translations[{$langcode}]"] = $translation;
}
$this
->drupalPost(NULL, $edit, t('Save translations'));
$this
->assertText(t('The string has been saved.'), t('The string has been saved.'));
$this
->assertEqual($this
->getUrl(), url('admin/config/regional/translate/translate', array(
'absolute' => TRUE,
)), t('Correct page redirection.'));
$this
->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
// The indicator should not be here.
foreach ($translations as $langcode => $translation) {
$this
->assertNoRaw($language_indicator . $langcode . '</em>', t('String is translated.'));
}
return $translations;
}
}
Classes
Name | Description |
---|---|
LanguageHierarchyBaseTestCase | Base class for Language Hierarchy module tests. |
LanguageHierarchyI18nStringTranslationWebTestCase | Functional tests for i18n_string (user-defined strings) translation. |
LanguageHierarchyStringTranslationWebTestCase | Functional tests for string (interface) translation. |