'Taxonomy upgrade path', 'description' => 'Taxonomy upgrade path tests.', 'group' => 'Upgrade path', ); } public function setUp() { // Path to the database dump. $this->databaseDumpFiles = array( drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.filled.database.php', ); parent::setUp(); } /** * Retrieve an array mapping allowed vocabulary id to field name for * all taxonomy_term_reference fields for which an instance exists * for the specified entity type and bundle. */ function instanceVocabularies($entity_type, $bundle) { $instances = array(); foreach (field_info_instances($entity_type, $bundle) as $instance) { $field = field_info_field($instance['field_name']); if ($field['type'] == 'taxonomy_term_reference') { foreach ($field['settings']['allowed_values'] as $tree) { // Prefer valid taxonomy term reference fields for a given vocabulary // when they exist. if (empty($instances[$tree['vocabulary']]) || $instances[$tree['vocabulary']] == 'taxonomyextra') { $instances[$tree['vocabulary']] = $field['field_name']; } } } } return $instances; } /** * Basic tests for the taxonomy upgrade. */ public function testTaxonomyUpgrade() { $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.'); // Visit the front page to assert for PHP warning and errors. $this->drupalGet(''); // Check that taxonomy_vocabulary_node_type and taxonomy_term_node have been // removed. $this->assertFalse(db_table_exists('taxonomy_vocabulary_node_type'), 'taxonomy_vocabulary_node_type has been removed.'); $this->assertFalse(db_table_exists('taxonomy_term_node'), 'taxonomy_term_node has been removed.'); // Check that the node type 'page' has been associated to a taxonomy // reference field for each vocabulary. $voc_keys = array(); foreach (taxonomy_get_vocabularies() as $vocab) { $voc_keys[] = $vocab->machine_name; } $instances = $this->instanceVocabularies('node', 'page'); $inst_keys = array_keys($instances); sort($voc_keys); sort($inst_keys); $this->assertEqual($voc_keys, $inst_keys, 'Node type page has instances for every vocabulary.'); // Ensure instance variables are getting through. foreach ($instances as $instance) { $this->assertTrue(isset($instance['required']), 'The required setting was preserved during the upgrade path.'); $this->assertTrue($instance['description'], 'The description was preserved during the upgrade path'); } // Node type 'story' was not explicitly in $vocabulary->nodes but // each node of type 'story' was associated to one or more terms. // Check that the node type 'story' has been associated only to // the taxonomyextra field. $instances = $this->instanceVocabularies('node', 'story'); $field_names = array_flip($instances); $this->assertEqual(count($field_names), 1, 'Only one taxonomy term field instance exists for story nodes'); $this->assertEqual(key($field_names), 'taxonomyextra', 'Only the excess taxonomy term field is used on story nodes'); // Check that the node type 'poll' has been associated to no taxonomy // reference field. $instances = $this->instanceVocabularies('node', 'poll'); $this->assertTrue(empty($instances), 'Node type poll has no taxonomy term reference field instances.'); // Check that each node of type 'page' and 'story' is associated to all the // terms except terms whose ID is equal to the node ID or is equal to the // node ID subtracted from 49. $nodes = node_load_multiple(array(), array('type' => 'page')); $nodes += node_load_multiple(array(), array('type' => 'story')); $terms = db_select('taxonomy_term_data', 'td') ->fields('td') ->orderBy('vid') ->orderBy('tid') ->execute() ->fetchAllAssoc('tid'); field_attach_prepare_view('node', $nodes, 'full'); foreach ($nodes as $nid => $node) { $node->content = field_attach_view('node', $node, 'full'); $render = drupal_render($node->content); $this->drupalSetContent($render); $this->verbose($render); $vocabulary_seen = array(); foreach ($terms as $tid => $term) { // In our test database, each node is arbitrary associated with all // terms except two: one whose tid is ($nid) and one whose tid is // (49 - $nid). $should_be_displayed = ($tid != $nid) && ($tid + $nid != 49); // Only vocabularies 13 to 24 are properly associated with the node // type 'page'. All other node types are not associated with any // vocabulary, but still are associated with terms. Those terms // will be moved to the taxonomy extra field. if ($node->type == 'page' && $term->vid >= 13 && $term->vid <= 24) { $vocabulary = taxonomy_vocabulary_load($term->vid); $field_class = 'field-name-' . strtr('taxonomy_' . $vocabulary->machine_name, '_', '-');; } else { $field_class = 'field-name-taxonomyextra'; } // Odd vocabularies are single, so any additional term will be moved // to the taxonomy extra field. if ($should_be_displayed) { if ($term->vid % 2 == 1 && !empty($vocabulary_seen[$term->vid])) { $field_class = 'field-name-taxonomyextra'; } $vocabulary_seen[$term->vid] = TRUE; } $args = array( '%name' => $term->name, '@field' => $field_class, '%nid' => $nid, ); // Use link rather than term name because migrated term names can be // substrings of other term names. e.g. "term 1 of vocabulary 2" is // found when "term 1 of vocabulary 20" is output. $term_path = url('taxonomy/term/' . $term->tid); if (!$should_be_displayed) { // Look for any link with the term path. $links = $this->xpath('//a[@href=:term_path]', array(':term_path' => $term_path)); $this->assertFalse($links, format_string('Term %name (@field) is not displayed on node %nid', $args)); } else { // Look for a link with the term path inside the correct field. // We search for "SPACE + class + SPACE" to avoid matching a substring // of the class. $links = $this->xpath('//div[contains(concat(" ", normalize-space(@class), " "), :field_class)]//a[@href=:term_path]', array(':field_class' => ' ' . $field_class . ' ', ':term_path' => $term_path)); $this->assertTrue($links, format_string('Term %name (@field) is displayed on node %nid', $args)); } } // nid 1, revision 1 had a bogus record in {term_node} pointing to term // ID 0. Make sure we ignored this instead of generating a bogus term. if ($node->nid == 1) { $link = l($term->name, 'taxonomy/term/0'); $this->assertNoRaw($link, format_string('Bogus term (tid 0) is not displayed on node 1 vid %old_vid.', $args)); } // The first 12 nodes have two revisions. For nodes with // revisions, check that the oldest revision is associated only // to terms whose ID is equal to the node ID or 49 less the node ID. $revisions = node_revision_list($node); if ($node->nid < 13) { $this->assertEqual(count($revisions), 2, format_string('Node %nid has two revisions.', $args)); $last_rev = end($revisions); $args['%old_vid'] = $last_rev->vid; $node_old = node_load($node->nid, $last_rev->vid); field_attach_prepare_view('node', array($node_old->nid => $node_old), 'full'); $node_old->content = field_attach_view('node', $node_old, 'full'); $render = drupal_render($node_old->content); $this->drupalSetContent($render); $this->verbose($render); $term = $terms[$node->nid]; $link = l($term->name, 'taxonomy/term/' . $term->tid); $this->assertRaw($link, format_string('Term %name (@field) is displayed on node %nid vid %old_vid.', $args)); $term = $terms[49-$node->nid]; $link = l($term->name, 'taxonomy/term/' . $term->tid); $this->assertRaw($link, format_string('Term %name (@field) is displayed on node %nid %old_vid.', $args)); } else { $this->assertEqual(count($revisions), 1, format_string('Node %nid has one revision.', $args)); } } } }