cms/drupal/modules/node/node.test
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * @file
       
     5  * Tests for node.module.
       
     6  */
       
     7 
       
     8 /**
       
     9  * Defines a base class for testing the Node module.
       
    10  */
       
    11 class NodeWebTestCase extends DrupalWebTestCase {
       
    12   function setUp() {
       
    13     $modules = func_get_args();
       
    14     if (isset($modules[0]) && is_array($modules[0])) {
       
    15       $modules = $modules[0];
       
    16     }
       
    17     $modules[] = 'node';
       
    18     parent::setUp($modules);
       
    19 
       
    20     // Create Basic page and Article node types.
       
    21     if ($this->profile != 'standard') {
       
    22       $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
       
    23       $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
       
    24     }
       
    25   }
       
    26 }
       
    27 
       
    28 /**
       
    29  * Test the node_load_multiple() function.
       
    30  */
       
    31 class NodeLoadMultipleTestCase extends DrupalWebTestCase {
       
    32 
       
    33   public static function getInfo() {
       
    34     return array(
       
    35       'name' => 'Load multiple nodes',
       
    36       'description' => 'Test the loading of multiple nodes.',
       
    37       'group' => 'Node',
       
    38     );
       
    39   }
       
    40 
       
    41   function setUp() {
       
    42     parent::setUp();
       
    43     $web_user = $this->drupalCreateUser(array('create article content', 'create page content'));
       
    44     $this->drupalLogin($web_user);
       
    45   }
       
    46 
       
    47   /**
       
    48    * Create four nodes and ensure they're loaded correctly.
       
    49    */
       
    50   function testNodeMultipleLoad() {
       
    51     $node1 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
       
    52     $node2 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
       
    53     $node3 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 0));
       
    54     $node4 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0));
       
    55 
       
    56     // Confirm that promoted nodes appear in the default node listing.
       
    57     $this->drupalGet('node');
       
    58     $this->assertText($node1->title, 'Node title appears on the default listing.');
       
    59     $this->assertText($node2->title, 'Node title appears on the default listing.');
       
    60     $this->assertNoText($node3->title, 'Node title does not appear in the default listing.');
       
    61     $this->assertNoText($node4->title, 'Node title does not appear in the default listing.');
       
    62 
       
    63     // Load nodes with only a condition. Nodes 3 and 4 will be loaded.
       
    64     $nodes = node_load_multiple(NULL, array('promote' => 0));
       
    65     $this->assertEqual($node3->title, $nodes[$node3->nid]->title, 'Node was loaded.');
       
    66     $this->assertEqual($node4->title, $nodes[$node4->nid]->title, 'Node was loaded.');
       
    67     $count = count($nodes);
       
    68     $this->assertTrue($count == 2, format_string('@count nodes loaded.', array('@count' => $count)));
       
    69 
       
    70     // Load nodes by nid. Nodes 1, 2 and 4 will be loaded.
       
    71     $nodes = node_load_multiple(array(1, 2, 4));
       
    72     $count = count($nodes);
       
    73     $this->assertTrue(count($nodes) == 3, format_string('@count nodes loaded', array('@count' => $count)));
       
    74     $this->assertTrue(isset($nodes[$node1->nid]), 'Node is correctly keyed in the array');
       
    75     $this->assertTrue(isset($nodes[$node2->nid]), 'Node is correctly keyed in the array');
       
    76     $this->assertTrue(isset($nodes[$node4->nid]), 'Node is correctly keyed in the array');
       
    77     foreach ($nodes as $node) {
       
    78       $this->assertTrue(is_object($node), 'Node is an object');
       
    79     }
       
    80 
       
    81     // Load nodes by nid, where type = article. Nodes 1, 2 and 3 will be loaded.
       
    82     $nodes = node_load_multiple(array(1, 2, 3, 4), array('type' => 'article'));
       
    83     $count = count($nodes);
       
    84     $this->assertTrue($count == 3, format_string('@count nodes loaded', array('@count' => $count)));
       
    85     $this->assertEqual($nodes[$node1->nid]->title, $node1->title, 'Node successfully loaded.');
       
    86     $this->assertEqual($nodes[$node2->nid]->title, $node2->title, 'Node successfully loaded.');
       
    87     $this->assertEqual($nodes[$node3->nid]->title, $node3->title, 'Node successfully loaded.');
       
    88     $this->assertFalse(isset($nodes[$node4->nid]));
       
    89 
       
    90     // Now that all nodes have been loaded into the static cache, ensure that
       
    91     // they are loaded correctly again when a condition is passed.
       
    92     $nodes = node_load_multiple(array(1, 2, 3, 4), array('type' => 'article'));
       
    93     $count = count($nodes);
       
    94     $this->assertTrue($count == 3, format_string('@count nodes loaded.', array('@count' => $count)));
       
    95     $this->assertEqual($nodes[$node1->nid]->title, $node1->title, 'Node successfully loaded');
       
    96     $this->assertEqual($nodes[$node2->nid]->title, $node2->title, 'Node successfully loaded');
       
    97     $this->assertEqual($nodes[$node3->nid]->title, $node3->title, 'Node successfully loaded');
       
    98     $this->assertFalse(isset($nodes[$node4->nid]), 'Node was not loaded');
       
    99 
       
   100     // Load nodes by nid, where type = article and promote = 0.
       
   101     $nodes = node_load_multiple(array(1, 2, 3, 4), array('type' => 'article', 'promote' => 0));
       
   102     $count = count($nodes);
       
   103     $this->assertTrue($count == 1, format_string('@count node loaded', array('@count' => $count)));
       
   104     $this->assertEqual($nodes[$node3->nid]->title, $node3->title, 'Node successfully loaded.');
       
   105   }
       
   106 }
       
   107 
       
   108 /**
       
   109  * Tests for the hooks invoked during node_load().
       
   110  */
       
   111 class NodeLoadHooksTestCase extends DrupalWebTestCase {
       
   112   public static function getInfo() {
       
   113     return array(
       
   114       'name' => 'Node load hooks',
       
   115       'description' => 'Test the hooks invoked when a node is being loaded.',
       
   116       'group' => 'Node',
       
   117     );
       
   118   }
       
   119 
       
   120   function setUp() {
       
   121     parent::setUp('node_test');
       
   122   }
       
   123 
       
   124   /**
       
   125    * Test that hook_node_load() is invoked correctly.
       
   126    */
       
   127   function testHookNodeLoad() {
       
   128     // Create some sample articles and pages.
       
   129     $node1 = $this->drupalCreateNode(array('type' => 'article', 'status' => NODE_PUBLISHED));
       
   130     $node2 = $this->drupalCreateNode(array('type' => 'article', 'status' => NODE_PUBLISHED));
       
   131     $node3 = $this->drupalCreateNode(array('type' => 'article', 'status' => NODE_NOT_PUBLISHED));
       
   132     $node4 = $this->drupalCreateNode(array('type' => 'page', 'status' => NODE_NOT_PUBLISHED));
       
   133 
       
   134     // Check that when a set of nodes that only contains articles is loaded,
       
   135     // the properties added to the node by node_test_load_node() correctly
       
   136     // reflect the expected values.
       
   137     $nodes = node_load_multiple(array(), array('status' => NODE_PUBLISHED));
       
   138     $loaded_node = end($nodes);
       
   139     $this->assertEqual($loaded_node->node_test_loaded_nids, array($node1->nid, $node2->nid), 'hook_node_load() received the correct list of node IDs the first time it was called.');
       
   140     $this->assertEqual($loaded_node->node_test_loaded_types, array('article'), 'hook_node_load() received the correct list of node types the first time it was called.');
       
   141 
       
   142     // Now, as part of the same page request, load a set of nodes that contain
       
   143     // both articles and pages, and make sure the parameters passed to
       
   144     // node_test_node_load() are correctly updated.
       
   145     $nodes = node_load_multiple(array(), array('status' => NODE_NOT_PUBLISHED));
       
   146     $loaded_node = end($nodes);
       
   147     $this->assertEqual($loaded_node->node_test_loaded_nids, array($node3->nid, $node4->nid), 'hook_node_load() received the correct list of node IDs the second time it was called.');
       
   148     $this->assertEqual($loaded_node->node_test_loaded_types, array('article', 'page'), 'hook_node_load() received the correct list of node types the second time it was called.');
       
   149   }
       
   150 }
       
   151 
       
   152 /**
       
   153  * Tests the node revision functionality.
       
   154  */
       
   155 class NodeRevisionsTestCase extends DrupalWebTestCase {
       
   156 
       
   157   /**
       
   158    * Nodes used by the test.
       
   159    *
       
   160    * @var array
       
   161    */
       
   162   protected $nodes;
       
   163 
       
   164   /**
       
   165    * The revision messages for node revisions created in the test.
       
   166    *
       
   167    * @var array
       
   168    */
       
   169   protected $logs;
       
   170 
       
   171   public static function getInfo() {
       
   172     return array(
       
   173       'name' => 'Node revisions',
       
   174       'description' => 'Create a node with revisions and test viewing, saving, reverting, and deleting revisions.',
       
   175       'group' => 'Node',
       
   176     );
       
   177   }
       
   178 
       
   179   function setUp() {
       
   180     parent::setUp();
       
   181 
       
   182     // Create and login user.
       
   183     $web_user = $this->drupalCreateUser(array('view revisions', 'revert revisions', 'edit any page content',
       
   184                                                'delete revisions', 'delete any page content'));
       
   185     $this->drupalLogin($web_user);
       
   186 
       
   187     // Create initial node.
       
   188     $node = $this->drupalCreateNode();
       
   189     $settings = get_object_vars($node);
       
   190     $settings['revision'] = 1;
       
   191 
       
   192     $nodes = array();
       
   193     $logs = array();
       
   194 
       
   195     // Get original node.
       
   196     $nodes[] = $node;
       
   197 
       
   198     // Create three revisions.
       
   199     $revision_count = 3;
       
   200     for ($i = 0; $i < $revision_count; $i++) {
       
   201       $logs[] = $settings['log'] = $this->randomName(32);
       
   202 
       
   203       // Create revision with random title and body and update variables.
       
   204       $this->drupalCreateNode($settings);
       
   205       $node = node_load($node->nid); // Make sure we get revision information.
       
   206       $settings = get_object_vars($node);
       
   207 
       
   208       $nodes[] = $node;
       
   209     }
       
   210 
       
   211     $this->nodes = $nodes;
       
   212     $this->logs = $logs;
       
   213   }
       
   214 
       
   215   /**
       
   216    * Checks node revision related operations.
       
   217    */
       
   218   function testRevisions() {
       
   219     $nodes = $this->nodes;
       
   220     $logs = $this->logs;
       
   221 
       
   222     // Get last node for simple checks.
       
   223     $node = $nodes[3];
       
   224 
       
   225     // Confirm the correct revision text appears on "view revisions" page.
       
   226     $this->drupalGet("node/$node->nid/revisions/$node->vid/view");
       
   227     $this->assertText($node->body[LANGUAGE_NONE][0]['value'], 'Correct text displays for version.');
       
   228 
       
   229     // Confirm the correct log message appears on "revisions overview" page.
       
   230     $this->drupalGet("node/$node->nid/revisions");
       
   231     foreach ($logs as $log) {
       
   232       $this->assertText($log, 'Log message found.');
       
   233     }
       
   234 
       
   235     // Confirm that revisions revert properly.
       
   236     $this->drupalPost("node/$node->nid/revisions/{$nodes[1]->vid}/revert", array(), t('Revert'));
       
   237     $this->assertRaw(t('@type %title has been reverted back to the revision from %revision-date.',
       
   238                         array('@type' => 'Basic page', '%title' => $nodes[1]->title,
       
   239                               '%revision-date' => format_date($nodes[1]->revision_timestamp))), 'Revision reverted.');
       
   240     $reverted_node = node_load($node->nid);
       
   241     $this->assertTrue(($nodes[1]->body[LANGUAGE_NONE][0]['value'] == $reverted_node->body[LANGUAGE_NONE][0]['value']), 'Node reverted correctly.');
       
   242 
       
   243     // Confirm revisions delete properly.
       
   244     $this->drupalPost("node/$node->nid/revisions/{$nodes[1]->vid}/delete", array(), t('Delete'));
       
   245     $this->assertRaw(t('Revision from %revision-date of @type %title has been deleted.',
       
   246                         array('%revision-date' => format_date($nodes[1]->revision_timestamp),
       
   247                               '@type' => 'Basic page', '%title' => $nodes[1]->title)), 'Revision deleted.');
       
   248     $this->assertTrue(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid and vid = :vid', array(':nid' => $node->nid, ':vid' => $nodes[1]->vid))->fetchField() == 0, 'Revision not found.');
       
   249   }
       
   250 
       
   251   /**
       
   252    * Checks that revisions are correctly saved without log messages.
       
   253    */
       
   254   function testNodeRevisionWithoutLogMessage() {
       
   255     // Create a node with an initial log message.
       
   256     $log = $this->randomName(10);
       
   257     $node = $this->drupalCreateNode(array('log' => $log));
       
   258 
       
   259     // Save over the same revision and explicitly provide an empty log message
       
   260     // (for example, to mimic the case of a node form submitted with no text in
       
   261     // the "log message" field), and check that the original log message is
       
   262     // preserved.
       
   263     $new_title = $this->randomName(10) . 'testNodeRevisionWithoutLogMessage1';
       
   264     $updated_node = (object) array(
       
   265       'nid' => $node->nid,
       
   266       'vid' => $node->vid,
       
   267       'uid' => $node->uid,
       
   268       'type' => $node->type,
       
   269       'title' => $new_title,
       
   270       'log' => '',
       
   271     );
       
   272     node_save($updated_node);
       
   273     $this->drupalGet('node/' . $node->nid);
       
   274     $this->assertText($new_title, 'New node title appears on the page.');
       
   275     $node_revision = node_load($node->nid, NULL, TRUE);
       
   276     $this->assertEqual($node_revision->log, $log, 'After an existing node revision is re-saved without a log message, the original log message is preserved.');
       
   277 
       
   278     // Create another node with an initial log message.
       
   279     $node = $this->drupalCreateNode(array('log' => $log));
       
   280 
       
   281     // Save a new node revision without providing a log message, and check that
       
   282     // this revision has an empty log message.
       
   283     $new_title = $this->randomName(10) . 'testNodeRevisionWithoutLogMessage2';
       
   284     $updated_node = (object) array(
       
   285       'nid' => $node->nid,
       
   286       'vid' => $node->vid,
       
   287       'uid' => $node->uid,
       
   288       'type' => $node->type,
       
   289       'title' => $new_title,
       
   290       'revision' => 1,
       
   291     );
       
   292     node_save($updated_node);
       
   293     $this->drupalGet('node/' . $node->nid);
       
   294     $this->assertText($new_title, 'New node title appears on the page.');
       
   295     $node_revision = node_load($node->nid, NULL, TRUE);
       
   296     $this->assertTrue(empty($node_revision->log), 'After a new node revision is saved with an empty log message, the log message for the node is empty.');
       
   297   }
       
   298 }
       
   299 
       
   300 /**
       
   301  * Tests the node edit functionality.
       
   302  */
       
   303 class PageEditTestCase extends DrupalWebTestCase {
       
   304 
       
   305   /**
       
   306    * A user with permission to create and edit own page content.
       
   307    *
       
   308    * @var object
       
   309    */
       
   310   protected $web_user;
       
   311 
       
   312   /**
       
   313    * A user with permission to bypass node access and administer nodes.
       
   314    *
       
   315    * @var object
       
   316    */
       
   317   protected $admin_user;
       
   318 
       
   319   public static function getInfo() {
       
   320     return array(
       
   321       'name' => 'Node edit',
       
   322       'description' => 'Create a node and test node edit functionality.',
       
   323       'group' => 'Node',
       
   324     );
       
   325   }
       
   326 
       
   327   function setUp() {
       
   328     parent::setUp();
       
   329 
       
   330     $this->web_user = $this->drupalCreateUser(array('edit own page content', 'create page content'));
       
   331     $this->admin_user = $this->drupalCreateUser(array('bypass node access', 'administer nodes'));
       
   332   }
       
   333 
       
   334   /**
       
   335    * Checks node edit functionality.
       
   336    */
       
   337   function testPageEdit() {
       
   338     $this->drupalLogin($this->web_user);
       
   339 
       
   340     $langcode = LANGUAGE_NONE;
       
   341     $title_key = "title";
       
   342     $body_key = "body[$langcode][0][value]";
       
   343     // Create node to edit.
       
   344     $edit = array();
       
   345     $edit[$title_key] = $this->randomName(8);
       
   346     $edit[$body_key] = $this->randomName(16);
       
   347     $this->drupalPost('node/add/page', $edit, t('Save'));
       
   348 
       
   349     // Check that the node exists in the database.
       
   350     $node = $this->drupalGetNodeByTitle($edit[$title_key]);
       
   351     $this->assertTrue($node, 'Node found in database.');
       
   352 
       
   353     // Check that "edit" link points to correct page.
       
   354     $this->clickLink(t('Edit'));
       
   355     $edit_url = url("node/$node->nid/edit", array('absolute' => TRUE));
       
   356     $actual_url = $this->getURL();
       
   357     $this->assertEqual($edit_url, $actual_url, 'On edit page.');
       
   358 
       
   359     // Check that the title and body fields are displayed with the correct values.
       
   360     $active = '<span class="element-invisible">' . t('(active tab)') . '</span>';
       
   361     $link_text = t('!local-task-title!active', array('!local-task-title' => t('Edit'), '!active' => $active));
       
   362     $this->assertText(strip_tags($link_text), 0, 'Edit tab found and marked active.');
       
   363     $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
       
   364     $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
       
   365 
       
   366     // Edit the content of the node.
       
   367     $edit = array();
       
   368     $edit[$title_key] = $this->randomName(8);
       
   369     $edit[$body_key] = $this->randomName(16);
       
   370     // Stay on the current page, without reloading.
       
   371     $this->drupalPost(NULL, $edit, t('Save'));
       
   372 
       
   373     // Check that the title and body fields are displayed with the updated values.
       
   374     $this->assertText($edit[$title_key], 'Title displayed.');
       
   375     $this->assertText($edit[$body_key], 'Body displayed.');
       
   376 
       
   377     // Login as a second administrator user.
       
   378     $second_web_user = $this->drupalCreateUser(array('administer nodes', 'edit any page content'));
       
   379     $this->drupalLogin($second_web_user);
       
   380     // Edit the same node, creating a new revision.
       
   381     $this->drupalGet("node/$node->nid/edit");
       
   382     $edit = array();
       
   383     $edit['title'] = $this->randomName(8);
       
   384     $edit[$body_key] = $this->randomName(16);
       
   385     $edit['revision'] = TRUE;
       
   386     $this->drupalPost(NULL, $edit, t('Save'));
       
   387 
       
   388     // Ensure that the node revision has been created.
       
   389     $revised_node = $this->drupalGetNodeByTitle($edit['title']);
       
   390     $this->assertNotIdentical($node->vid, $revised_node->vid, 'A new revision has been created.');
       
   391     // Ensure that the node author is preserved when it was not changed in the
       
   392     // edit form.
       
   393     $this->assertIdentical($node->uid, $revised_node->uid, 'The node author has been preserved.');
       
   394     // Ensure that the revision authors are different since the revisions were
       
   395     // made by different users.
       
   396     $first_node_version = node_load($node->nid, $node->vid);
       
   397     $second_node_version = node_load($node->nid, $revised_node->vid);
       
   398     $this->assertNotIdentical($first_node_version->revision_uid, $second_node_version->revision_uid, 'Each revision has a distinct user.');
       
   399   }
       
   400 
       
   401   /**
       
   402    * Tests changing a node's "authored by" field.
       
   403    */
       
   404   function testPageAuthoredBy() {
       
   405     $this->drupalLogin($this->admin_user);
       
   406 
       
   407     // Create node to edit.
       
   408     $langcode = LANGUAGE_NONE;
       
   409     $body_key = "body[$langcode][0][value]";
       
   410     $edit = array();
       
   411     $edit['title'] = $this->randomName(8);
       
   412     $edit[$body_key] = $this->randomName(16);
       
   413     $this->drupalPost('node/add/page', $edit, t('Save'));
       
   414 
       
   415     // Check that the node was authored by the currently logged in user.
       
   416     $node = $this->drupalGetNodeByTitle($edit['title']);
       
   417     $this->assertIdentical($node->uid, $this->admin_user->uid, 'Node authored by admin user.');
       
   418 
       
   419     // Try to change the 'authored by' field to an invalid user name.
       
   420     $edit = array(
       
   421       'name' => 'invalid-name',
       
   422     );
       
   423     $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
       
   424     $this->assertText('The username invalid-name does not exist.');
       
   425 
       
   426     // Change the authored by field to an empty string, which should assign
       
   427     // authorship to the anonymous user (uid 0).
       
   428     $edit['name'] = '';
       
   429     $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
       
   430     $node = node_load($node->nid, NULL, TRUE);
       
   431     $this->assertIdentical($node->uid, '0', 'Node authored by anonymous user.');
       
   432 
       
   433     // Change the authored by field to another user's name (that is not
       
   434     // logged in).
       
   435     $edit['name'] = $this->web_user->name;
       
   436     $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
       
   437     $node = node_load($node->nid, NULL, TRUE);
       
   438     $this->assertIdentical($node->uid, $this->web_user->uid, 'Node authored by normal user.');
       
   439 
       
   440     // Check that normal users cannot change the authored by information.
       
   441     $this->drupalLogin($this->web_user);
       
   442     $this->drupalGet('node/' . $node->nid . '/edit');
       
   443     $this->assertNoFieldByName('name');
       
   444   }
       
   445 }
       
   446 
       
   447 /**
       
   448  * Tests the node entity preview functionality.
       
   449  */
       
   450 class PagePreviewTestCase extends DrupalWebTestCase {
       
   451   public static function getInfo() {
       
   452     return array(
       
   453       'name' => 'Node preview',
       
   454       'description' => 'Test node preview functionality.',
       
   455       'group' => 'Node',
       
   456     );
       
   457   }
       
   458 
       
   459   function setUp() {
       
   460     parent::setUp(array('taxonomy', 'node'));
       
   461 
       
   462     $web_user = $this->drupalCreateUser(array('edit own page content', 'create page content'));
       
   463     $this->drupalLogin($web_user);
       
   464 
       
   465     // Add a vocabulary so we can test different view modes.
       
   466     $vocabulary = (object) array(
       
   467       'name' => $this->randomName(),
       
   468       'description' => $this->randomName(),
       
   469       'machine_name' => drupal_strtolower($this->randomName()),
       
   470       'help' => '',
       
   471       'nodes' => array('page' => 'page'),
       
   472     );
       
   473     taxonomy_vocabulary_save($vocabulary);
       
   474 
       
   475     $this->vocabulary = $vocabulary;
       
   476 
       
   477     // Add a term to the vocabulary.
       
   478     $term = (object) array(
       
   479       'name' => $this->randomName(),
       
   480       'description' => $this->randomName(),
       
   481       // Use the first available text format.
       
   482       'format' => db_query_range('SELECT format FROM {filter_format}', 0, 1)->fetchField(),
       
   483       'vid' => $this->vocabulary->vid,
       
   484       'vocabulary_machine_name' => $vocabulary->machine_name,
       
   485     );
       
   486     taxonomy_term_save($term);
       
   487 
       
   488     $this->term = $term;
       
   489 
       
   490     // Set up a field and instance.
       
   491     $this->field_name = drupal_strtolower($this->randomName());
       
   492     $this->field = array(
       
   493       'field_name' => $this->field_name,
       
   494       'type' => 'taxonomy_term_reference',
       
   495       'settings' => array(
       
   496         'allowed_values' => array(
       
   497           array(
       
   498             'vocabulary' => $this->vocabulary->machine_name,
       
   499             'parent' => '0',
       
   500           ),
       
   501         ),
       
   502       )
       
   503     );
       
   504 
       
   505     field_create_field($this->field);
       
   506     $this->instance = array(
       
   507       'field_name' => $this->field_name,
       
   508       'entity_type' => 'node',
       
   509       'bundle' => 'page',
       
   510       'widget' => array(
       
   511         'type' => 'options_select',
       
   512       ),
       
   513       // Hide on full display but render on teaser.
       
   514       'display' => array(
       
   515         'default' => array(
       
   516           'type' => 'hidden',
       
   517         ),
       
   518         'teaser' => array(
       
   519           'type' => 'taxonomy_term_reference_link',
       
   520         ),
       
   521       ),
       
   522     );
       
   523     field_create_instance($this->instance);
       
   524   }
       
   525 
       
   526   /**
       
   527    * Checks the node preview functionality.
       
   528    */
       
   529   function testPagePreview() {
       
   530     $langcode = LANGUAGE_NONE;
       
   531     $title_key = "title";
       
   532     $body_key = "body[$langcode][0][value]";
       
   533     $term_key = "{$this->field_name}[$langcode]";
       
   534 
       
   535     // Fill in node creation form and preview node.
       
   536     $edit = array();
       
   537     $edit[$title_key] = $this->randomName(8);
       
   538     $edit[$body_key] = $this->randomName(16);
       
   539     $edit[$term_key] = $this->term->tid;
       
   540     $this->drupalPost('node/add/page', $edit, t('Preview'));
       
   541 
       
   542     // Check that the preview is displaying the title, body, and term.
       
   543     $this->assertTitle(t('Preview | Drupal'), 'Basic page title is preview.');
       
   544     $this->assertText($edit[$title_key], 'Title displayed.');
       
   545     $this->assertText($edit[$body_key], 'Body displayed.');
       
   546     $this->assertText($this->term->name, 'Term displayed.');
       
   547 
       
   548     // Check that the title, body, and term fields are displayed with the
       
   549     // correct values.
       
   550     $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
       
   551     $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
       
   552     $this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
       
   553   }
       
   554 
       
   555   /**
       
   556    * Checks the node preview functionality, when using revisions.
       
   557    */
       
   558   function testPagePreviewWithRevisions() {
       
   559     $langcode = LANGUAGE_NONE;
       
   560     $title_key = "title";
       
   561     $body_key = "body[$langcode][0][value]";
       
   562     $term_key = "{$this->field_name}[$langcode]";
       
   563     // Force revision on "Basic page" content.
       
   564     variable_set('node_options_page', array('status', 'revision'));
       
   565 
       
   566     // Fill in node creation form and preview node.
       
   567     $edit = array();
       
   568     $edit[$title_key] = $this->randomName(8);
       
   569     $edit[$body_key] = $this->randomName(16);
       
   570     $edit[$term_key] = $this->term->tid;
       
   571     $edit['log'] = $this->randomName(32);
       
   572     $this->drupalPost('node/add/page', $edit, t('Preview'));
       
   573 
       
   574     // Check that the preview is displaying the title, body, and term.
       
   575     $this->assertTitle(t('Preview | Drupal'), 'Basic page title is preview.');
       
   576     $this->assertText($edit[$title_key], 'Title displayed.');
       
   577     $this->assertText($edit[$body_key], 'Body displayed.');
       
   578     $this->assertText($this->term->name, 'Term displayed.');
       
   579 
       
   580     // Check that the title, body, and term fields are displayed with the
       
   581     // correct values.
       
   582     $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
       
   583     $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
       
   584     $this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
       
   585 
       
   586     // Check that the log field has the correct value.
       
   587     $this->assertFieldByName('log', $edit['log'], 'Log field displayed.');
       
   588   }
       
   589 }
       
   590 
       
   591 /**
       
   592  * Tests creating and saving a node.
       
   593  */
       
   594 class NodeCreationTestCase extends DrupalWebTestCase {
       
   595   public static function getInfo() {
       
   596     return array(
       
   597       'name' => 'Node creation',
       
   598       'description' => 'Create a node and test saving it.',
       
   599       'group' => 'Node',
       
   600     );
       
   601   }
       
   602 
       
   603   function setUp() {
       
   604     // Enable dummy module that implements hook_node_insert for exceptions.
       
   605     parent::setUp('node_test_exception');
       
   606 
       
   607     $web_user = $this->drupalCreateUser(array('create page content', 'edit own page content'));
       
   608     $this->drupalLogin($web_user);
       
   609   }
       
   610 
       
   611   /**
       
   612    * Creates a "Basic page" node and verifies its consistency in the database.
       
   613    */
       
   614   function testNodeCreation() {
       
   615     // Create a node.
       
   616     $edit = array();
       
   617     $langcode = LANGUAGE_NONE;
       
   618     $edit["title"] = $this->randomName(8);
       
   619     $edit["body[$langcode][0][value]"] = $this->randomName(16);
       
   620     $this->drupalPost('node/add/page', $edit, t('Save'));
       
   621 
       
   622     // Check that the Basic page has been created.
       
   623     $this->assertRaw(t('!post %title has been created.', array('!post' => 'Basic page', '%title' => $edit["title"])), 'Basic page created.');
       
   624 
       
   625     // Check that the node exists in the database.
       
   626     $node = $this->drupalGetNodeByTitle($edit["title"]);
       
   627     $this->assertTrue($node, 'Node found in database.');
       
   628   }
       
   629 
       
   630   /**
       
   631    * Verifies that a transaction rolls back the failed creation.
       
   632    */
       
   633   function testFailedPageCreation() {
       
   634     // Create a node.
       
   635     $edit = array(
       
   636       'uid'      => $this->loggedInUser->uid,
       
   637       'name'     => $this->loggedInUser->name,
       
   638       'type'     => 'page',
       
   639       'language' => LANGUAGE_NONE,
       
   640       'title'    => 'testing_transaction_exception',
       
   641     );
       
   642 
       
   643     try {
       
   644       // An exception is generated by node_test_exception_node_insert() if the
       
   645       // title is 'testing_transaction_exception'.
       
   646       node_save((object) $edit);
       
   647       $this->fail(t('Expected exception has not been thrown.'));
       
   648     }
       
   649     catch (Exception $e) {
       
   650       $this->pass(t('Expected exception has been thrown.'));
       
   651     }
       
   652 
       
   653     if (Database::getConnection()->supportsTransactions()) {
       
   654       // Check that the node does not exist in the database.
       
   655       $node = $this->drupalGetNodeByTitle($edit['title']);
       
   656       $this->assertFalse($node, 'Transactions supported, and node not found in database.');
       
   657     }
       
   658     else {
       
   659       // Check that the node exists in the database.
       
   660       $node = $this->drupalGetNodeByTitle($edit['title']);
       
   661       $this->assertTrue($node, 'Transactions not supported, and node found in database.');
       
   662 
       
   663       // Check that the failed rollback was logged.
       
   664       $records = db_query("SELECT wid FROM {watchdog} WHERE message LIKE 'Explicit rollback failed%'")->fetchAll();
       
   665       $this->assertTrue(count($records) > 0, 'Transactions not supported, and rollback error logged to watchdog.');
       
   666     }
       
   667 
       
   668     // Check that the rollback error was logged.
       
   669     $records = db_query("SELECT wid FROM {watchdog} WHERE variables LIKE '%Test exception for rollback.%'")->fetchAll();
       
   670     $this->assertTrue(count($records) > 0, 'Rollback explanatory error logged to watchdog.');
       
   671   }
       
   672 
       
   673   /**
       
   674    * Create an unpublished node and confirm correct redirect behavior.
       
   675    */
       
   676   function testUnpublishedNodeCreation() {
       
   677     // Set "Basic page" content type to be unpublished by default.
       
   678     variable_set('node_options_page', array());
       
   679     // Set the front page to the default "node" page.
       
   680     variable_set('site_frontpage', 'node');
       
   681 
       
   682     // Create a node.
       
   683     $edit = array();
       
   684     $edit["title"] = $this->randomName(8);
       
   685     $edit["body[" . LANGUAGE_NONE . "][0][value]"] = $this->randomName(16);
       
   686     $this->drupalPost('node/add/page', $edit, t('Save'));
       
   687 
       
   688     // Check that the user was redirected to the home page.
       
   689     $this->assertText(t('Welcome to Drupal'), t('The user is redirected to the home page.'));
       
   690   }
       
   691 }
       
   692 
       
   693 /**
       
   694  * Tests the functionality of node entity edit permissions.
       
   695  */
       
   696 class PageViewTestCase extends DrupalWebTestCase {
       
   697   public static function getInfo() {
       
   698     return array(
       
   699       'name' => 'Node edit permissions',
       
   700       'description' => 'Create a node and test edit permissions.',
       
   701       'group' => 'Node',
       
   702     );
       
   703   }
       
   704 
       
   705   /**
       
   706    * Tests an anonymous and unpermissioned user attempting to edit the node.
       
   707    */
       
   708   function testPageView() {
       
   709     // Create a node to view.
       
   710     $node = $this->drupalCreateNode();
       
   711     $this->assertTrue(node_load($node->nid), 'Node created.');
       
   712 
       
   713     // Try to edit with anonymous user.
       
   714     $html = $this->drupalGet("node/$node->nid/edit");
       
   715     $this->assertResponse(403);
       
   716 
       
   717     // Create a user without permission to edit node.
       
   718     $web_user = $this->drupalCreateUser(array('access content'));
       
   719     $this->drupalLogin($web_user);
       
   720 
       
   721     // Attempt to access edit page.
       
   722     $this->drupalGet("node/$node->nid/edit");
       
   723     $this->assertResponse(403);
       
   724 
       
   725     // Create user with permission to edit node.
       
   726     $web_user = $this->drupalCreateUser(array('bypass node access'));
       
   727     $this->drupalLogin($web_user);
       
   728 
       
   729     // Attempt to access edit page.
       
   730     $this->drupalGet("node/$node->nid/edit");
       
   731     $this->assertResponse(200);
       
   732   }
       
   733 }
       
   734 
       
   735 /**
       
   736  * Tests the summary length functionality.
       
   737  */
       
   738 class SummaryLengthTestCase extends DrupalWebTestCase {
       
   739   public static function getInfo() {
       
   740     return array(
       
   741       'name' => 'Summary length',
       
   742       'description' => 'Test summary length.',
       
   743       'group' => 'Node',
       
   744     );
       
   745   }
       
   746 
       
   747   /**
       
   748    * Tests the node summary length functionality.
       
   749    */
       
   750   function testSummaryLength() {
       
   751     // Create a node to view.
       
   752     $settings = array(
       
   753       'body' => array(LANGUAGE_NONE => array(array('value' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vitae arcu at leo cursus laoreet. Curabitur dui tortor, adipiscing malesuada tempor in, bibendum ac diam. Cras non tellus a libero pellentesque condimentum. What is a Drupalism? Suspendisse ac lacus libero. Ut non est vel nisl faucibus interdum nec sed leo. Pellentesque sem risus, vulputate eu semper eget, auctor in libero. Ut fermentum est vitae metus convallis scelerisque. Phasellus pellentesque rhoncus tellus, eu dignissim purus posuere id. Quisque eu fringilla ligula. Morbi ullamcorper, lorem et mattis egestas, tortor neque pretium velit, eget eleifend odio turpis eu purus. Donec vitae metus quis leo pretium tincidunt a pulvinar sem. Morbi adipiscing laoreet mauris vel placerat. Nullam elementum, nisl sit amet scelerisque malesuada, dolor nunc hendrerit quam, eu ultrices erat est in orci. Curabitur feugiat egestas nisl sed accumsan.'))),
       
   754       'promote' => 1,
       
   755     );
       
   756     $node = $this->drupalCreateNode($settings);
       
   757     $this->assertTrue(node_load($node->nid), 'Node created.');
       
   758 
       
   759     // Create user with permission to view the node.
       
   760     $web_user = $this->drupalCreateUser(array('access content', 'administer content types'));
       
   761     $this->drupalLogin($web_user);
       
   762 
       
   763     // Attempt to access the front page.
       
   764     $this->drupalGet("node");
       
   765     // The node teaser when it has 600 characters in length
       
   766     $expected = 'What is a Drupalism?';
       
   767     $this->assertRaw($expected, 'Check that the summary is 600 characters in length', 'Node');
       
   768 
       
   769     // Change the teaser length for "Basic page" content type.
       
   770     $instance = field_info_instance('node', 'body', $node->type);
       
   771     $instance['display']['teaser']['settings']['trim_length'] = 200;
       
   772     field_update_instance($instance);
       
   773 
       
   774     // Attempt to access the front page again and check if the summary is now only 200 characters in length.
       
   775     $this->drupalGet("node");
       
   776     $this->assertNoRaw($expected, 'Check that the summary is not longer than 200 characters', 'Node');
       
   777   }
       
   778 }
       
   779 
       
   780 /**
       
   781  * Tests XSS functionality with a node entity.
       
   782  */
       
   783 class NodeTitleXSSTestCase extends DrupalWebTestCase {
       
   784   public static function getInfo() {
       
   785     return array(
       
   786       'name' => 'Node title XSS filtering',
       
   787       'description' => 'Create a node with dangerous tags in its title and test that they are escaped.',
       
   788       'group' => 'Node',
       
   789     );
       
   790   }
       
   791 
       
   792   /**
       
   793    * Tests XSS functionality with a node entity.
       
   794    */
       
   795   function testNodeTitleXSS() {
       
   796     // Prepare a user to do the stuff.
       
   797     $web_user = $this->drupalCreateUser(array('create page content', 'edit any page content'));
       
   798     $this->drupalLogin($web_user);
       
   799 
       
   800     $xss = '<script>alert("xss")</script>';
       
   801     $title = $xss . $this->randomName();
       
   802     $edit = array("title" => $title);
       
   803 
       
   804     $this->drupalPost('node/add/page', $edit, t('Preview'));
       
   805     $this->assertNoRaw($xss, 'Harmful tags are escaped when previewing a node.');
       
   806 
       
   807     $settings = array('title' => $title);
       
   808     $node = $this->drupalCreateNode($settings);
       
   809 
       
   810     $this->drupalGet('node/' . $node->nid);
       
   811     // assertTitle() decodes HTML-entities inside the <title> element.
       
   812     $this->assertTitle($edit["title"] . ' | Drupal', 'Title is diplayed when viewing a node.');
       
   813     $this->assertNoRaw($xss, 'Harmful tags are escaped when viewing a node.');
       
   814 
       
   815     $this->drupalGet('node/' . $node->nid . '/edit');
       
   816     $this->assertNoRaw($xss, 'Harmful tags are escaped when editing a node.');
       
   817   }
       
   818 }
       
   819 
       
   820 /**
       
   821  * Tests the availability of the syndicate block.
       
   822  */
       
   823 class NodeBlockTestCase extends DrupalWebTestCase {
       
   824   public static function getInfo() {
       
   825     return array(
       
   826       'name' => 'Block availability',
       
   827       'description' => 'Check if the syndicate block is available.',
       
   828       'group' => 'Node',
       
   829     );
       
   830   }
       
   831 
       
   832   function setUp() {
       
   833     parent::setUp();
       
   834 
       
   835     // Create and login user
       
   836     $admin_user = $this->drupalCreateUser(array('administer blocks'));
       
   837     $this->drupalLogin($admin_user);
       
   838   }
       
   839 
       
   840   /**
       
   841    * Tests that the "Syndicate" block is shown when enabled.
       
   842    */
       
   843   function testSyndicateBlock() {
       
   844     // Set block title to confirm that the interface is available.
       
   845     $this->drupalPost('admin/structure/block/manage/node/syndicate/configure', array('title' => $this->randomName(8)), t('Save block'));
       
   846     $this->assertText(t('The block configuration has been saved.'), 'Block configuration set.');
       
   847 
       
   848     // Set the block to a region to confirm block is available.
       
   849     $edit = array();
       
   850     $edit['blocks[node_syndicate][region]'] = 'footer';
       
   851     $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
       
   852     $this->assertText(t('The block settings have been updated.'), 'Block successfully move to footer region.');
       
   853   }
       
   854 }
       
   855 
       
   856 /**
       
   857  * Checks that the post information displays when enabled for a content type.
       
   858  */
       
   859 class NodePostSettingsTestCase extends DrupalWebTestCase {
       
   860   public static function getInfo() {
       
   861     return array(
       
   862       'name' => 'Node post information display',
       
   863       'description' => 'Check that the post information (submitted by Username on date) text displays appropriately.',
       
   864       'group' => 'Node',
       
   865     );
       
   866   }
       
   867 
       
   868   function setUp() {
       
   869     parent::setUp();
       
   870 
       
   871     $web_user = $this->drupalCreateUser(array('create page content', 'administer content types', 'access user profiles'));
       
   872     $this->drupalLogin($web_user);
       
   873   }
       
   874 
       
   875   /**
       
   876    * Confirms "Basic page" content type and post information is on a new node.
       
   877    */
       
   878   function testPagePostInfo() {
       
   879 
       
   880     // Set "Basic page" content type to display post information.
       
   881     $edit = array();
       
   882     $edit['node_submitted'] = TRUE;
       
   883     $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
       
   884 
       
   885     // Create a node.
       
   886     $edit = array();
       
   887     $langcode = LANGUAGE_NONE;
       
   888     $edit["title"] = $this->randomName(8);
       
   889     $edit["body[$langcode][0][value]"] = $this->randomName(16);
       
   890     $this->drupalPost('node/add/page', $edit, t('Save'));
       
   891 
       
   892     // Check that the post information is displayed.
       
   893     $node = $this->drupalGetNodeByTitle($edit["title"]);
       
   894     $elements = $this->xpath('//div[contains(@class,:class)]', array(':class' => 'submitted'));
       
   895     $this->assertEqual(count($elements), 1, 'Post information is displayed.');
       
   896   }
       
   897 
       
   898   /**
       
   899    * Confirms absence of post information on a new node.
       
   900    */
       
   901   function testPageNotPostInfo() {
       
   902 
       
   903     // Set "Basic page" content type to display post information.
       
   904     $edit = array();
       
   905     $edit['node_submitted'] = FALSE;
       
   906     $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
       
   907 
       
   908     // Create a node.
       
   909     $edit = array();
       
   910     $langcode = LANGUAGE_NONE;
       
   911     $edit["title"] = $this->randomName(8);
       
   912     $edit["body[$langcode][0][value]"] = $this->randomName(16);
       
   913     $this->drupalPost('node/add/page', $edit, t('Save'));
       
   914 
       
   915     // Check that the post information is displayed.
       
   916     $node = $this->drupalGetNodeByTitle($edit["title"]);
       
   917     $this->assertNoRaw('<span class="submitted">', 'Post information is not displayed.');
       
   918   }
       
   919 }
       
   920 
       
   921 /**
       
   922  * Ensures that data added to nodes by other modules appears in RSS feeds.
       
   923  *
       
   924  * Create a node, enable the node_test module to ensure that extra data is
       
   925  * added to the node->content array, then verify that the data appears on the
       
   926  * sitewide RSS feed at rss.xml.
       
   927  */
       
   928 class NodeRSSContentTestCase extends DrupalWebTestCase {
       
   929   public static function getInfo() {
       
   930     return array(
       
   931       'name' => 'Node RSS Content',
       
   932       'description' => 'Ensure that data added to nodes by other modules appears in RSS feeds.',
       
   933       'group' => 'Node',
       
   934     );
       
   935   }
       
   936 
       
   937   function setUp() {
       
   938     // Enable dummy module that implements hook_node_view.
       
   939     parent::setUp('node_test');
       
   940 
       
   941     // Use bypass node access permission here, because the test class uses
       
   942     // hook_grants_alter() to deny access to everyone on node_access
       
   943     // queries.
       
   944     $user = $this->drupalCreateUser(array('bypass node access', 'access content', 'create article content'));
       
   945     $this->drupalLogin($user);
       
   946   }
       
   947 
       
   948   /**
       
   949    * Ensures that a new node includes the custom data when added to an RSS feed.
       
   950    */
       
   951   function testNodeRSSContent() {
       
   952     // Create a node.
       
   953     $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
       
   954 
       
   955     $this->drupalGet('rss.xml');
       
   956 
       
   957     // Check that content added in 'rss' view mode appear in RSS feed.
       
   958     $rss_only_content = t('Extra data that should appear only in the RSS feed for node !nid.', array('!nid' => $node->nid));
       
   959     $this->assertText($rss_only_content, 'Node content designated for RSS appear in RSS feed.');
       
   960 
       
   961     // Check that content added in view modes other than 'rss' doesn't
       
   962     // appear in RSS feed.
       
   963     $non_rss_content = t('Extra data that should appear everywhere except the RSS feed for node !nid.', array('!nid' => $node->nid));
       
   964     $this->assertNoText($non_rss_content, 'Node content not designed for RSS doesn\'t appear in RSS feed.');
       
   965 
       
   966     // Check that extra RSS elements and namespaces are added to RSS feed.
       
   967     $test_element = array(
       
   968       'key' => 'testElement',
       
   969       'value' => t('Value of testElement RSS element for node !nid.', array('!nid' => $node->nid)),
       
   970     );
       
   971     $test_ns = 'xmlns:drupaltest="http://example.com/test-namespace"';
       
   972     $this->assertRaw(format_xml_elements(array($test_element)), 'Extra RSS elements appear in RSS feed.');
       
   973     $this->assertRaw($test_ns, 'Extra namespaces appear in RSS feed.');
       
   974 
       
   975     // Check that content added in 'rss' view mode doesn't appear when
       
   976     // viewing node.
       
   977     $this->drupalGet("node/$node->nid");
       
   978     $this->assertNoText($rss_only_content, 'Node content designed for RSS doesn\'t appear when viewing node.');
       
   979 
       
   980     // Check that the node feed page does not try to interpret additional path
       
   981     // components as arguments for node_feed() and returns default content.
       
   982     $this->drupalGet('rss.xml/' . $this->randomName() . '/' . $this->randomName());
       
   983     $this->assertText($rss_only_content, 'Ignore page arguments when delivering rss.xml.');
       
   984   }
       
   985 }
       
   986 
       
   987 /**
       
   988  * Tests basic node_access functionality.
       
   989  *
       
   990  * Note that hook_node_access_records() is covered in another test class.
       
   991  *
       
   992  * @todo Cover hook_node_access in a separate test class.
       
   993  */
       
   994 class NodeAccessTestCase extends DrupalWebTestCase {
       
   995   public static function getInfo() {
       
   996     return array(
       
   997       'name' => 'Node access',
       
   998       'description' => 'Test node_access function',
       
   999       'group' => 'Node',
       
  1000     );
       
  1001   }
       
  1002 
       
  1003   /**
       
  1004    * Asserts node_access() correctly grants or denies access.
       
  1005    */
       
  1006   function assertNodeAccess($ops, $node, $account) {
       
  1007     foreach ($ops as $op => $result) {
       
  1008       $msg = format_string("node_access returns @result with operation '@op'.", array('@result' => $result ? 'true' : 'false', '@op' => $op));
       
  1009       $this->assertEqual($result, node_access($op, $node, $account), $msg);
       
  1010     }
       
  1011   }
       
  1012 
       
  1013   function setUp() {
       
  1014     parent::setUp();
       
  1015     // Clear permissions for authenticated users.
       
  1016     db_delete('role_permission')
       
  1017       ->condition('rid', DRUPAL_AUTHENTICATED_RID)
       
  1018       ->execute();
       
  1019   }
       
  1020 
       
  1021   /**
       
  1022    * Runs basic tests for node_access function.
       
  1023    */
       
  1024   function testNodeAccess() {
       
  1025     // Ensures user without 'access content' permission can do nothing.
       
  1026     $web_user1 = $this->drupalCreateUser(array('create page content', 'edit any page content', 'delete any page content'));
       
  1027     $node1 = $this->drupalCreateNode(array('type' => 'page'));
       
  1028     $this->assertNodeAccess(array('create' => FALSE), 'page', $web_user1);
       
  1029     $this->assertNodeAccess(array('view' => FALSE, 'update' => FALSE, 'delete' => FALSE), $node1, $web_user1);
       
  1030 
       
  1031     // Ensures user with 'bypass node access' permission can do everything.
       
  1032     $web_user2 = $this->drupalCreateUser(array('bypass node access'));
       
  1033     $node2 = $this->drupalCreateNode(array('type' => 'page'));
       
  1034     $this->assertNodeAccess(array('create' => TRUE), 'page', $web_user2);
       
  1035     $this->assertNodeAccess(array('view' => TRUE, 'update' => TRUE, 'delete' => TRUE), $node2, $web_user2);
       
  1036 
       
  1037     // User cannot 'view own unpublished content'.
       
  1038     $web_user3 = $this->drupalCreateUser(array('access content'));
       
  1039     $node3 = $this->drupalCreateNode(array('status' => 0, 'uid' => $web_user3->uid));
       
  1040     $this->assertNodeAccess(array('view' => FALSE), $node3, $web_user3);
       
  1041 
       
  1042     // User cannot create content without permission.
       
  1043     $this->assertNodeAccess(array('create' => FALSE), 'page', $web_user3);
       
  1044 
       
  1045     // User can 'view own unpublished content', but another user cannot.
       
  1046     $web_user4 = $this->drupalCreateUser(array('access content', 'view own unpublished content'));
       
  1047     $web_user5 = $this->drupalCreateUser(array('access content', 'view own unpublished content'));
       
  1048     $node4 = $this->drupalCreateNode(array('status' => 0, 'uid' => $web_user4->uid));
       
  1049     $this->assertNodeAccess(array('view' => TRUE, 'update' => FALSE), $node4, $web_user4);
       
  1050     $this->assertNodeAccess(array('view' => FALSE), $node4, $web_user5);
       
  1051 
       
  1052     // Tests the default access provided for a published node.
       
  1053     $node5 = $this->drupalCreateNode();
       
  1054     $this->assertNodeAccess(array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE), $node5, $web_user3);
       
  1055   }
       
  1056 }
       
  1057 
       
  1058 /**
       
  1059  * Tests hook_node_access_records() functionality.
       
  1060  */
       
  1061 class NodeAccessRecordsTestCase extends DrupalWebTestCase {
       
  1062   public static function getInfo() {
       
  1063     return array(
       
  1064       'name' => 'Node access records',
       
  1065       'description' => 'Test hook_node_access_records when acquiring grants.',
       
  1066       'group' => 'Node',
       
  1067     );
       
  1068   }
       
  1069 
       
  1070   function setUp() {
       
  1071     // Enable dummy module that implements hook_node_grants(),
       
  1072     // hook_node_access_records(), hook_node_grants_alter() and
       
  1073     // hook_node_access_records_alter().
       
  1074     parent::setUp('node_test');
       
  1075   }
       
  1076 
       
  1077   /**
       
  1078    * Creates a node and tests the creation of node access rules.
       
  1079    */
       
  1080   function testNodeAccessRecords() {
       
  1081     // Create an article node.
       
  1082     $node1 = $this->drupalCreateNode(array('type' => 'article'));
       
  1083     $this->assertTrue(node_load($node1->nid), 'Article node created.');
       
  1084 
       
  1085     // Check to see if grants added by node_test_node_access_records made it in.
       
  1086     $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node1->nid))->fetchAll();
       
  1087     $this->assertEqual(count($records), 1, 'Returned the correct number of rows.');
       
  1088     $this->assertEqual($records[0]->realm, 'test_article_realm', 'Grant with article_realm acquired for node without alteration.');
       
  1089     $this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.');
       
  1090 
       
  1091     // Create an unpromoted "Basic page" node.
       
  1092     $node2 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0));
       
  1093     $this->assertTrue(node_load($node2->nid), 'Unpromoted basic page node created.');
       
  1094 
       
  1095     // Check to see if grants added by node_test_node_access_records made it in.
       
  1096     $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node2->nid))->fetchAll();
       
  1097     $this->assertEqual(count($records), 1, 'Returned the correct number of rows.');
       
  1098     $this->assertEqual($records[0]->realm, 'test_page_realm', 'Grant with page_realm acquired for node without alteration.');
       
  1099     $this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.');
       
  1100 
       
  1101     // Create an unpromoted, unpublished "Basic page" node.
       
  1102     $node3 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0, 'status' => 0));
       
  1103     $this->assertTrue(node_load($node3->nid), 'Unpromoted, unpublished basic page node created.');
       
  1104 
       
  1105     // Check to see if grants added by node_test_node_access_records made it in.
       
  1106     $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node3->nid))->fetchAll();
       
  1107     $this->assertEqual(count($records), 1, 'Returned the correct number of rows.');
       
  1108     $this->assertEqual($records[0]->realm, 'test_page_realm', 'Grant with page_realm acquired for node without alteration.');
       
  1109     $this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.');
       
  1110 
       
  1111     // Create a promoted "Basic page" node.
       
  1112     $node4 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1));
       
  1113     $this->assertTrue(node_load($node4->nid), 'Promoted basic page node created.');
       
  1114 
       
  1115     // Check to see if grant added by node_test_node_access_records was altered
       
  1116     // by node_test_node_access_records_alter.
       
  1117     $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node4->nid))->fetchAll();
       
  1118     $this->assertEqual(count($records), 1, 'Returned the correct number of rows.');
       
  1119     $this->assertEqual($records[0]->realm, 'test_alter_realm', 'Altered grant with alter_realm acquired for node.');
       
  1120     $this->assertEqual($records[0]->gid, 2, 'Altered grant with gid = 2 acquired for node.');
       
  1121 
       
  1122     // Check to see if we can alter grants with hook_node_grants_alter().
       
  1123     $operations = array('view', 'update', 'delete');
       
  1124     // Create a user that is allowed to access content.
       
  1125     $web_user = $this->drupalCreateUser(array('access content'));
       
  1126     foreach ($operations as $op) {
       
  1127       $grants = node_test_node_grants($op, $web_user);
       
  1128       $altered_grants = $grants;
       
  1129       drupal_alter('node_grants', $altered_grants, $web_user, $op);
       
  1130       $this->assertNotEqual($grants, $altered_grants, format_string('Altered the %op grant for a user.', array('%op' => $op)));
       
  1131     }
       
  1132 
       
  1133     // Check that core does not grant access to an unpublished node when an
       
  1134     // empty $grants array is returned.
       
  1135     $node6 = $this->drupalCreateNode(array('status' => 0, 'disable_node_access' => TRUE));
       
  1136     $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node6->nid))->fetchAll();
       
  1137     $this->assertEqual(count($records), 0, 'Returned no records for unpublished node.');
       
  1138   }
       
  1139 }
       
  1140 
       
  1141 /**
       
  1142  * Tests for Node Access with a non-node base table.
       
  1143  */
       
  1144 class NodeAccessBaseTableTestCase extends DrupalWebTestCase {
       
  1145 
       
  1146   public static function getInfo() {
       
  1147     return array(
       
  1148       'name' => 'Node Access on any table',
       
  1149       'description' => 'Checks behavior of the node access subsystem if the base table is not node.',
       
  1150       'group' => 'Node',
       
  1151     );
       
  1152   }
       
  1153 
       
  1154   public function setUp() {
       
  1155     parent::setUp('node_access_test');
       
  1156     node_access_rebuild();
       
  1157     variable_set('node_access_test_private', TRUE);
       
  1158   }
       
  1159 
       
  1160   /**
       
  1161    * Tests the "private" node access functionality.
       
  1162    *
       
  1163    * - Create 2 users with "access content" and "create article" permissions.
       
  1164    * - Each user creates one private and one not private article.
       
  1165 
       
  1166    * - Test that each user can view the other user's non-private article.
       
  1167    * - Test that each user cannot view the other user's private article.
       
  1168    * - Test that each user finds only appropriate (non-private + own private)
       
  1169    *   in taxonomy listing.
       
  1170    * - Create another user with 'view any private content'.
       
  1171    * - Test that user 4 can view all content created above.
       
  1172    * - Test that user 4 can view all content on taxonomy listing.
       
  1173    */
       
  1174   function testNodeAccessBasic() {
       
  1175     $num_simple_users = 2;
       
  1176     $simple_users = array();
       
  1177 
       
  1178     // nodes keyed by uid and nid: $nodes[$uid][$nid] = $is_private;
       
  1179     $this->nodesByUser = array();
       
  1180     $titles = array(); // Titles keyed by nid
       
  1181     $private_nodes = array(); // Array of nids marked private.
       
  1182     for ($i = 0; $i < $num_simple_users; $i++) {
       
  1183       $simple_users[$i] = $this->drupalCreateUser(array('access content', 'create article content'));
       
  1184     }
       
  1185     foreach ($simple_users as $this->webUser) {
       
  1186       $this->drupalLogin($this->webUser);
       
  1187       foreach (array(0 => 'Public', 1 => 'Private') as $is_private => $type) {
       
  1188         $edit = array(
       
  1189           'title' => t('@private_public Article created by @user', array('@private_public' => $type, '@user' => $this->webUser->name)),
       
  1190         );
       
  1191         if ($is_private) {
       
  1192           $edit['private'] = TRUE;
       
  1193           $edit['body[und][0][value]'] = 'private node';
       
  1194           $edit['field_tags[und]'] = 'private';
       
  1195         }
       
  1196         else {
       
  1197           $edit['body[und][0][value]'] = 'public node';
       
  1198           $edit['field_tags[und]'] = 'public';
       
  1199         }
       
  1200 
       
  1201         $this->drupalPost('node/add/article', $edit, t('Save'));
       
  1202         $nid = db_query('SELECT nid FROM {node} WHERE title = :title', array(':title' => $edit['title']))->fetchField();
       
  1203         $private_status = db_query('SELECT private FROM {node_access_test} where nid = :nid', array(':nid' => $nid))->fetchField();
       
  1204         $this->assertTrue($is_private == $private_status, 'The private status of the node was properly set in the node_access_test table.');
       
  1205         if ($is_private) {
       
  1206           $private_nodes[] = $nid;
       
  1207         }
       
  1208         $titles[$nid] = $edit['title'];
       
  1209         $this->nodesByUser[$this->webUser->uid][$nid] = $is_private;
       
  1210       }
       
  1211     }
       
  1212     $this->publicTid = db_query('SELECT tid FROM {taxonomy_term_data} WHERE name = :name', array(':name' => 'public'))->fetchField();
       
  1213     $this->privateTid = db_query('SELECT tid FROM {taxonomy_term_data} WHERE name = :name', array(':name' => 'private'))->fetchField();
       
  1214     $this->assertTrue($this->publicTid, 'Public tid was found');
       
  1215     $this->assertTrue($this->privateTid, 'Private tid was found');
       
  1216     foreach ($simple_users as $this->webUser) {
       
  1217       $this->drupalLogin($this->webUser);
       
  1218       // Check own nodes to see that all are readable.
       
  1219       foreach ($this->nodesByUser as $uid => $data) {
       
  1220         foreach ($data as $nid => $is_private) {
       
  1221           $this->drupalGet('node/' . $nid);
       
  1222           if ($is_private) {
       
  1223             $should_be_visible = $uid == $this->webUser->uid;
       
  1224           }
       
  1225           else {
       
  1226             $should_be_visible = TRUE;
       
  1227           }
       
  1228           $this->assertResponse($should_be_visible ? 200 : 403, strtr('A %private node by user %uid is %visible for user %current_uid.', array(
       
  1229             '%private' => $is_private ? 'private' : 'public',
       
  1230             '%uid' => $uid,
       
  1231             '%visible' => $should_be_visible ? 'visible' : 'not visible',
       
  1232             '%current_uid' => $this->webUser->uid,
       
  1233           )));
       
  1234         }
       
  1235       }
       
  1236 
       
  1237       // Check to see that the correct nodes are shown on taxonomy/private
       
  1238       // and taxonomy/public.
       
  1239       $this->assertTaxonomyPage(FALSE);
       
  1240     }
       
  1241 
       
  1242     // Now test that a user with 'access any private content' can view content.
       
  1243     $access_user = $this->drupalCreateUser(array('access content', 'create article content', 'node test view', 'search content'));
       
  1244     $this->drupalLogin($access_user);
       
  1245 
       
  1246     foreach ($this->nodesByUser as $uid => $private_status) {
       
  1247       foreach ($private_status as $nid => $is_private) {
       
  1248         $this->drupalGet('node/' . $nid);
       
  1249         $this->assertResponse(200);
       
  1250       }
       
  1251     }
       
  1252 
       
  1253     // This user should be able to see all of the nodes on the relevant
       
  1254     // taxonomy pages.
       
  1255     $this->assertTaxonomyPage(TRUE);
       
  1256   }
       
  1257 
       
  1258   /**
       
  1259    * Checks taxonomy/term listings to ensure only accessible nodes are listed.
       
  1260    *
       
  1261    * @param $is_admin
       
  1262    *   A boolean indicating whether the current user is an administrator. If
       
  1263    *   TRUE, all nodes should be listed. If FALSE, only public nodes and the
       
  1264    *   user's own private nodes should be listed.
       
  1265    */
       
  1266   protected function assertTaxonomyPage($is_admin) {
       
  1267     foreach (array($this->publicTid, $this->privateTid) as $tid_is_private => $tid) {
       
  1268       $this->drupalGet("taxonomy/term/$tid");
       
  1269       $this->nids_visible = array();
       
  1270       foreach ($this->xpath("//a[text()='Read more']") as $link) {
       
  1271         $this->assertTrue(preg_match('|node/(\d+)$|', (string) $link['href'], $matches), 'Read more points to a node');
       
  1272         $this->nids_visible[$matches[1]] = TRUE;
       
  1273       }
       
  1274       foreach ($this->nodesByUser as $uid => $data) {
       
  1275         foreach ($data as $nid => $is_private) {
       
  1276           // Private nodes should be visible on the private term page,
       
  1277           // public nodes should be visible on the public term page.
       
  1278           $should_be_visible = $tid_is_private == $is_private;
       
  1279           // Non-administrators can only see their own nodes on the private
       
  1280           // term page.
       
  1281           if (!$is_admin && $tid_is_private) {
       
  1282             $should_be_visible = $should_be_visible && $uid == $this->webUser->uid;
       
  1283           }
       
  1284           $this->assertIdentical(isset($this->nids_visible[$nid]), $should_be_visible, strtr('A %private node by user %uid is %visible for user %current_uid on the %tid_is_private page.', array(
       
  1285             '%private' => $is_private ? 'private' : 'public',
       
  1286             '%uid' => $uid,
       
  1287             '%visible' => isset($this->nids_visible[$nid]) ? 'visible' : 'not visible',
       
  1288             '%current_uid' => $this->webUser->uid,
       
  1289             '%tid_is_private' => $tid_is_private ? 'private' : 'public',
       
  1290           )));
       
  1291         }
       
  1292       }
       
  1293     }
       
  1294   }
       
  1295 }
       
  1296 
       
  1297 /**
       
  1298  * Tests node save related functionality, including import-save.
       
  1299  */
       
  1300 class NodeSaveTestCase extends DrupalWebTestCase {
       
  1301 
       
  1302   public static function getInfo() {
       
  1303     return array(
       
  1304       'name' => 'Node save',
       
  1305       'description' => 'Test node_save() for saving content.',
       
  1306       'group' => 'Node',
       
  1307     );
       
  1308   }
       
  1309 
       
  1310   function setUp() {
       
  1311     parent::setUp('node_test');
       
  1312     // Create a user that is allowed to post; we'll use this to test the submission.
       
  1313     $web_user = $this->drupalCreateUser(array('create article content'));
       
  1314     $this->drupalLogin($web_user);
       
  1315     $this->web_user = $web_user;
       
  1316   }
       
  1317 
       
  1318   /**
       
  1319    * Checks whether custom node IDs are saved properly during an import operation.
       
  1320    *
       
  1321    * Workflow:
       
  1322    *  - first create a piece of content
       
  1323    *  - save the content
       
  1324    *  - check if node exists
       
  1325    */
       
  1326   function testImport() {
       
  1327     // Node ID must be a number that is not in the database.
       
  1328     $max_nid = db_query('SELECT MAX(nid) FROM {node}')->fetchField();
       
  1329     $test_nid = $max_nid + mt_rand(1000, 1000000);
       
  1330     $title = $this->randomName(8);
       
  1331     $node = array(
       
  1332       'title' => $title,
       
  1333       'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32)))),
       
  1334       'uid' => $this->web_user->uid,
       
  1335       'type' => 'article',
       
  1336       'nid' => $test_nid,
       
  1337       'is_new' => TRUE,
       
  1338     );
       
  1339     $node = node_submit((object) $node);
       
  1340 
       
  1341     // Verify that node_submit did not overwrite the user ID.
       
  1342     $this->assertEqual($node->uid, $this->web_user->uid, 'Function node_submit() preserves user ID');
       
  1343 
       
  1344     node_save($node);
       
  1345     // Test the import.
       
  1346     $node_by_nid = node_load($test_nid);
       
  1347     $this->assertTrue($node_by_nid, 'Node load by node ID.');
       
  1348 
       
  1349     $node_by_title = $this->drupalGetNodeByTitle($title);
       
  1350     $this->assertTrue($node_by_title, 'Node load by node title.');
       
  1351   }
       
  1352 
       
  1353   /**
       
  1354    * Verifies accuracy of the "created" and "changed" timestamp functionality.
       
  1355    */
       
  1356   function testTimestamps() {
       
  1357     // Use the default timestamps.
       
  1358     $edit = array(
       
  1359       'uid' => $this->web_user->uid,
       
  1360       'type' => 'article',
       
  1361       'title' => $this->randomName(8),
       
  1362     );
       
  1363 
       
  1364     node_save((object) $edit);
       
  1365     $node = $this->drupalGetNodeByTitle($edit['title']);
       
  1366     $this->assertEqual($node->created, REQUEST_TIME, 'Creating a node sets default "created" timestamp.');
       
  1367     $this->assertEqual($node->changed, REQUEST_TIME, 'Creating a node sets default "changed" timestamp.');
       
  1368 
       
  1369     // Store the timestamps.
       
  1370     $created = $node->created;
       
  1371     $changed = $node->changed;
       
  1372 
       
  1373     node_save($node);
       
  1374     $node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
       
  1375     $this->assertEqual($node->created, $created, 'Updating a node preserves "created" timestamp.');
       
  1376 
       
  1377     // Programmatically set the timestamps using hook_node_presave.
       
  1378     $node->title = 'testing_node_presave';
       
  1379 
       
  1380     node_save($node);
       
  1381     $node = $this->drupalGetNodeByTitle('testing_node_presave', TRUE);
       
  1382     $this->assertEqual($node->created, 280299600, 'Saving a node uses "created" timestamp set in presave hook.');
       
  1383     $this->assertEqual($node->changed, 979534800, 'Saving a node uses "changed" timestamp set in presave hook.');
       
  1384 
       
  1385     // Programmatically set the timestamps on the node.
       
  1386     $edit = array(
       
  1387       'uid' => $this->web_user->uid,
       
  1388       'type' => 'article',
       
  1389       'title' => $this->randomName(8),
       
  1390       'created' => 280299600, // Sun, 19 Nov 1978 05:00:00 GMT
       
  1391       'changed' => 979534800, // Drupal 1.0 release.
       
  1392     );
       
  1393 
       
  1394     node_save((object) $edit);
       
  1395     $node = $this->drupalGetNodeByTitle($edit['title']);
       
  1396     $this->assertEqual($node->created, 280299600, 'Creating a node uses user-set "created" timestamp.');
       
  1397     $this->assertNotEqual($node->changed, 979534800, 'Creating a node doesn\'t use user-set "changed" timestamp.');
       
  1398 
       
  1399     // Update the timestamps.
       
  1400     $node->created = 979534800;
       
  1401     $node->changed = 280299600;
       
  1402 
       
  1403     node_save($node);
       
  1404     $node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
       
  1405     $this->assertEqual($node->created, 979534800, 'Updating a node uses user-set "created" timestamp.');
       
  1406     $this->assertNotEqual($node->changed, 280299600, 'Updating a node doesn\'t use user-set "changed" timestamp.');
       
  1407   }
       
  1408 
       
  1409   /**
       
  1410    * Tests determing changes in hook_node_presave() and verifies the static node
       
  1411    * load cache is cleared upon save.
       
  1412    */
       
  1413   function testDeterminingChanges() {
       
  1414     // Initial creation.
       
  1415     $node = (object) array(
       
  1416       'uid' => $this->web_user->uid,
       
  1417       'type' => 'article',
       
  1418       'title' => 'test_changes',
       
  1419     );
       
  1420     node_save($node);
       
  1421 
       
  1422     // Update the node without applying changes.
       
  1423     node_save($node);
       
  1424     $this->assertEqual($node->title, 'test_changes', 'No changes have been determined.');
       
  1425 
       
  1426     // Apply changes.
       
  1427     $node->title = 'updated';
       
  1428     node_save($node);
       
  1429 
       
  1430     // The hook implementations node_test_node_presave() and
       
  1431     // node_test_node_update() determine changes and change the title.
       
  1432     $this->assertEqual($node->title, 'updated_presave_update', 'Changes have been determined.');
       
  1433 
       
  1434     // Test the static node load cache to be cleared.
       
  1435     $node = node_load($node->nid);
       
  1436     $this->assertEqual($node->title, 'updated_presave', 'Static cache has been cleared.');
       
  1437   }
       
  1438 
       
  1439   /**
       
  1440    * Tests saving a node on node insert.
       
  1441    *
       
  1442    * This test ensures that a node has been fully saved when hook_node_insert()
       
  1443    * is invoked, so that the node can be saved again in a hook implementation
       
  1444    * without errors.
       
  1445    *
       
  1446    * @see node_test_node_insert()
       
  1447    */
       
  1448   function testNodeSaveOnInsert() {
       
  1449     // node_test_node_insert() triggers a save on insert if the title equals
       
  1450     // 'new'.
       
  1451     $node = $this->drupalCreateNode(array('title' => 'new'));
       
  1452     $this->assertEqual($node->title, 'Node ' . $node->nid, 'Node saved on node insert.');
       
  1453   }
       
  1454 }
       
  1455 
       
  1456 /**
       
  1457  * Tests related to node types.
       
  1458  */
       
  1459 class NodeTypeTestCase extends DrupalWebTestCase {
       
  1460   public static function getInfo() {
       
  1461     return array(
       
  1462       'name' => 'Node types',
       
  1463       'description' => 'Ensures that node type functions work correctly.',
       
  1464       'group' => 'Node',
       
  1465     );
       
  1466   }
       
  1467 
       
  1468   /**
       
  1469    * Ensures that node type functions (node_type_get_*) work correctly.
       
  1470    *
       
  1471    * Load available node types and validate the returned data.
       
  1472    */
       
  1473   function testNodeTypeGetFunctions() {
       
  1474     $node_types = node_type_get_types();
       
  1475     $node_names = node_type_get_names();
       
  1476 
       
  1477     $this->assertTrue(isset($node_types['article']), 'Node type article is available.');
       
  1478     $this->assertTrue(isset($node_types['page']), 'Node type basic page is available.');
       
  1479 
       
  1480     $this->assertEqual($node_types['article']->name, $node_names['article'], 'Correct node type base has been returned.');
       
  1481 
       
  1482     $this->assertEqual($node_types['article'], node_type_get_type('article'), 'Correct node type has been returned.');
       
  1483     $this->assertEqual($node_types['article']->name, node_type_get_name('article'), 'Correct node type name has been returned.');
       
  1484     $this->assertEqual($node_types['page']->base, node_type_get_base('page'), 'Correct node type base has been returned.');
       
  1485   }
       
  1486 
       
  1487   /**
       
  1488    * Tests creating a content type programmatically and via a form.
       
  1489    */
       
  1490   function testNodeTypeCreation() {
       
  1491     // Create a content type programmaticaly.
       
  1492     $type = $this->drupalCreateContentType();
       
  1493 
       
  1494     $type_exists = db_query('SELECT 1 FROM {node_type} WHERE type = :type', array(':type' => $type->type))->fetchField();
       
  1495     $this->assertTrue($type_exists, 'The new content type has been created in the database.');
       
  1496 
       
  1497     // Login a test user.
       
  1498     $web_user = $this->drupalCreateUser(array('create ' . $type->name . ' content'));
       
  1499     $this->drupalLogin($web_user);
       
  1500 
       
  1501     $this->drupalGet('node/add/' . str_replace('_', '-', $type->name));
       
  1502     $this->assertResponse(200, 'The new content type can be accessed at node/add.');
       
  1503 
       
  1504     // Create a content type via the user interface.
       
  1505     $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types'));
       
  1506     $this->drupalLogin($web_user);
       
  1507     $edit = array(
       
  1508       'name' => 'foo',
       
  1509       'title_label' => 'title for foo',
       
  1510       'type' => 'foo',
       
  1511     );
       
  1512     $this->drupalPost('admin/structure/types/add', $edit, t('Save content type'));
       
  1513     $type_exists = db_query('SELECT 1 FROM {node_type} WHERE type = :type', array(':type' => 'foo'))->fetchField();
       
  1514     $this->assertTrue($type_exists, 'The new content type has been created in the database.');
       
  1515   }
       
  1516 
       
  1517   /**
       
  1518    * Tests editing a node type using the UI.
       
  1519    */
       
  1520   function testNodeTypeEditing() {
       
  1521     $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer fields'));
       
  1522     $this->drupalLogin($web_user);
       
  1523 
       
  1524     $instance = field_info_instance('node', 'body', 'page');
       
  1525     $this->assertEqual($instance['label'], 'Body', 'Body field was found.');
       
  1526 
       
  1527     // Verify that title and body fields are displayed.
       
  1528     $this->drupalGet('node/add/page');
       
  1529     $this->assertRaw('Title', 'Title field was found.');
       
  1530     $this->assertRaw('Body', 'Body field was found.');
       
  1531 
       
  1532     // Rename the title field.
       
  1533     $edit = array(
       
  1534       'title_label' => 'Foo',
       
  1535     );
       
  1536     $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
       
  1537     // Refresh the field information for the rest of the test.
       
  1538     field_info_cache_clear();
       
  1539 
       
  1540     $this->drupalGet('node/add/page');
       
  1541     $this->assertRaw('Foo', 'New title label was displayed.');
       
  1542     $this->assertNoRaw('Title', 'Old title label was not displayed.');
       
  1543 
       
  1544     // Change the name, machine name and description.
       
  1545     $edit = array(
       
  1546       'name' => 'Bar',
       
  1547       'type' => 'bar',
       
  1548       'description' => 'Lorem ipsum.',
       
  1549     );
       
  1550     $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
       
  1551     field_info_cache_clear();
       
  1552 
       
  1553     $this->drupalGet('node/add');
       
  1554     $this->assertRaw('Bar', 'New name was displayed.');
       
  1555     $this->assertRaw('Lorem ipsum', 'New description was displayed.');
       
  1556     $this->clickLink('Bar');
       
  1557     $this->assertEqual(url('node/add/bar', array('absolute' => TRUE)), $this->getUrl(), 'New machine name was used in URL.');
       
  1558     $this->assertRaw('Foo', 'Title field was found.');
       
  1559     $this->assertRaw('Body', 'Body field was found.');
       
  1560 
       
  1561     // Remove the body field.
       
  1562     $this->drupalPost('admin/structure/types/manage/bar/fields/body/delete', NULL, t('Delete'));
       
  1563     // Resave the settings for this type.
       
  1564     $this->drupalPost('admin/structure/types/manage/bar', array(), t('Save content type'));
       
  1565     // Check that the body field doesn't exist.
       
  1566     $this->drupalGet('node/add/bar');
       
  1567     $this->assertNoRaw('Body', 'Body field was not found.');
       
  1568   }
       
  1569 
       
  1570   /**
       
  1571    * Tests that node_types_rebuild() correctly handles the 'disabled' flag.
       
  1572    */
       
  1573   function testNodeTypeStatus() {
       
  1574     // Enable all core node modules, and all types should be active.
       
  1575     module_enable(array('blog', 'book', 'poll'), FALSE);
       
  1576     node_types_rebuild();
       
  1577     $types = node_type_get_types();
       
  1578     foreach (array('blog', 'book', 'poll', 'article', 'page') as $type) {
       
  1579       $this->assertTrue(isset($types[$type]), format_string('%type is found in node types.', array('%type' => $type)));
       
  1580       $this->assertTrue(isset($types[$type]->disabled) && empty($types[$type]->disabled), format_string('%type type is enabled.', array('%type' => $type)));
       
  1581     }
       
  1582 
       
  1583     // Disable poll module and the respective type should be marked as disabled.
       
  1584     module_disable(array('poll'), FALSE);
       
  1585     node_types_rebuild();
       
  1586     $types = node_type_get_types();
       
  1587     $this->assertTrue(!empty($types['poll']->disabled), "Poll module's node type disabled.");
       
  1588     $this->assertTrue(isset($types['blog']) && empty($types['blog']->disabled), "Blog module's node type still active.");
       
  1589 
       
  1590     // Disable blog module and the respective type should be marked as disabled.
       
  1591     module_disable(array('blog'), FALSE);
       
  1592     node_types_rebuild();
       
  1593     $types = node_type_get_types();
       
  1594     $this->assertTrue(!empty($types['blog']->disabled), "Blog module's node type disabled.");
       
  1595     $this->assertTrue(!empty($types['poll']->disabled), "Poll module's node type still disabled.");
       
  1596 
       
  1597     // Disable book module and the respective type should still be active, since
       
  1598     // it is not provided by hook_node_info().
       
  1599     module_disable(array('book'), FALSE);
       
  1600     node_types_rebuild();
       
  1601     $types = node_type_get_types();
       
  1602     $this->assertTrue(isset($types['book']) && empty($types['book']->disabled), "Book module's node type still active.");
       
  1603     $this->assertTrue(!empty($types['blog']->disabled), "Blog module's node type still disabled.");
       
  1604     $this->assertTrue(!empty($types['poll']->disabled), "Poll module's node type still disabled.");
       
  1605     $this->assertTrue(isset($types['article']) && empty($types['article']->disabled), "Article node type still active.");
       
  1606     $this->assertTrue(isset($types['page']) && empty($types['page']->disabled), "Basic page node type still active.");
       
  1607 
       
  1608     // Re-enable the modules and verify that the types are active again.
       
  1609     module_enable(array('blog', 'book', 'poll'), FALSE);
       
  1610     node_types_rebuild();
       
  1611     $types = node_type_get_types();
       
  1612     foreach (array('blog', 'book', 'poll', 'article', 'page') as $type) {
       
  1613       $this->assertTrue(isset($types[$type]), format_string('%type is found in node types.', array('%type' => $type)));
       
  1614       $this->assertTrue(isset($types[$type]->disabled) && empty($types[$type]->disabled), format_string('%type type is enabled.', array('%type' => $type)));
       
  1615     }
       
  1616   }
       
  1617 }
       
  1618 
       
  1619 /**
       
  1620  * Test node type customizations persistence.
       
  1621  */
       
  1622 class NodeTypePersistenceTestCase extends DrupalWebTestCase {
       
  1623   public static function getInfo() {
       
  1624     return array(
       
  1625       'name' => 'Node type persist',
       
  1626       'description' => 'Ensures that node type customization survives module enabling and disabling.',
       
  1627       'group' => 'Node',
       
  1628     );
       
  1629   }
       
  1630 
       
  1631   /**
       
  1632    * Tests that node type customizations persist through disable and uninstall.
       
  1633    */
       
  1634   function testNodeTypeCustomizationPersistence() {
       
  1635     $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer modules'));
       
  1636     $this->drupalLogin($web_user);
       
  1637     $poll_key = 'modules[Core][poll][enable]';
       
  1638     $poll_enable = array($poll_key => "1");
       
  1639     $poll_disable = array($poll_key => FALSE);
       
  1640 
       
  1641     // Enable poll and verify that the node type is in the DB and is not
       
  1642     // disabled.
       
  1643     $this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
       
  1644     $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
       
  1645     $this->assertNotIdentical($disabled, FALSE, 'Poll node type found in the database');
       
  1646     $this->assertEqual($disabled, 0, 'Poll node type is not disabled');
       
  1647 
       
  1648     // Check that poll node type (uncustomized) shows up.
       
  1649     $this->drupalGet('node/add');
       
  1650     $this->assertText('poll', 'poll type is found on node/add');
       
  1651 
       
  1652     // Customize poll description.
       
  1653     $description = $this->randomName();
       
  1654     $edit = array('description' => $description);
       
  1655     $this->drupalPost('admin/structure/types/manage/poll', $edit, t('Save content type'));
       
  1656 
       
  1657     // Check that poll node type customization shows up.
       
  1658     $this->drupalGet('node/add');
       
  1659     $this->assertText($description, 'Customized description found');
       
  1660 
       
  1661     // Disable poll and check that the node type gets disabled.
       
  1662     $this->drupalPost('admin/modules', $poll_disable, t('Save configuration'));
       
  1663     $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
       
  1664     $this->assertEqual($disabled, 1, 'Poll node type is disabled');
       
  1665     $this->drupalGet('node/add');
       
  1666     $this->assertNoText('poll', 'poll type is not found on node/add');
       
  1667 
       
  1668     // Reenable poll and check that the customization survived the module
       
  1669     // disable.
       
  1670     $this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
       
  1671     $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
       
  1672     $this->assertNotIdentical($disabled, FALSE, 'Poll node type found in the database');
       
  1673     $this->assertEqual($disabled, 0, 'Poll node type is not disabled');
       
  1674     $this->drupalGet('node/add');
       
  1675     $this->assertText($description, 'Customized description found');
       
  1676 
       
  1677     // Disable and uninstall poll.
       
  1678     $this->drupalPost('admin/modules', $poll_disable, t('Save configuration'));
       
  1679     $edit = array('uninstall[poll]' => 'poll');
       
  1680     $this->drupalPost('admin/modules/uninstall', $edit, t('Uninstall'));
       
  1681     $this->drupalPost(NULL, array(), t('Uninstall'));
       
  1682     $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
       
  1683     $this->assertTrue($disabled, 'Poll node type is in the database and is disabled');
       
  1684     $this->drupalGet('node/add');
       
  1685     $this->assertNoText('poll', 'poll type is no longer found on node/add');
       
  1686 
       
  1687     // Reenable poll and check that the customization survived the module
       
  1688     // uninstall.
       
  1689     $this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
       
  1690     $this->drupalGet('node/add');
       
  1691     $this->assertText($description, 'Customized description is found even after uninstall and reenable.');
       
  1692   }
       
  1693 }
       
  1694 
       
  1695 /**
       
  1696  * Verifies the rebuild functionality for the node_access table.
       
  1697  */
       
  1698 class NodeAccessRebuildTestCase extends DrupalWebTestCase {
       
  1699   public static function getInfo() {
       
  1700     return array(
       
  1701       'name' => 'Node access rebuild',
       
  1702       'description' => 'Ensures that node access rebuild functions work correctly.',
       
  1703       'group' => 'Node',
       
  1704     );
       
  1705   }
       
  1706 
       
  1707   function setUp() {
       
  1708     parent::setUp();
       
  1709 
       
  1710     $web_user = $this->drupalCreateUser(array('administer site configuration', 'access administration pages', 'access site reports'));
       
  1711     $this->drupalLogin($web_user);
       
  1712     $this->web_user = $web_user;
       
  1713   }
       
  1714 
       
  1715   /**
       
  1716    * Tests rebuilding the node access permissions table.
       
  1717    */
       
  1718   function testNodeAccessRebuild() {
       
  1719     $this->drupalGet('admin/reports/status');
       
  1720     $this->clickLink(t('Rebuild permissions'));
       
  1721     $this->drupalPost(NULL, array(), t('Rebuild permissions'));
       
  1722     $this->assertText(t('Content permissions have been rebuilt.'));
       
  1723   }
       
  1724 }
       
  1725 
       
  1726 /**
       
  1727  * Tests node administration page functionality.
       
  1728  */
       
  1729 class NodeAdminTestCase extends DrupalWebTestCase {
       
  1730   public static function getInfo() {
       
  1731     return array(
       
  1732       'name' => 'Node administration',
       
  1733       'description' => 'Test node administration page functionality.',
       
  1734       'group' => 'Node',
       
  1735     );
       
  1736   }
       
  1737 
       
  1738   function setUp() {
       
  1739     parent::setUp();
       
  1740 
       
  1741     // Remove the "view own unpublished content" permission which is set
       
  1742     // by default for authenticated users so we can test this permission
       
  1743     // correctly.
       
  1744     user_role_revoke_permissions(DRUPAL_AUTHENTICATED_RID, array('view own unpublished content'));
       
  1745 
       
  1746     $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'access content overview', 'administer nodes', 'bypass node access'));
       
  1747     $this->base_user_1 = $this->drupalCreateUser(array('access content overview'));
       
  1748     $this->base_user_2 = $this->drupalCreateUser(array('access content overview', 'view own unpublished content'));
       
  1749     $this->base_user_3 = $this->drupalCreateUser(array('access content overview', 'bypass node access'));
       
  1750   }
       
  1751 
       
  1752   /**
       
  1753    * Tests that the table sorting works on the content admin pages.
       
  1754    */
       
  1755   function testContentAdminSort() {
       
  1756     $this->drupalLogin($this->admin_user);
       
  1757     foreach (array('dd', 'aa', 'DD', 'bb', 'cc', 'CC', 'AA', 'BB') as $prefix) {
       
  1758       $this->drupalCreateNode(array('title' => $prefix . $this->randomName(6)));
       
  1759     }
       
  1760 
       
  1761     // Test that the default sort by node.changed DESC actually fires properly.
       
  1762     $nodes_query = db_select('node', 'n')
       
  1763       ->fields('n', array('nid'))
       
  1764       ->orderBy('changed', 'DESC')
       
  1765       ->execute()
       
  1766       ->fetchCol();
       
  1767 
       
  1768     $nodes_form = array();
       
  1769     $this->drupalGet('admin/content');
       
  1770     foreach ($this->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
       
  1771       $nodes_form[] = $input;
       
  1772     }
       
  1773     $this->assertEqual($nodes_query, $nodes_form, 'Nodes are sorted in the form according to the default query.');
       
  1774 
       
  1775     // Compare the rendered HTML node list to a query for the nodes ordered by
       
  1776     // title to account for possible database-dependent sort order.
       
  1777     $nodes_query = db_select('node', 'n')
       
  1778       ->fields('n', array('nid'))
       
  1779       ->orderBy('title')
       
  1780       ->execute()
       
  1781       ->fetchCol();
       
  1782 
       
  1783     $nodes_form = array();
       
  1784     $this->drupalGet('admin/content', array('query' => array('sort' => 'asc', 'order' => 'Title')));
       
  1785     foreach ($this->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
       
  1786       $nodes_form[] = $input;
       
  1787     }
       
  1788     $this->assertEqual($nodes_query, $nodes_form, 'Nodes are sorted in the form the same as they are in the query.');
       
  1789   }
       
  1790 
       
  1791   /**
       
  1792    * Tests content overview with different user permissions.
       
  1793    *
       
  1794    * Taxonomy filters are tested separately.
       
  1795    *
       
  1796    * @see TaxonomyNodeFilterTestCase
       
  1797    */
       
  1798   function testContentAdminPages() {
       
  1799     $this->drupalLogin($this->admin_user);
       
  1800 
       
  1801     $nodes['published_page'] = $this->drupalCreateNode(array('type' => 'page'));
       
  1802     $nodes['published_article'] = $this->drupalCreateNode(array('type' => 'article'));
       
  1803     $nodes['unpublished_page_1'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->base_user_1->uid, 'status' => 0));
       
  1804     $nodes['unpublished_page_2'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->base_user_2->uid, 'status' => 0));
       
  1805 
       
  1806     // Verify view, edit, and delete links for any content.
       
  1807     $this->drupalGet('admin/content');
       
  1808     $this->assertResponse(200);
       
  1809     foreach ($nodes as $node) {
       
  1810       $this->assertLinkByHref('node/' . $node->nid);
       
  1811       $this->assertLinkByHref('node/' . $node->nid . '/edit');
       
  1812       $this->assertLinkByHref('node/' . $node->nid . '/delete');
       
  1813       // Verify tableselect.
       
  1814       $this->assertFieldByName('nodes[' . $node->nid . ']', '', 'Tableselect found.');
       
  1815     }
       
  1816 
       
  1817     // Verify filtering by publishing status.
       
  1818     $edit = array(
       
  1819       'status' => 'status-1',
       
  1820     );
       
  1821     $this->drupalPost(NULL, $edit, t('Filter'));
       
  1822 
       
  1823     $this->assertRaw(t('where %property is %value', array('%property' => t('status'), '%value' => 'published')), 'Content list is filtered by status.');
       
  1824 
       
  1825     $this->assertLinkByHref('node/' . $nodes['published_page']->nid . '/edit');
       
  1826     $this->assertLinkByHref('node/' . $nodes['published_article']->nid . '/edit');
       
  1827     $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/edit');
       
  1828 
       
  1829     // Verify filtering by status and content type.
       
  1830     $edit = array(
       
  1831       'type' => 'page',
       
  1832     );
       
  1833     $this->drupalPost(NULL, $edit, t('Refine'));
       
  1834 
       
  1835     $this->assertRaw(t('where %property is %value', array('%property' => t('status'), '%value' => 'published')), 'Content list is filtered by status.');
       
  1836     $this->assertRaw(t('and where %property is %value', array('%property' => t('type'), '%value' => 'Basic page')), 'Content list is filtered by content type.');
       
  1837 
       
  1838     $this->assertLinkByHref('node/' . $nodes['published_page']->nid . '/edit');
       
  1839     $this->assertNoLinkByHref('node/' . $nodes['published_article']->nid . '/edit');
       
  1840 
       
  1841     // Verify no operation links are displayed for regular users.
       
  1842     $this->drupalLogout();
       
  1843     $this->drupalLogin($this->base_user_1);
       
  1844     $this->drupalGet('admin/content');
       
  1845     $this->assertResponse(200);
       
  1846     $this->assertLinkByHref('node/' . $nodes['published_page']->nid);
       
  1847     $this->assertLinkByHref('node/' . $nodes['published_article']->nid);
       
  1848     $this->assertNoLinkByHref('node/' . $nodes['published_page']->nid . '/edit');
       
  1849     $this->assertNoLinkByHref('node/' . $nodes['published_page']->nid . '/delete');
       
  1850     $this->assertNoLinkByHref('node/' . $nodes['published_article']->nid . '/edit');
       
  1851     $this->assertNoLinkByHref('node/' . $nodes['published_article']->nid . '/delete');
       
  1852 
       
  1853     // Verify no unpublished content is displayed without permission.
       
  1854     $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid);
       
  1855     $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/edit');
       
  1856     $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/delete');
       
  1857 
       
  1858     // Verify no tableselect.
       
  1859     $this->assertNoFieldByName('nodes[' . $nodes['published_page']->nid . ']', '', 'No tableselect found.');
       
  1860 
       
  1861     // Verify unpublished content is displayed with permission.
       
  1862     $this->drupalLogout();
       
  1863     $this->drupalLogin($this->base_user_2);
       
  1864     $this->drupalGet('admin/content');
       
  1865     $this->assertResponse(200);
       
  1866     $this->assertLinkByHref('node/' . $nodes['unpublished_page_2']->nid);
       
  1867     // Verify no operation links are displayed.
       
  1868     $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_2']->nid . '/edit');
       
  1869     $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_2']->nid . '/delete');
       
  1870 
       
  1871     // Verify user cannot see unpublished content of other users.
       
  1872     $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid);
       
  1873     $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/edit');
       
  1874     $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/delete');
       
  1875 
       
  1876     // Verify no tableselect.
       
  1877     $this->assertNoFieldByName('nodes[' . $nodes['unpublished_page_2']->nid . ']', '', 'No tableselect found.');
       
  1878 
       
  1879     // Verify node access can be bypassed.
       
  1880     $this->drupalLogout();
       
  1881     $this->drupalLogin($this->base_user_3);
       
  1882     $this->drupalGet('admin/content');
       
  1883     $this->assertResponse(200);
       
  1884     foreach ($nodes as $node) {
       
  1885       $this->assertLinkByHref('node/' . $node->nid);
       
  1886       $this->assertLinkByHref('node/' . $node->nid . '/edit');
       
  1887       $this->assertLinkByHref('node/' . $node->nid . '/delete');
       
  1888     }
       
  1889   }
       
  1890 }
       
  1891 
       
  1892 /**
       
  1893  * Tests node title functionality.
       
  1894  */
       
  1895 class NodeTitleTestCase extends DrupalWebTestCase {
       
  1896 
       
  1897   /**
       
  1898    * A user with permission to create and edit content and to administer nodes.
       
  1899    *
       
  1900    * @var object
       
  1901    */
       
  1902   protected $admin_user;
       
  1903 
       
  1904   public static function getInfo() {
       
  1905     return array(
       
  1906       'name' => 'Node title',
       
  1907       'description' => 'Test node title.',
       
  1908       'group' => 'Node'
       
  1909     );
       
  1910   }
       
  1911 
       
  1912   function setUp() {
       
  1913     parent::setUp();
       
  1914     $this->admin_user = $this->drupalCreateUser(array('administer nodes', 'create article content', 'create page content'));
       
  1915     $this->drupalLogin($this->admin_user);
       
  1916   }
       
  1917 
       
  1918   /**
       
  1919    *  Creates one node and tests if the node title has the correct value.
       
  1920    */
       
  1921   function testNodeTitle() {
       
  1922     // Create "Basic page" content with title.
       
  1923     // Add the node to the frontpage so we can test if teaser links are clickable.
       
  1924     $settings = array(
       
  1925       'title' => $this->randomName(8),
       
  1926       'promote' => 1,
       
  1927     );
       
  1928     $node = $this->drupalCreateNode($settings);
       
  1929 
       
  1930     // Test <title> tag.
       
  1931     $this->drupalGet("node/$node->nid");
       
  1932     $xpath = '//title';
       
  1933     $this->assertEqual(current($this->xpath($xpath)), $node->title .' | Drupal', 'Page title is equal to node title.', 'Node');
       
  1934 
       
  1935     // Test breadcrumb in comment preview.
       
  1936     $this->drupalGet("comment/reply/$node->nid");
       
  1937     $xpath = '//div[@class="breadcrumb"]/a[last()]';
       
  1938     $this->assertEqual(current($this->xpath($xpath)), $node->title, 'Node breadcrumb is equal to node title.', 'Node');
       
  1939 
       
  1940     // Test node title in comment preview.
       
  1941     $this->assertEqual(current($this->xpath('//div[@id=:id]/h2/a', array(':id' => 'node-' . $node->nid))), $node->title, 'Node preview title is equal to node title.', 'Node');
       
  1942 
       
  1943     // Test node title is clickable on teaser list (/node).
       
  1944     $this->drupalGet('node');
       
  1945     $this->clickLink($node->title);
       
  1946   }
       
  1947 }
       
  1948 
       
  1949 /**
       
  1950  * Test the node_feed() functionality.
       
  1951  */
       
  1952 class NodeFeedTestCase extends DrupalWebTestCase {
       
  1953   public static function getInfo() {
       
  1954     return array(
       
  1955       'name' => 'Node feed',
       
  1956       'description' => 'Ensures that node_feed() functions correctly.',
       
  1957       'group' => 'Node',
       
  1958    );
       
  1959   }
       
  1960 
       
  1961   /**
       
  1962    * Ensures that node_feed() accepts and prints extra channel elements.
       
  1963    */
       
  1964   function testNodeFeedExtraChannelElements() {
       
  1965     ob_start();
       
  1966     node_feed(array(), array('copyright' => 'Drupal is a registered trademark of Dries Buytaert.'));
       
  1967     $output = ob_get_clean();
       
  1968 
       
  1969     $this->assertTrue(strpos($output, '<copyright>Drupal is a registered trademark of Dries Buytaert.</copyright>') !== FALSE);
       
  1970   }
       
  1971 }
       
  1972 
       
  1973 /**
       
  1974  * Functional tests for the node module blocks.
       
  1975  */
       
  1976 class NodeBlockFunctionalTest extends DrupalWebTestCase {
       
  1977   public static function getInfo() {
       
  1978     return array(
       
  1979       'name' => 'Node blocks',
       
  1980       'description' => 'Test node block functionality.',
       
  1981       'group' => 'Node',
       
  1982     );
       
  1983   }
       
  1984 
       
  1985   function setUp() {
       
  1986     parent::setUp('node', 'block');
       
  1987 
       
  1988     // Create users and test node.
       
  1989     $this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer nodes', 'administer blocks'));
       
  1990     $this->web_user = $this->drupalCreateUser(array('access content', 'create article content'));
       
  1991   }
       
  1992 
       
  1993   /**
       
  1994    * Tests the recent comments block.
       
  1995    */
       
  1996   function testRecentNodeBlock() {
       
  1997     $this->drupalLogin($this->admin_user);
       
  1998 
       
  1999     // Disallow anonymous users to view content.
       
  2000     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       
  2001       'access content' => FALSE,
       
  2002     ));
       
  2003 
       
  2004     // Set the block to a region to confirm block is available.
       
  2005     $edit = array(
       
  2006       'blocks[node_recent][region]' => 'sidebar_first',
       
  2007     );
       
  2008     $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
       
  2009     $this->assertText(t('The block settings have been updated.'), 'Block saved to first sidebar region.');
       
  2010 
       
  2011     // Set block title and variables.
       
  2012     $block = array(
       
  2013       'title' => $this->randomName(),
       
  2014       'node_recent_block_count' => 2,
       
  2015     );
       
  2016     $this->drupalPost('admin/structure/block/manage/node/recent/configure', $block, t('Save block'));
       
  2017     $this->assertText(t('The block configuration has been saved.'), 'Block saved.');
       
  2018 
       
  2019     // Test that block is not visible without nodes
       
  2020     $this->drupalGet('');
       
  2021     $this->assertText(t('No content available.'), 'Block with "No content available." found.');
       
  2022 
       
  2023     // Add some test nodes.
       
  2024     $default_settings = array('uid' => $this->web_user->uid, 'type' => 'article');
       
  2025     $node1 = $this->drupalCreateNode($default_settings);
       
  2026     $node2 = $this->drupalCreateNode($default_settings);
       
  2027     $node3 = $this->drupalCreateNode($default_settings);
       
  2028 
       
  2029     // Change the changed time for node so that we can test ordering.
       
  2030     db_update('node')
       
  2031       ->fields(array(
       
  2032         'changed' => $node1->changed + 100,
       
  2033       ))
       
  2034       ->condition('nid', $node2->nid)
       
  2035       ->execute();
       
  2036     db_update('node')
       
  2037       ->fields(array(
       
  2038         'changed' => $node1->changed + 200,
       
  2039       ))
       
  2040       ->condition('nid', $node3->nid)
       
  2041       ->execute();
       
  2042 
       
  2043     // Test that a user without the 'access content' permission cannot
       
  2044     // see the block.
       
  2045     $this->drupalLogout();
       
  2046     $this->drupalGet('');
       
  2047     $this->assertNoText($block['title'], 'Block was not found.');
       
  2048 
       
  2049     // Test that only the 2 latest nodes are shown.
       
  2050     $this->drupalLogin($this->web_user);
       
  2051     $this->assertNoText($node1->title, 'Node not found in block.');
       
  2052     $this->assertText($node2->title, 'Node found in block.');
       
  2053     $this->assertText($node3->title, 'Node found in block.');
       
  2054 
       
  2055     // Check to make sure nodes are in the right order.
       
  2056     $this->assertTrue($this->xpath('//div[@id="block-node-recent"]/div/table/tbody/tr[position() = 1]/td/div/a[text() = "' . $node3->title . '"]'), 'Nodes were ordered correctly in block.');
       
  2057 
       
  2058     // Set the number of recent nodes to show to 10.
       
  2059     $this->drupalLogout();
       
  2060     $this->drupalLogin($this->admin_user);
       
  2061     $block = array(
       
  2062       'node_recent_block_count' => 10,
       
  2063     );
       
  2064     $this->drupalPost('admin/structure/block/manage/node/recent/configure', $block, t('Save block'));
       
  2065     $this->assertText(t('The block configuration has been saved.'), 'Block saved.');
       
  2066 
       
  2067     // Post an additional node.
       
  2068     $node4 = $this->drupalCreateNode($default_settings);
       
  2069 
       
  2070     // Test that all four nodes are shown.
       
  2071     $this->drupalGet('');
       
  2072     $this->assertText($node1->title, 'Node found in block.');
       
  2073     $this->assertText($node2->title, 'Node found in block.');
       
  2074     $this->assertText($node3->title, 'Node found in block.');
       
  2075     $this->assertText($node4->title, 'Node found in block.');
       
  2076 
       
  2077     // Create the custom block.
       
  2078     $custom_block = array();
       
  2079     $custom_block['info'] = $this->randomName();
       
  2080     $custom_block['title'] = $this->randomName();
       
  2081     $custom_block['types[article]'] = TRUE;
       
  2082     $custom_block['body[value]'] = $this->randomName(32);
       
  2083     $custom_block['regions[' . variable_get('theme_default', 'bartik') . ']'] = 'content';
       
  2084     if ($admin_theme = variable_get('admin_theme')) {
       
  2085       $custom_block['regions[' . $admin_theme . ']'] = 'content';
       
  2086     }
       
  2087     $this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
       
  2088 
       
  2089     $bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
       
  2090     $this->assertTrue($bid, 'Custom block with visibility rule was created.');
       
  2091 
       
  2092     // Verify visibility rules.
       
  2093     $this->drupalGet('');
       
  2094     $this->assertNoText($custom_block['title'], 'Block was displayed on the front page.');
       
  2095     $this->drupalGet('node/add/article');
       
  2096     $this->assertText($custom_block['title'], 'Block was displayed on the node/add/article page.');
       
  2097     $this->drupalGet('node/' . $node1->nid);
       
  2098     $this->assertText($custom_block['title'], 'Block was displayed on the node/N.');
       
  2099 
       
  2100     // Delete the created custom block & verify that it's been deleted.
       
  2101     $this->drupalPost('admin/structure/block/manage/block/' . $bid . '/delete', array(), t('Delete'));
       
  2102     $bid = db_query("SELECT 1 FROM {block_node_type} WHERE module = 'block' AND delta = :delta", array(':delta' => $bid))->fetchField();
       
  2103     $this->assertFalse($bid, 'Custom block was deleted.');
       
  2104   }
       
  2105 }
       
  2106 /**
       
  2107  * Tests basic options of multi-step node forms.
       
  2108  */
       
  2109 class MultiStepNodeFormBasicOptionsTest extends DrupalWebTestCase {
       
  2110   public static function getInfo() {
       
  2111     return array(
       
  2112       'name' => 'Multistep node form basic options',
       
  2113       'description' => 'Test the persistence of basic options through multiple steps.',
       
  2114       'group' => 'Node',
       
  2115     );
       
  2116   }
       
  2117 
       
  2118   function setUp() {
       
  2119     parent::setUp('poll');
       
  2120     $web_user = $this->drupalCreateUser(array('administer nodes', 'create poll content'));
       
  2121     $this->drupalLogin($web_user);
       
  2122   }
       
  2123 
       
  2124   /**
       
  2125    * Tests changing the default values of basic options to ensure they persist.
       
  2126    */
       
  2127   function testMultiStepNodeFormBasicOptions() {
       
  2128     $edit = array(
       
  2129       'title' => 'a',
       
  2130       'status' => FALSE,
       
  2131       'promote' => FALSE,
       
  2132       'sticky' => 1,
       
  2133       'choice[new:0][chtext]' => 'a',
       
  2134       'choice[new:1][chtext]' => 'a',
       
  2135     );
       
  2136     $this->drupalPost('node/add/poll', $edit, t('More choices'));
       
  2137     $this->assertNoFieldChecked('edit-status', 'status stayed unchecked');
       
  2138     $this->assertNoFieldChecked('edit-promote', 'promote stayed unchecked');
       
  2139     $this->assertFieldChecked('edit-sticky', 'sticky stayed checked');
       
  2140   }
       
  2141 }
       
  2142 
       
  2143 /**
       
  2144  * Test to ensure that a node's content is always rebuilt.
       
  2145  */
       
  2146 class NodeBuildContent extends DrupalWebTestCase {
       
  2147 
       
  2148   public static function getInfo() {
       
  2149     return array(
       
  2150       'name' => 'Rebuild content',
       
  2151       'description' => 'Test the rebuilding of content for different build modes.',
       
  2152       'group' => 'Node',
       
  2153     );
       
  2154   }
       
  2155 
       
  2156  /**
       
  2157   * Ensures that content array is rebuilt on every call to node_build_content().
       
  2158   */
       
  2159   function testNodeRebuildContent() {
       
  2160     $node = $this->drupalCreateNode();
       
  2161 
       
  2162     // Set a property in the content array so we can test for its existence later on.
       
  2163     $node->content['test_content_property'] = array('#value' => $this->randomString());
       
  2164     $content = node_build_content($node);
       
  2165 
       
  2166     // If the property doesn't exist it means the node->content was rebuilt.
       
  2167     $this->assertFalse(isset($content['test_content_property']), 'Node content was emptied prior to being built.');
       
  2168   }
       
  2169 }
       
  2170 
       
  2171 /**
       
  2172  * Tests node_query_node_access_alter().
       
  2173  */
       
  2174 class NodeQueryAlter extends DrupalWebTestCase {
       
  2175 
       
  2176   public static function getInfo() {
       
  2177     return array(
       
  2178       'name' => 'Node query alter',
       
  2179       'description' => 'Test that node access queries are properly altered by the node module.',
       
  2180       'group' => 'Node',
       
  2181     );
       
  2182   }
       
  2183 
       
  2184   /**
       
  2185    * User with permission to view content.
       
  2186    *
       
  2187    * @var object
       
  2188    */
       
  2189   protected $accessUser;
       
  2190 
       
  2191   /**
       
  2192    * User without permission to view content.
       
  2193    *
       
  2194    * @var object
       
  2195    */
       
  2196   protected $noAccessUser;
       
  2197 
       
  2198   function setUp() {
       
  2199     parent::setUp('node_access_test');
       
  2200     node_access_rebuild();
       
  2201 
       
  2202     // Create some content.
       
  2203     $this->drupalCreateNode();
       
  2204     $this->drupalCreateNode();
       
  2205     $this->drupalCreateNode();
       
  2206     $this->drupalCreateNode();
       
  2207 
       
  2208     // Create user with simple node access permission. The 'node test view'
       
  2209     // permission is implemented and granted by the node_access_test module.
       
  2210     $this->accessUser = $this->drupalCreateUser(array('access content overview', 'access content', 'node test view'));
       
  2211     $this->noAccessUser = $this->drupalCreateUser(array('access content overview', 'access content'));
       
  2212     $this->noAccessUser2 = $this->drupalCreateUser(array('access content overview', 'access content'));
       
  2213   }
       
  2214 
       
  2215   /**
       
  2216    * Tests that node access permissions are followed.
       
  2217    */
       
  2218   function testNodeQueryAlterWithUI() {
       
  2219     // Verify that a user with access permission can see at least one node.
       
  2220     $this->drupalLogin($this->accessUser);
       
  2221     $this->drupalGet('node_access_test_page');
       
  2222     $this->assertText('Yes, 4 nodes', "4 nodes were found for access user");
       
  2223     $this->assertNoText('Exception', "No database exception");
       
  2224 
       
  2225     // Test the content overview page.
       
  2226     $this->drupalGet('admin/content');
       
  2227     $table_rows = $this->xpath('//tbody/tr');
       
  2228     $this->assertEqual(4, count($table_rows), "4 nodes were found for access user");
       
  2229 
       
  2230     // Verify that a user with no access permission cannot see nodes.
       
  2231     $this->drupalLogin($this->noAccessUser);
       
  2232     $this->drupalGet('node_access_test_page');
       
  2233     $this->assertText('No nodes', "No nodes were found for no access user");
       
  2234     $this->assertNoText('Exception', "No database exception");
       
  2235 
       
  2236     $this->drupalGet('admin/content');
       
  2237     $this->assertText(t('No content available.'));
       
  2238   }
       
  2239 
       
  2240   /**
       
  2241    * Tests 'node_access' query alter, for user with access.
       
  2242    *
       
  2243    * Verifies that a non-standard table alias can be used, and that a user with
       
  2244    * node access can view the nodes.
       
  2245    */
       
  2246   function testNodeQueryAlterLowLevelWithAccess() {
       
  2247     // User with access should be able to view 4 nodes.
       
  2248     try {
       
  2249       $query = db_select('node', 'mytab')
       
  2250         ->fields('mytab');
       
  2251       $query->addTag('node_access');
       
  2252       $query->addMetaData('op', 'view');
       
  2253       $query->addMetaData('account', $this->accessUser);
       
  2254 
       
  2255       $result = $query->execute()->fetchAll();
       
  2256       $this->assertEqual(count($result), 4, 'User with access can see correct nodes');
       
  2257     }
       
  2258     catch (Exception $e) {
       
  2259       $this->fail(t('Altered query is malformed'));
       
  2260     }
       
  2261   }
       
  2262 
       
  2263   /**
       
  2264    * Tests 'node_access' query alter, for user without access.
       
  2265    *
       
  2266    * Verifies that a non-standard table alias can be used, and that a user
       
  2267    * without node access cannot view the nodes.
       
  2268    */
       
  2269   function testNodeQueryAlterLowLevelNoAccess() {
       
  2270     // User without access should be able to view 0 nodes.
       
  2271     try {
       
  2272       $query = db_select('node', 'mytab')
       
  2273         ->fields('mytab');
       
  2274       $query->addTag('node_access');
       
  2275       $query->addMetaData('op', 'view');
       
  2276       $query->addMetaData('account', $this->noAccessUser);
       
  2277 
       
  2278       $result = $query->execute()->fetchAll();
       
  2279       $this->assertEqual(count($result), 0, 'User with no access cannot see nodes');
       
  2280     }
       
  2281     catch (Exception $e) {
       
  2282       $this->fail(t('Altered query is malformed'));
       
  2283     }
       
  2284   }
       
  2285 
       
  2286   /**
       
  2287    * Tests 'node_access' query alter, for edit access.
       
  2288    *
       
  2289    * Verifies that a non-standard table alias can be used, and that a user with
       
  2290    * view-only node access cannot edit the nodes.
       
  2291    */
       
  2292   function testNodeQueryAlterLowLevelEditAccess() {
       
  2293     // User with view-only access should not be able to edit nodes.
       
  2294     try {
       
  2295       $query = db_select('node', 'mytab')
       
  2296         ->fields('mytab');
       
  2297       $query->addTag('node_access');
       
  2298       $query->addMetaData('op', 'update');
       
  2299       $query->addMetaData('account', $this->accessUser);
       
  2300 
       
  2301       $result = $query->execute()->fetchAll();
       
  2302       $this->assertEqual(count($result), 0, 'User with view-only access cannot edit nodes');
       
  2303     }
       
  2304     catch (Exception $e) {
       
  2305       $this->fail($e->getMessage());
       
  2306       $this->fail((string) $query);
       
  2307       $this->fail(t('Altered query is malformed'));
       
  2308     }
       
  2309   }
       
  2310 
       
  2311   /**
       
  2312    * Tests 'node_access' query alter override.
       
  2313    *
       
  2314    * Verifies that node_access_view_all_nodes() is called from
       
  2315    * node_query_node_access_alter(). We do this by checking that a user who
       
  2316    * normally would not have view privileges is able to view the nodes when we
       
  2317    * add a record to {node_access} paired with a corresponding privilege in
       
  2318    * hook_node_grants().
       
  2319    */
       
  2320   function testNodeQueryAlterOverride() {
       
  2321     $record = array(
       
  2322       'nid' => 0,
       
  2323       'gid' => 0,
       
  2324       'realm' => 'node_access_all',
       
  2325       'grant_view' => 1,
       
  2326       'grant_update' => 0,
       
  2327       'grant_delete' => 0,
       
  2328     );
       
  2329     drupal_write_record('node_access', $record);
       
  2330 
       
  2331     // Test that the noAccessUser still doesn't have the 'view'
       
  2332     // privilege after adding the node_access record.
       
  2333     drupal_static_reset('node_access_view_all_nodes');
       
  2334     try {
       
  2335       $query = db_select('node', 'mytab')
       
  2336         ->fields('mytab');
       
  2337       $query->addTag('node_access');
       
  2338       $query->addMetaData('op', 'view');
       
  2339       $query->addMetaData('account', $this->noAccessUser);
       
  2340 
       
  2341       $result = $query->execute()->fetchAll();
       
  2342       $this->assertEqual(count($result), 0, 'User view privileges are not overridden');
       
  2343     }
       
  2344     catch (Exception $e) {
       
  2345       $this->fail(t('Altered query is malformed'));
       
  2346     }
       
  2347 
       
  2348     // Have node_test_node_grants return a node_access_all privilege,
       
  2349     // to grant the noAccessUser 'view' access.  To verify that
       
  2350     // node_access_view_all_nodes is properly checking the specified
       
  2351     // $account instead of the global $user, we will log in as
       
  2352     // noAccessUser2.
       
  2353     $this->drupalLogin($this->noAccessUser2);
       
  2354     variable_set('node_test_node_access_all_uid', $this->noAccessUser->uid);
       
  2355     drupal_static_reset('node_access_view_all_nodes');
       
  2356     try {
       
  2357       $query = db_select('node', 'mytab')
       
  2358         ->fields('mytab');
       
  2359       $query->addTag('node_access');
       
  2360       $query->addMetaData('op', 'view');
       
  2361       $query->addMetaData('account', $this->noAccessUser);
       
  2362 
       
  2363       $result = $query->execute()->fetchAll();
       
  2364       $this->assertEqual(count($result), 4, 'User view privileges are overridden');
       
  2365     }
       
  2366     catch (Exception $e) {
       
  2367       $this->fail(t('Altered query is malformed'));
       
  2368     }
       
  2369     variable_del('node_test_node_access_all_uid');
       
  2370   }
       
  2371 }
       
  2372 
       
  2373 
       
  2374 /**
       
  2375  * Tests node_query_entity_field_access_alter().
       
  2376  */
       
  2377 class NodeEntityFieldQueryAlter extends DrupalWebTestCase {
       
  2378 
       
  2379   public static function getInfo() {
       
  2380     return array(
       
  2381       'name' => 'Node entity query alter',
       
  2382       'description' => 'Test that node access entity queries are properly altered by the node module.',
       
  2383       'group' => 'Node',
       
  2384     );
       
  2385   }
       
  2386 
       
  2387   /**
       
  2388    * User with permission to view content.
       
  2389    *
       
  2390    * @var object
       
  2391    */
       
  2392   protected $accessUser;
       
  2393 
       
  2394   /**
       
  2395    * User without permission to view content.
       
  2396    *
       
  2397    * @var object
       
  2398    */
       
  2399   protected $noAccessUser;
       
  2400 
       
  2401   function setUp() {
       
  2402     parent::setUp('node_access_test');
       
  2403     node_access_rebuild();
       
  2404 
       
  2405     // Creating 4 nodes with an entity field so we can test that sort of query
       
  2406     // alter. All field values starts with 'A' so we can identify and fetch them
       
  2407     // in the node_access_test module.
       
  2408     $settings = array('language' => LANGUAGE_NONE);
       
  2409     for ($i = 0; $i < 4; $i++) {
       
  2410       $body = array(
       
  2411         'value' => 'A' . $this->randomName(32),
       
  2412         'format' => filter_default_format(),
       
  2413       );
       
  2414       $settings['body'][LANGUAGE_NONE][0] = $body;
       
  2415       $this->drupalCreateNode($settings);
       
  2416     }
       
  2417 
       
  2418     // Create user with simple node access permission. The 'node test view'
       
  2419     // permission is implemented and granted by the node_access_test module.
       
  2420     $this->accessUser = $this->drupalCreateUser(array('access content', 'node test view'));
       
  2421     $this->noAccessUser = $this->drupalCreateUser(array('access content'));
       
  2422   }
       
  2423 
       
  2424   /**
       
  2425    * Tests that node access permissions are followed.
       
  2426    */
       
  2427   function testNodeQueryAlterWithUI() {
       
  2428     // Verify that a user with access permission can see at least one node.
       
  2429     $this->drupalLogin($this->accessUser);
       
  2430     $this->drupalGet('node_access_entity_test_page');
       
  2431     $this->assertText('Yes, 4 nodes', "4 nodes were found for access user");
       
  2432     $this->assertNoText('Exception', "No database exception");
       
  2433 
       
  2434     // Verify that a user with no access permission cannot see nodes.
       
  2435     $this->drupalLogin($this->noAccessUser);
       
  2436     $this->drupalGet('node_access_entity_test_page');
       
  2437     $this->assertText('No nodes', "No nodes were found for no access user");
       
  2438     $this->assertNoText('Exception', "No database exception");
       
  2439   }
       
  2440 }
       
  2441 
       
  2442 /**
       
  2443  * Test node token replacement in strings.
       
  2444  */
       
  2445 class NodeTokenReplaceTestCase extends DrupalWebTestCase {
       
  2446   public static function getInfo() {
       
  2447     return array(
       
  2448       'name' => 'Node token replacement',
       
  2449       'description' => 'Generates text using placeholders for dummy content to check node token replacement.',
       
  2450       'group' => 'Node',
       
  2451     );
       
  2452   }
       
  2453 
       
  2454   /**
       
  2455    * Creates a node, then tests the tokens generated from it.
       
  2456    */
       
  2457   function testNodeTokenReplacement() {
       
  2458     global $language;
       
  2459     $url_options = array(
       
  2460       'absolute' => TRUE,
       
  2461       'language' => $language,
       
  2462     );
       
  2463 
       
  2464     // Create a user and a node.
       
  2465     $account = $this->drupalCreateUser();
       
  2466     $settings = array(
       
  2467       'type' => 'article',
       
  2468       'uid' => $account->uid,
       
  2469       'title' => '<blink>Blinking Text</blink>',
       
  2470       'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32), 'summary' => $this->randomName(16)))),
       
  2471     );
       
  2472     $node = $this->drupalCreateNode($settings);
       
  2473 
       
  2474     // Load node so that the body and summary fields are structured properly.
       
  2475     $node = node_load($node->nid);
       
  2476     $instance = field_info_instance('node', 'body', $node->type);
       
  2477 
       
  2478     // Generate and test sanitized tokens.
       
  2479     $tests = array();
       
  2480     $langcode = entity_language('node', $node);
       
  2481     $tests['[node:nid]'] = $node->nid;
       
  2482     $tests['[node:vid]'] = $node->vid;
       
  2483     $tests['[node:tnid]'] = $node->tnid;
       
  2484     $tests['[node:type]'] = 'article';
       
  2485     $tests['[node:type-name]'] = 'Article';
       
  2486     $tests['[node:title]'] = check_plain($node->title);
       
  2487     $tests['[node:body]'] = _text_sanitize($instance, $langcode, $node->body[$langcode][0], 'value');
       
  2488     $tests['[node:summary]'] = _text_sanitize($instance, $langcode, $node->body[$langcode][0], 'summary');
       
  2489     $tests['[node:language]'] = check_plain($langcode);
       
  2490     $tests['[node:url]'] = url('node/' . $node->nid, $url_options);
       
  2491     $tests['[node:edit-url]'] = url('node/' . $node->nid . '/edit', $url_options);
       
  2492     $tests['[node:author]'] = check_plain(format_username($account));
       
  2493     $tests['[node:author:uid]'] = $node->uid;
       
  2494     $tests['[node:author:name]'] = check_plain(format_username($account));
       
  2495     $tests['[node:created:since]'] = format_interval(REQUEST_TIME - $node->created, 2, $language->language);
       
  2496     $tests['[node:changed:since]'] = format_interval(REQUEST_TIME - $node->changed, 2, $language->language);
       
  2497 
       
  2498     // Test to make sure that we generated something for each token.
       
  2499     $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
       
  2500 
       
  2501     foreach ($tests as $input => $expected) {
       
  2502       $output = token_replace($input, array('node' => $node), array('language' => $language));
       
  2503       $this->assertEqual($output, $expected, format_string('Sanitized node token %token replaced.', array('%token' => $input)));
       
  2504     }
       
  2505 
       
  2506     // Generate and test unsanitized tokens.
       
  2507     $tests['[node:title]'] = $node->title;
       
  2508     $tests['[node:body]'] = $node->body[$langcode][0]['value'];
       
  2509     $tests['[node:summary]'] = $node->body[$langcode][0]['summary'];
       
  2510     $tests['[node:language]'] = $langcode;
       
  2511     $tests['[node:author:name]'] = format_username($account);
       
  2512 
       
  2513     foreach ($tests as $input => $expected) {
       
  2514       $output = token_replace($input, array('node' => $node), array('language' => $language, 'sanitize' => FALSE));
       
  2515       $this->assertEqual($output, $expected, format_string('Unsanitized node token %token replaced.', array('%token' => $input)));
       
  2516     }
       
  2517 
       
  2518     // Repeat for a node without a summary.
       
  2519     $settings['body'] = array(LANGUAGE_NONE => array(array('value' => $this->randomName(32), 'summary' => '')));
       
  2520     $node = $this->drupalCreateNode($settings);
       
  2521 
       
  2522     // Load node (without summary) so that the body and summary fields are
       
  2523     // structured properly.
       
  2524     $node = node_load($node->nid);
       
  2525     $instance = field_info_instance('node', 'body', $node->type);
       
  2526 
       
  2527     // Generate and test sanitized token - use full body as expected value.
       
  2528     $tests = array();
       
  2529     $tests['[node:summary]'] = _text_sanitize($instance, $langcode, $node->body[$langcode][0], 'value');
       
  2530 
       
  2531     // Test to make sure that we generated something for each token.
       
  2532     $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated for node without a summary.');
       
  2533 
       
  2534     foreach ($tests as $input => $expected) {
       
  2535       $output = token_replace($input, array('node' => $node), array('language' => $language));
       
  2536       $this->assertEqual($output, $expected, format_string('Sanitized node token %token replaced for node without a summary.', array('%token' => $input)));
       
  2537     }
       
  2538 
       
  2539     // Generate and test unsanitized tokens.
       
  2540     $tests['[node:summary]'] = $node->body[$langcode][0]['value'];
       
  2541 
       
  2542     foreach ($tests as $input => $expected) {
       
  2543       $output = token_replace($input, array('node' => $node), array('language' => $language, 'sanitize' => FALSE));
       
  2544       $this->assertEqual($output, $expected, format_string('Unsanitized node token %token replaced for node without a summary.', array('%token' => $input)));
       
  2545     }
       
  2546   }
       
  2547 }
       
  2548 
       
  2549 /**
       
  2550  * Tests user permissions for node revisions.
       
  2551  */
       
  2552 class NodeRevisionPermissionsTestCase extends DrupalWebTestCase {
       
  2553 
       
  2554   /**
       
  2555    * Nodes used by the test.
       
  2556    *
       
  2557    * @var array
       
  2558    */
       
  2559   protected $node_revisions = array();
       
  2560 
       
  2561   /**
       
  2562    * Users with different revision permission used by the test.
       
  2563    *
       
  2564    * @var array
       
  2565    */
       
  2566   protected $accounts = array();
       
  2567 
       
  2568   /**
       
  2569    * Map revision permission names to node revision access ops.
       
  2570    *
       
  2571    * @var array
       
  2572    */
       
  2573   protected $map = array(
       
  2574     'view' => 'view revisions',
       
  2575     'update' => 'revert revisions',
       
  2576     'delete' => 'delete revisions',
       
  2577   );
       
  2578 
       
  2579   public static function getInfo() {
       
  2580     return array(
       
  2581       'name' => 'Node revision permissions',
       
  2582       'description' => 'Tests user permissions for node revision operations.',
       
  2583       'group' => 'Node',
       
  2584     );
       
  2585   }
       
  2586 
       
  2587   function setUp() {
       
  2588     parent::setUp();
       
  2589 
       
  2590     // Create a node with several revisions.
       
  2591     $node = $this->drupalCreateNode();
       
  2592     $this->node_revisions[] = $node;
       
  2593 
       
  2594     for ($i = 0; $i < 3; $i++) {
       
  2595       // Create a revision for the same nid and settings with a random log.
       
  2596       $revision = clone $node;
       
  2597       $revision->revision = 1;
       
  2598       $revision->log = $this->randomName(32);
       
  2599       node_save($revision);
       
  2600       $this->node_revisions[] = $revision;
       
  2601     }
       
  2602 
       
  2603     // Create three users, one with each revision permission.
       
  2604     foreach ($this->map as $op => $permission) {
       
  2605       // Create the user.
       
  2606       $account = $this->drupalCreateUser(
       
  2607         array(
       
  2608           'access content',
       
  2609           'edit any page content',
       
  2610           'delete any page content',
       
  2611           $permission,
       
  2612         )
       
  2613       );
       
  2614       $account->op = $op;
       
  2615       $this->accounts[] = $account;
       
  2616     }
       
  2617 
       
  2618     // Create an admin account (returns TRUE for all revision permissions).
       
  2619     $admin_account = $this->drupalCreateUser(array('access content', 'administer nodes'));
       
  2620     $admin_account->is_admin = TRUE;
       
  2621     $this->accounts['admin'] = $admin_account;
       
  2622 
       
  2623     // Create a normal account (returns FALSE for all revision permissions).
       
  2624     $normal_account = $this->drupalCreateUser();
       
  2625     $normal_account->op = FALSE;
       
  2626     $this->accounts[] = $normal_account;
       
  2627   }
       
  2628 
       
  2629   /**
       
  2630    * Tests the _node_revision_access() function.
       
  2631    */
       
  2632   function testNodeRevisionAccess() {
       
  2633     $revision = $this->node_revisions[1];
       
  2634 
       
  2635     $parameters = array(
       
  2636       'op' => array_keys($this->map),
       
  2637       'account' => $this->accounts,
       
  2638     );
       
  2639 
       
  2640     $permutations = $this->generatePermutations($parameters);
       
  2641     foreach ($permutations as $case) {
       
  2642       if (!empty($case['account']->is_admin) || $case['op'] == $case['account']->op) {
       
  2643         $this->assertTrue(_node_revision_access($revision, $case['op'], $case['account']), "{$this->map[$case['op']]} granted.");
       
  2644       }
       
  2645       else {
       
  2646         $this->assertFalse(_node_revision_access($revision, $case['op'], $case['account']), "{$this->map[$case['op']]} not granted.");
       
  2647       }
       
  2648     }
       
  2649 
       
  2650     // Test that access is FALSE for a node administrator with an invalid $node
       
  2651     // or $op parameters.
       
  2652     $admin_account = $this->accounts['admin'];
       
  2653     $this->assertFalse(_node_revision_access(FALSE, 'view', $admin_account), '_node_revision_access() returns FALSE with an invalid node.');
       
  2654     $this->assertFalse(_node_revision_access($revision, 'invalid-op', $admin_account), '_node_revision_access() returns FALSE with an invalid op.');
       
  2655 
       
  2656     // Test that the $account parameter defaults to the "logged in" user.
       
  2657     $original_user = $GLOBALS['user'];
       
  2658     $GLOBALS['user'] = $admin_account;
       
  2659     $this->assertTrue(_node_revision_access($revision, 'view'), '_node_revision_access() returns TRUE when used with global user.');
       
  2660     $GLOBALS['user'] = $original_user;
       
  2661   }
       
  2662 }
       
  2663 
       
  2664 /**
       
  2665  * Tests pagination with a node access module enabled.
       
  2666  */
       
  2667 class NodeAccessPagerTestCase extends DrupalWebTestCase {
       
  2668 
       
  2669   public static function getInfo() {
       
  2670     return array(
       
  2671       'name' => 'Node access pagination',
       
  2672       'description' => 'Test access controlled node views have the right amount of comment pages.',
       
  2673       'group' => 'Node',
       
  2674     );
       
  2675   }
       
  2676 
       
  2677   public function setUp() {
       
  2678     parent::setUp('node_access_test', 'comment', 'forum');
       
  2679     node_access_rebuild();
       
  2680     $this->web_user = $this->drupalCreateUser(array('access content', 'access comments', 'node test view'));
       
  2681   }
       
  2682 
       
  2683   /**
       
  2684    * Tests the comment pager for nodes with multiple grants per realm.
       
  2685    */
       
  2686   public function testCommentPager() {
       
  2687     // Create a node.
       
  2688     $node = $this->drupalCreateNode();
       
  2689 
       
  2690     // Create 60 comments.
       
  2691     for ($i = 0; $i < 60; $i++) {
       
  2692       $comment = new stdClass();
       
  2693       $comment->cid = 0;
       
  2694       $comment->pid = 0;
       
  2695       $comment->uid = $this->web_user->uid;
       
  2696       $comment->nid = $node->nid;
       
  2697       $comment->subject = $this->randomName();
       
  2698       $comment->comment_body = array(
       
  2699         LANGUAGE_NONE => array(
       
  2700           array('value' => $this->randomName()),
       
  2701         ),
       
  2702       );
       
  2703       comment_save($comment);
       
  2704     }
       
  2705 
       
  2706     $this->drupalLogin($this->web_user);
       
  2707 
       
  2708     // View the node page. With the default 50 comments per page there should
       
  2709     // be two pages (0, 1) but no third (2) page.
       
  2710     $this->drupalGet('node/' . $node->nid);
       
  2711     $this->assertText($node->title);
       
  2712     $this->assertText(t('Comments'));
       
  2713     $this->assertRaw('page=1');
       
  2714     $this->assertNoRaw('page=2');
       
  2715   }
       
  2716 
       
  2717   /**
       
  2718    * Tests the forum node pager for nodes with multiple grants per realm.
       
  2719    */
       
  2720   public function testForumPager() {
       
  2721     // Look up the forums vocabulary ID.
       
  2722     $vid = variable_get('forum_nav_vocabulary', 0);
       
  2723     $this->assertTrue($vid, 'Forum navigation vocabulary ID is set.');
       
  2724 
       
  2725     // Look up the general discussion term.
       
  2726     $tree = taxonomy_get_tree($vid, 0, 1);
       
  2727     $tid = reset($tree)->tid;
       
  2728     $this->assertTrue($tid, 'General discussion term is found in the forum vocabulary.');
       
  2729 
       
  2730     // Create 30 nodes.
       
  2731     for ($i = 0; $i < 30; $i++) {
       
  2732       $this->drupalCreateNode(array(
       
  2733         'nid' => NULL,
       
  2734         'type' => 'forum',
       
  2735         'taxonomy_forums' => array(
       
  2736           LANGUAGE_NONE => array(
       
  2737             array('tid' => $tid, 'vid' => $vid, 'vocabulary_machine_name' => 'forums'),
       
  2738           ),
       
  2739         ),
       
  2740       ));
       
  2741     }
       
  2742 
       
  2743     // View the general discussion forum page. With the default 25 nodes per
       
  2744     // page there should be two pages for 30 nodes, no more.
       
  2745     $this->drupalLogin($this->web_user);
       
  2746     $this->drupalGet('forum/' . $tid);
       
  2747     $this->assertRaw('page=1');
       
  2748     $this->assertNoRaw('page=2');
       
  2749   }
       
  2750 }
       
  2751 
       
  2752 
       
  2753 /**
       
  2754  * Tests the interaction of the node access system with fields.
       
  2755  */
       
  2756 class NodeAccessFieldTestCase extends NodeWebTestCase {
       
  2757 
       
  2758   public static function getInfo() {
       
  2759     return array(
       
  2760       'name' => 'Node access and fields',
       
  2761       'description' => 'Tests the interaction of the node access system with fields.',
       
  2762       'group' => 'Node',
       
  2763     );
       
  2764   }
       
  2765 
       
  2766   public function setUp() {
       
  2767     parent::setUp('node_access_test', 'field_ui');
       
  2768     node_access_rebuild();
       
  2769 
       
  2770     // Create some users.
       
  2771     $this->admin_user = $this->drupalCreateUser(array('access content', 'bypass node access', 'administer fields'));
       
  2772     $this->content_admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer fields'));
       
  2773 
       
  2774     // Add a custom field to the page content type.
       
  2775     $this->field_name = drupal_strtolower($this->randomName() . '_field_name');
       
  2776     $this->field = field_create_field(array('field_name' => $this->field_name, 'type' => 'text'));
       
  2777     $this->instance = field_create_instance(array(
       
  2778       'field_name' => $this->field_name,
       
  2779       'entity_type' => 'node',
       
  2780       'bundle' => 'page',
       
  2781     ));
       
  2782   }
       
  2783 
       
  2784   /**
       
  2785    * Tests administering fields when node access is restricted.
       
  2786    */
       
  2787   function testNodeAccessAdministerField() {
       
  2788     // Create a page node.
       
  2789     $langcode = LANGUAGE_NONE;
       
  2790     $field_data = array();
       
  2791     $value = $field_data[$langcode][0]['value'] = $this->randomName();
       
  2792     $node = $this->drupalCreateNode(array($this->field_name => $field_data));
       
  2793 
       
  2794     // Log in as the administrator and confirm that the field value is present.
       
  2795     $this->drupalLogin($this->admin_user);
       
  2796     $this->drupalGet("node/{$node->nid}");
       
  2797     $this->assertText($value, 'The saved field value is visible to an administrator.');
       
  2798 
       
  2799     // Log in as the content admin and try to view the node.
       
  2800     $this->drupalLogin($this->content_admin_user);
       
  2801     $this->drupalGet("node/{$node->nid}");
       
  2802     $this->assertText('Access denied', 'Access is denied for the content admin.');
       
  2803 
       
  2804     // Modify the field default as the content admin.
       
  2805     $edit = array();
       
  2806     $default = 'Sometimes words have two meanings';
       
  2807     $edit["{$this->field_name}[$langcode][0][value]"] = $default;
       
  2808     $this->drupalPost(
       
  2809       "admin/structure/types/manage/page/fields/{$this->field_name}",
       
  2810       $edit,
       
  2811       t('Save settings')
       
  2812     );
       
  2813 
       
  2814     // Log in as the administrator.
       
  2815     $this->drupalLogin($this->admin_user);
       
  2816 
       
  2817     // Confirm that the existing node still has the correct field value.
       
  2818     $this->drupalGet("node/{$node->nid}");
       
  2819     $this->assertText($value, 'The original field value is visible to an administrator.');
       
  2820 
       
  2821     // Confirm that the new default value appears when creating a new node.
       
  2822     $this->drupalGet('node/add/page');
       
  2823     $this->assertRaw($default, 'The updated default value is displayed when creating a new node.');
       
  2824   }
       
  2825 }
       
  2826 
       
  2827 /**
       
  2828  * Tests changing view modes for nodes.
       
  2829  */
       
  2830 class NodeEntityViewModeAlterTest extends NodeWebTestCase {
       
  2831 
       
  2832   public static function getInfo() {
       
  2833     return array(
       
  2834       'name' => 'Node entity view mode',
       
  2835       'description' => 'Test changing view mode.',
       
  2836       'group' => 'Node'
       
  2837     );
       
  2838   }
       
  2839 
       
  2840   function setUp() {
       
  2841     parent::setUp(array('node_test'));
       
  2842   }
       
  2843 
       
  2844   /**
       
  2845    * Create a "Basic page" node and verify its consistency in the database.
       
  2846    */
       
  2847   function testNodeViewModeChange() {
       
  2848     $web_user = $this->drupalCreateUser(array('create page content', 'edit own page content'));
       
  2849     $this->drupalLogin($web_user);
       
  2850 
       
  2851     // Create a node.
       
  2852     $edit = array();
       
  2853     $langcode = LANGUAGE_NONE;
       
  2854     $edit["title"] = $this->randomName(8);
       
  2855     $edit["body[$langcode][0][value]"] = 'Data that should appear only in the body for the node.';
       
  2856     $edit["body[$langcode][0][summary]"] = 'Extra data that should appear only in the teaser for the node.';
       
  2857     $this->drupalPost('node/add/page', $edit, t('Save'));
       
  2858 
       
  2859     $node = $this->drupalGetNodeByTitle($edit["title"]);
       
  2860 
       
  2861     // Set the flag to alter the view mode and view the node.
       
  2862     variable_set('node_test_change_view_mode', 'teaser');
       
  2863     $this->drupalGet('node/' . $node->nid);
       
  2864 
       
  2865     // Check that teaser mode is viewed.
       
  2866     $this->assertText('Extra data that should appear only in the teaser for the node.', 'Teaser text present');
       
  2867     // Make sure body text is not present.
       
  2868     $this->assertNoText('Data that should appear only in the body for the node.', 'Body text not present');
       
  2869 
       
  2870     // Test that the correct build mode has been set.
       
  2871     $build = node_view($node);
       
  2872     $this->assertEqual($build['#view_mode'], 'teaser', 'The view mode has correctly been set to teaser.');
       
  2873   }
       
  2874 
       
  2875   /**
       
  2876    * Tests fields that were previously hidden when the view mode is changed.
       
  2877    */
       
  2878   function testNodeViewModeChangeHiddenField() {
       
  2879     // Hide the tags field on the default display
       
  2880     $instance = field_info_instance('node', 'field_tags', 'article');
       
  2881     $instance['display']['default']['type'] = 'hidden';
       
  2882     field_update_instance($instance);
       
  2883 
       
  2884     $web_user = $this->drupalCreateUser(array('create article content', 'edit own article content'));
       
  2885     $this->drupalLogin($web_user);
       
  2886 
       
  2887     // Create a node.
       
  2888     $edit = array();
       
  2889     $langcode = LANGUAGE_NONE;
       
  2890     $edit["title"] = $this->randomName(8);
       
  2891     $edit["body[$langcode][0][value]"] = 'Data that should appear only in the body for the node.';
       
  2892     $edit["body[$langcode][0][summary]"] = 'Extra data that should appear only in the teaser for the node.';
       
  2893     $edit["field_tags[$langcode]"] = 'Extra tag';
       
  2894     $this->drupalPost('node/add/article', $edit, t('Save'));
       
  2895 
       
  2896     $node = $this->drupalGetNodeByTitle($edit["title"]);
       
  2897 
       
  2898     // Set the flag to alter the view mode and view the node.
       
  2899     variable_set('node_test_change_view_mode', 'teaser');
       
  2900     $this->drupalGet('node/' . $node->nid);
       
  2901 
       
  2902     // Check that teaser mode is viewed.
       
  2903     $this->assertText('Extra data that should appear only in the teaser for the node.', 'Teaser text present');
       
  2904     // Make sure body text is not present.
       
  2905     $this->assertNoText('Data that should appear only in the body for the node.', 'Body text not present');
       
  2906     // Make sure tags are present.
       
  2907     $this->assertText('Extra tag', 'Taxonomy term present');
       
  2908 
       
  2909     // Test that the correct build mode has been set.
       
  2910     $build = node_view($node);
       
  2911     $this->assertEqual($build['#view_mode'], 'teaser', 'The view mode has correctly been set to teaser.');
       
  2912   }
       
  2913 }
       
  2914 
       
  2915 /**
       
  2916  * Tests the cache invalidation of node operations.
       
  2917  */
       
  2918 class NodePageCacheTest extends NodeWebTestCase {
       
  2919 
       
  2920   /**
       
  2921    * An admin user with administrative permissions for nodes.
       
  2922    */
       
  2923   protected $admin_user;
       
  2924 
       
  2925   public static function getInfo() {
       
  2926     return array(
       
  2927         'name' => 'Node page cache test',
       
  2928         'description' => 'Test cache invalidation of node operations.',
       
  2929         'group' => 'Node',
       
  2930     );
       
  2931   }
       
  2932 
       
  2933   function setUp() {
       
  2934     parent::setUp();
       
  2935 
       
  2936     variable_set('cache', 1);
       
  2937     variable_set('page_cache_maximum_age', 300);
       
  2938 
       
  2939     $this->admin_user = $this->drupalCreateUser(array(
       
  2940         'bypass node access',
       
  2941         'access content overview',
       
  2942         'administer nodes',
       
  2943     ));
       
  2944   }
       
  2945 
       
  2946   /**
       
  2947    * Tests deleting nodes clears page cache.
       
  2948    */
       
  2949   public function testNodeDelete() {
       
  2950     $node_path = 'node/' . $this->drupalCreateNode()->nid;
       
  2951 
       
  2952     // Populate page cache.
       
  2953     $this->drupalGet($node_path);
       
  2954 
       
  2955     // Login and delete the node.
       
  2956     $this->drupalLogin($this->admin_user);
       
  2957     $this->drupalPost($node_path . '/delete', array(), t('Delete'));
       
  2958 
       
  2959     // Logout and check the node is not available.
       
  2960     $this->drupalLogout();
       
  2961     $this->drupalGet($node_path);
       
  2962     $this->assertResponse(404);
       
  2963 
       
  2964     // Create two new nodes.
       
  2965     $nodes[0] = $this->drupalCreateNode();
       
  2966     $nodes[1] = $this->drupalCreateNode();
       
  2967     $node_path = 'node/' . $nodes[0]->nid;
       
  2968 
       
  2969     // Populate page cache.
       
  2970     $this->drupalGet($node_path);
       
  2971 
       
  2972     // Login and delete the nodes.
       
  2973     $this->drupalLogin($this->admin_user);
       
  2974     $this->drupalGet('admin/content');
       
  2975     $edit = array(
       
  2976         'operation' => 'delete',
       
  2977         'nodes[' . $nodes[0]->nid . ']' => TRUE,
       
  2978         'nodes[' . $nodes[1]->nid . ']' => TRUE,
       
  2979     );
       
  2980     $this->drupalPost(NULL, $edit, t('Update'));
       
  2981     $this->drupalPost(NULL, array(), t('Delete'));
       
  2982 
       
  2983     // Logout and check the node is not available.
       
  2984     $this->drupalLogout();
       
  2985     $this->drupalGet($node_path);
       
  2986     $this->assertResponse(404);
       
  2987   }
       
  2988 }
       
  2989 
       
  2990 /**
       
  2991  * Tests that multi-byte UTF-8 characters are stored and retrieved correctly.
       
  2992  */
       
  2993 class NodeMultiByteUtf8Test extends NodeWebTestCase {
       
  2994 
       
  2995   public static function getInfo() {
       
  2996     return array(
       
  2997       'name' => 'Multi-byte UTF-8',
       
  2998       'description' => 'Test that multi-byte UTF-8 characters are stored and retrieved correctly.',
       
  2999       'group' => 'Node',
       
  3000     );
       
  3001   }
       
  3002 
       
  3003   /**
       
  3004    * Tests that multi-byte UTF-8 characters are stored and retrieved correctly.
       
  3005    */
       
  3006   public function testMultiByteUtf8() {
       
  3007     $connection = Database::getConnection();
       
  3008     // On MySQL, this test will only run if 'charset' is set to 'utf8mb4' in
       
  3009     // settings.php.
       
  3010     if (!($connection->utf8mb4IsSupported() && $connection->utf8mb4IsActive())) {
       
  3011       return;
       
  3012     }
       
  3013     $title = '🐙';
       
  3014     $this->assertTrue(drupal_strlen($title, 'utf-8') < strlen($title), 'Title has multi-byte characters.');
       
  3015     $node = $this->drupalCreateNode(array('title' => $title));
       
  3016     $this->drupalGet('node/' . $node->nid);
       
  3017     $result = $this->xpath('//h1[@id="page-title"]');
       
  3018     $this->assertEqual(trim((string) $result[0]), $title, 'The passed title was returned.');
       
  3019   }
       
  3020 
       
  3021 }