\n" . print_r($message, TRUE) . "\n\n";
}
// Optional title to go before the output.
if (!empty($title)) {
$title = '
' . check_plain($title) . "
\n";
}
parent::verbose($title . $message);
}
/**
* Load the Performance admin page and clear all caches.
*/
public function clearAllCaches() {
$this->drupalGet('admin/config/development/performance');
$this->assertResponse(200);
$this->assertText(t('Performance'));
$this->assertText(t('Clear cache'));
$this->drupalPost(NULL, array(), t('Clear all caches'));
$this->assertResponse(200);
$this->assertText(t('Caches cleared'));
}
/**
* Create a content type for the tests.
*
* @param string $machine_name
* The machine name of a content type to create.
* @param string $label
* The human-readable name of the content type.
*
* @return array
* The content type definition.
*/
public function createContentType($machine_name, $label) {
// Create a content type.
$content_type = $this->drupalCreateContentType(array(
'type' => $machine_name,
'name' => $label,
));
// Enable meta tags for this new content type.
metatag_entity_type_enable('node', $machine_name, TRUE);
return $content_type;
}
/**
* Create an admin user for the tests.
*
* @param array $extra_permissions
* An array of permission strings to be added to the user.
*
* @return object
* A user object.
*/
public function createAdminUser(array $extra_permissions = array()) {
$permissions = array(
// Basic permissions for the module.
'administer meta tags',
'edit meta tags',
// General admin access.
'access administration pages',
);
// Reset the static variable used to identify permissions, otherwise it's
// possible the permissions check in drupalCreateUser will fail.
$this->checkPermissions(array(), TRUE);
cache_clear_all();
return $this->drupalCreateUser(array_merge($permissions, $extra_permissions));
}
/**
* Create a normal user for the tests.
*
* @param array $extra_permissions
* An array of permission strings to be added to the user.
*
* @return object
* A user object.
*/
public function createUser(array $extra_permissions) {
// Basic permissions for the module.
$permissions = array(
'edit meta tags',
);
// Reset the static variable used to identify permissions, otherwise it's
// possible the permissions check in drupalCreateUser will fail.
$this->checkPermissions(array(), TRUE);
cache_clear_all();
return $this->drupalCreateUser(array_merge($permissions, $extra_permissions));
}
/**
* Returns a new vocabulary with random properties.
*
* @param string $vocab_name
* If empty a random string will be used.
* @param string $content_type
* Any content types listed will have a Taxonomy Term reference field added
* that points to the new vocabulary.
*
* @return object
* A vocabulary object.
*/
public function createVocabulary($vocab_name = NULL, $content_type = NULL) {
if (empty($vocab_name)) {
$vocab_name = $this->randomName();
}
// Create a vocabulary.
$vocabulary = new stdClass();
$vocabulary->name = $vocab_name;
$vocabulary->description = $vocab_name;
$vocabulary->machine_name = drupal_strtolower($vocab_name);
$vocabulary->help = '';
$vocabulary->weight = mt_rand(0, 10);
if (!empty($content_type)) {
$vocabulary->nodes = array($content_type => $content_type);
}
taxonomy_vocabulary_save($vocabulary);
// Enable meta tags for this new vocabulary.
metatag_entity_type_enable('taxonomy_term', $vocab_name, TRUE);
return $vocabulary;
}
/**
* Returns a new taxonomy term in a specific vocabulary.
*
* @param object $vocabulary
* The vocabulary to add the term to.
* @param string $term_name
* The name to use for the new vocabulary. If none is provided one will be
* generated randomly.
*
* @return object
* A taxonomy term object.
*/
public function createTerm($vocabulary, $term_name = NULL) {
if (empty($term_name)) {
$term_name = $this->randomName();
}
// Create an object to save.
$term = new stdClass();
$term->name = $term_name;
$term->description = $term_name;
// Use the first available text format.
$term->format = db_query_range('SELECT format FROM {filter_format}', 0, 1)->fetchField();
$term->vid = $vocabulary->vid;
// Save the term.
taxonomy_term_save($term);
return $term;
}
/**
* Return an list of default values.
*
* This should cover all of the default meta tags provided for a test:foo
* entity.
*
* @return array
* List of meta tag default values to test.
*
* @todo Expand to cover more meta tags.
*
* @see metatag_test_metatag_config_default()
*/
public function getTestDefaults() {
return array(
// Basic meta tags.
'title' => array('value' => 'Test altered title'),
'description' => array('value' => 'Test foo description'),
'abstract' => array('value' => 'Test foo abstract'),
// @code
// 'keywords' => array('value' => ''),
// @endcode
// Advanced meta tags.
// @code
// 'robots' => array('value' => ''),
// 'news_keywords' => array('value' => ''),
// 'standout' => array('value' => ''),
// 'robots' => array('value' => ''),
// 'standout' => array('value' => ''),
// @endcode
'generator' => array('value' => 'Drupal 7 (https://www.drupal.org)'),
// @code
// 'standout' => array('value' => ''),
// 'image_src' => array('value' => ''),
// @endcode
'canonical' => array('value' => '[current-page:url:absolute]'),
'shortlink' => array('value' => '[current-page:url:unaliased]'),
// @code
// 'publisher' => array('value' => ''),
// 'author' => array('value' => ''),
// 'original-source' => array('value' => ''),
// 'revisit-after' => array('value' => ''),
// 'content-language' => array('value' => ''),'
// @endcode
);
}
/**
* Add a locale to the site.
*
* This assumes the Locale module is enabled.
*
* @param string $langcode
* The language code to add.
*/
public function addSiteLanguage($langcode) {
// Load the language-add page.
$this->drupalGet('admin/config/regional/language/add');
$this->assertResponse(200, 'Loaded the language-add admin page.');
// Submit the language-add form.
$args = array(
'langcode' => $langcode,
);
$this->drupalPost(NULL, $args, t('Add language'));
$this->assertResponse(200);
// Verify that the browser was returned to the main languages admin page.
$this->assertEqual($this->getUrl(), url('admin/config/regional/language', array('absolute' => TRUE)), 'Redirected back to the main languages admin page.');
// Clear the language list cache so it can be reloaded.
drupal_static_reset('language_list');
// Get all language definitions.
$languages = language_list();
$language = $languages[$langcode]->name;
$this->assertText(strip_tags(t('The language %language has been created and can now be used. More information is available on the help screen.', array(
'%language' => t($language),
'@locale-help' => url('admin/help/locale'),
))), 'A new language has been added.');
}
/**
* Set up a basic starting point for the locales.
*
* This assumes the Locale module is enabled. This also must be done before
* other user accounts are logged in.
*
* @param array $locales
* A list of locales to be enabled, in langcode format.
*/
public function setupLocales(array $locales = array()) {
// If no locales were requested, add Spanish and French.
if (empty($locales)) {
$locales[] = 'es';
$locales[] = 'fr';
}
// Log in as an admin user with privs to just set up the locales.
$perms = array(
'administer languages',
'translate interface',
'access administration pages',
);
$admin_user = $this->drupalCreateUser($perms);
$this->drupalLogin($admin_user);
// Load the admin page, just to have a point of reference.
$this->drupalGet('admin');
$this->assertResponse(200, 'Loaded the main admin page.');
// Identify the site's default language.
$default_language = language_default('language');
// Add the locales.
foreach ($locales as $langcode) {
// Don't create the default language, it's already present.
if ($langcode != $default_language) {
$this->addSiteLanguage($langcode);
}
}
// Enable URL language detection and selection.
$this->drupalGet('admin/config/regional/language/configure');
$this->assertResponse(200);
$edit = array(
'language[enabled][locale-url]' => TRUE,
);
// Also enable path handling for Entity Translation if it is installed.
if (module_exists('entity_translation')) {
$edit['language_content[enabled][locale-url]'] = TRUE;
}
$this->drupalPost(NULL, $edit, t('Save settings'));
$this->assertResponse(200);
// Once all the setup is done, log out the user.
$this->drupalLogout();
}
/**
* Get the {locales_source} lid value for a specific context.
*
* @param string $context
* The context string to search for.
* @param string $textgroup
* This string's textgroup; defaults to 'metatag'.
*
* @return int
* The {locales_source}.lid value for this string.
*/
public function getTranslationLidByContext($context, $textgroup = 'metatag') {
// Extra debug output.
$this->debugLocalesSourcesByContext($context);
// Look for the string that's actually being requested.
return (int) db_query("SELECT lid
FROM {locales_source}
WHERE textgroup = :textgroup
AND context = :context",
array(
':textgroup' => $textgroup,
':context' => $context,
))
->fetchField();
}
/**
* Get the {locales_source} lid value for a specific source.
*
* @param string $string
* The translation string to search for.
* @param string $textgroup
* This string's textgroup; defaults to 'metatag'.
*
* @return int
* The {locales_source}.lid value for this string.
*/
public function getTranslationLidBySource($string, $textgroup = 'metatag') {
// Extra debug output.
$this->debugLocalesSourcesByContext('', $textgroup);
// Look for the string that's actually being requested.
return (int) db_query("SELECT lid
FROM {locales_source}
WHERE textgroup = :textgroup
AND source = :source",
array(
':textgroup' => $textgroup,
':source' => $string,
))
->fetchField();
}
/**
* Get the {locales_source} lid values for a specific context.
*
* @param string $context
* The context string to search for.
* @param string $textgroup
* This string's textgroup; defaults to 'metatag'.
*
* @return int
* The {locales_source}.lid value for this string.
*/
public function getTranslationsByContext($context, $textgroup = 'metatag') {
return db_query("SELECT lid
FROM {locales_source}
WHERE textgroup = :textgroup
AND context = :context",
array(
':textgroup' => $textgroup,
':context' => $context,
))
->fetchCol();
}
/**
* Generate a dump of the {locales_source} records for a specific context.
*
* @param string $context
* The translation context to search against.
* @param string $textgroup
* This string's textgroup; defaults to 'metatag'.
*/
public function debugLocalesSourcesByContext($context, $textgroup = 'metatag') {
// Get a dump of all i18n strings for Metatag.
$records = db_query("SELECT lid, location, textgroup, source, context, version
FROM {locales_source}
WHERE textgroup = :textgroup",
array(
':textgroup' => $textgroup,
))
->fetchAllAssoc('lid');
foreach ($records as $key => $record) {
$records[$key] = (array) $record;
}
$args = array(
'caption' => 'i18n source check for . ' . $context,
'header' => array(
'lid',
'location',
'textgroup',
'source',
'context',
'version',
),
'rows' => $records,
);
$this->verbose(theme('table', $args));
}
/**
* Save a {locales_target} translation string to the database.
*
* @param int $lid
* The {locales_source}.lid primary key.
* @param string $context
* The {locales_source}.context value for this string.
* @param string $langcode
* The language the string is being translated into.
* @param string $string_source
* The string that is being translated.
* @param string $string_target
* The destination string.
*/
public function saveTranslationString($lid, $context, $langcode, $string_source, $string_target) {
// Load the translation page for the front page's title tag.
$this->drupalGet('admin/config/regional/translate/edit/' . $lid);
$this->assertResponse(200, 'Loaded the front page title tag string translation page.');
$this->assertEqual($this->getUrl(), url('admin/config/regional/translate/edit/' . $lid, array('absolute' => TRUE)));
// Confirm that the permission-check text is not found.
$this->assertNoText(t('This is a user-defined string. You are not allowed to translate these strings.'));
// Look for the existing string. The string gets mungled by the Locale
// module, so need to replicate its behaviour.
$this->assertText(check_plain(wordwrap($string_source, 0)));
// Look for the context value; the context value is empty for all default
// i.e. interface strings, so don't test this when the context is empty.
if (!empty($context)) {
$this->assertText($context);
}
// Confirm that the destination strings exist.
$source_locale = language_default('language');
if (function_exists('i18n_string_source_language')) {
$source_locale = i18n_string_source_language();
}
if ($source_locale != 'en') {
$this->assertField('translations[en]', 'Found the English translation string field.');
}
if ($source_locale != 'fr') {
$this->assertField('translations[fr]', 'Found the French translation string field.');
}
if ($source_locale != 'es') {
$this->assertField('translations[es]', 'Found the Spanish translation string field.');
}
// Translate the string.
$edit = array(
"translations[{$langcode}]" => $string_target,
);
$this->drupalPost(NULL, $edit, t('Save translations'));
$this->assertResponse(200);
// Confirm the save worked.
$this->assertText(t('The string has been saved.'));
$this->assertEqual($this->getUrl(), url('admin/config/regional/translate/translate', array('absolute' => TRUE)));
// Debug output.
$this->debugLocalesTargetsByContext($context);
// Clear the Metatag caches.
metatag_flush_caches();
}
/**
* Generate a dump of the {locales_target} records for a specific context.
*
* @param string $context
* The translation context to search against.
*/
public function debugLocalesTargetsByContext($context) {
// , lt.i18n_status
$records = db_query("SELECT lt.lid, lt.translation, lt.language, lt.plid, lt.plural
FROM {locales_target} lt
INNER JOIN {locales_source} ls
ON lt.lid = ls.lid
WHERE ls.textgroup = 'metatag'
AND ls.context = :context",
array(':context' => $context))
->fetchAllAssoc('lid');
foreach ($records as $key => $record) {
$records[$key] = (array) $record;
}
$args = array(
'caption' => 'Locale target check for . ' . $context,
'header' => array(
'lid',
'translation',
'language',
'plid',
'plural',
// 'i18n_status',
),
'rows' => $records,
);
$this->verbose(theme('table', $args));
}
/**
* Creates an object which can be used for generating and checking behavior.
*
* @param string $identifier
* The machine name to identify this object in source code.
* @param string $path
* Path where generate metatags.
*
* @return object
* A mapping object.
*/
public function createTestObject($identifier, $path) {
$test_object = new stdClass();
$test_object->name = $identifier;
$test_object->path = $path;
$test_object->title = "My $identifier title";
$test_object->description = "My $identifier description";
$test_object->abstract = "My $identifier abstract";
$test_object->keywords = "My $identifier keywords";
return $test_object;
}
/**
* Generates meta tags by path from a test_object.
*
* @param object $test_object
* Metatag mapping object.
*/
public function generateByPathConfig($test_object) {
// Verify the "add context" page works.
$this->drupalGet('admin/config/search/metatags/context');
$this->assertResponse(200);
$this->assertText(t('Add a meta tag by path'));
// Verify the "add context" page works.
$this->drupalGet('admin/config/search/metatags/context/add');
$this->assertResponse(200);
$this->assertText(t('The unique ID for this metatag path context rule. This must contain only lower case letters, numbers and underscores.'));
// Add new Metatag object for this configuration.
$values = array(
'name' => $test_object->name,
);
$this->drupalPost('admin/config/search/metatags/context/add', $values, t('Add and configure'));
$this->assertResponse(200);
}
/**
* Edits meta tags by path from a test_object.
*
* @param object $test_object
* Metatag mapping object.
*/
public function editByPathConfig($test_object) {
$edit = array(
'paths' => $test_object->path,
'metatags[und][title][value]' => $test_object->title,
'metatags[und][description][value]' => $test_object->description,
'metatags[und][abstract][value]' => $test_object->abstract,
'metatags[und][keywords][value]' => $test_object->keywords,
);
$this->drupalPost('admin/config/search/metatags/context/' . $test_object->name, $edit, t('Save'));
$this->assertResponse(200);
}
/**
* Checks if meta tags have been added correctly from a test_object.
*
* @param object $test_object
* Metatag mapping object.
*/
public function checkByPathConfig($test_object) {
$this->drupalGet($test_object->path);
$this->assertResponse(200);
// Manually test the page title.
if (!empty($test_object->title)) {
$this->assertTitle($test_object->title, 'Title found in ' . $test_object->path);
}
// Test the other meta tags.
$tags = array('description', 'abstract', 'keywords');
foreach ($tags as $tag) {
if (!empty($test_object->{$tag})) {
$this->assertRaw($test_object->{$tag}, $tag . ' found in ' . $test_object->path);
}
else {
$this->assertNoRaw('assertTrue($count >= 1, 'Found Metatag strings to translate.');
$this->assertNoText(t('No strings available.'));
$xpath = $this->xpath("//body//div[@class='content']//table//tbody//tr");
$this->verbose("Found {$count} items to translate.");
if (!empty($string)) {
$this->assertText($context);
$this->assertText('metatag:' . $context);
}
}
// If the string is not supposed to be found, then confirm the context is
// not available.
else {
$this->assertNoText($context);
$this->assertNoText('metatag:' . $context);
}
}
/**
* Create an image of a specific size & type.
*
* @param string $image_size
* The size of the requested image in 'XxY' format; defaults to '200x200'.
* @param string $format
* The image format to use, defaults to 'png'.
*
* @return string
* The URL to a public file.
*/
public function generateImage($image_size = '200x200', $format = 'png') {
// Only proceed if the Devel Generate module is installed.
if (module_exists('devel_generate')) {
// Load the Devel Generate image generator logic.
module_load_include('inc', 'devel_generate', 'image.devel_generate');
$image_format = 'png';
$image_size = '200x200';
$temp_image = devel_generate_image($image_format, $image_size, $image_size);
return file_unmanaged_move($temp_image, 'public://');
}
else {
$this->error('The Devel Generate module is not enabled, it must be added to the $modules array in the setUp() method for this test class.');
}
}
/**
* Create an image file object of a specific size & type.
*
* @param string $image_size
* The size of the requested image in 'XxY' format; defaults to '200x200'.
* @param string $format
* The image format to use, defaults to 'png'.
*
* @return object
* The file object for the generated image.
*/
public function generateImageFile($image_size = '200x200', $format = 'png') {
// Generate a test image.
$image_uri = $this->generateImage();
// Create a file object for this image.
$file = new StdClass();
$file->fid = NULL;
$file->uid = 1;
$file->uri = $image_uri;
$file->filemime = file_get_mimetype($image_uri);
$file->filesize = filesize($image_uri);
$file->status = 1;
$file->timestamp = filemtime($image_uri);
$saved_file = file_save($file);
return $saved_file;
}
/**
* Verify a user entity's meta tags load correctly.
*
* @param object $user
* A user object that is to be tested.
*/
protected function assertUserEntityTags($user) {
// Load the user's profile page.
$this->drupalGet('user/' . $user->uid);
$this->assertResponse(200);
// Verify the title is using the custom default for this vocabulary.
$xpath = $this->xpath("//meta[@name='abstract']");
$this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.');
$this->assertEqual($xpath[0]['content'], $user->name . " ponies");
}
/**
* Generate a string that is allowable as a machine name.
*
* @param int $length
* How long the machine name will be, defaults to eight characters.
*
* @return string
* A string that contains lowercase letters and numbers, with a letter as
* the first character.
*/
public function randomMachineName($length = 8) {
return strtolower($this->randomName($length));
}
}