Projet

Général

Profil

Paste
Télécharger (109 ko) Statistiques
| Branche: | Révision:

root / htmltest / modules / node / node.test @ 85ad3d82

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();
461

    
462
    $web_user = $this->drupalCreateUser(array('edit own page content', 'create page content'));
463
    $this->drupalLogin($web_user);
464
  }
465

    
466
  /**
467
   * Checks the node preview functionality.
468
   */
469
  function testPagePreview() {
470
    $langcode = LANGUAGE_NONE;
471
    $title_key = "title";
472
    $body_key = "body[$langcode][0][value]";
473

    
474
    // Fill in node creation form and preview node.
475
    $edit = array();
476
    $edit[$title_key] = $this->randomName(8);
477
    $edit[$body_key] = $this->randomName(16);
478
    $this->drupalPost('node/add/page', $edit, t('Preview'));
479

    
480
    // Check that the preview is displaying the title and body.
481
    $this->assertTitle(t('Preview | Drupal'), 'Basic page title is preview.');
482
    $this->assertText($edit[$title_key], 'Title displayed.');
483
    $this->assertText($edit[$body_key], 'Body displayed.');
484

    
485
    // Check that the title and body fields are displayed with the correct values.
486
    $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
487
    $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
488
  }
489

    
490
  /**
491
   * Checks the node preview functionality, when using revisions.
492
   */
493
  function testPagePreviewWithRevisions() {
494
    $langcode = LANGUAGE_NONE;
495
    $title_key = "title";
496
    $body_key = "body[$langcode][0][value]";
497
    // Force revision on "Basic page" content.
498
    variable_set('node_options_page', array('status', 'revision'));
499

    
500
    // Fill in node creation form and preview node.
501
    $edit = array();
502
    $edit[$title_key] = $this->randomName(8);
503
    $edit[$body_key] = $this->randomName(16);
504
    $edit['log'] = $this->randomName(32);
505
    $this->drupalPost('node/add/page', $edit, t('Preview'));
506

    
507
    // Check that the preview is displaying the title and body.
508
    $this->assertTitle(t('Preview | Drupal'), 'Basic page title is preview.');
509
    $this->assertText($edit[$title_key], 'Title displayed.');
510
    $this->assertText($edit[$body_key], 'Body displayed.');
511

    
512
    // Check that the title and body fields are displayed with the correct values.
513
    $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.');
514
    $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
515

    
516
    // Check that the log field has the correct value.
517
    $this->assertFieldByName('log', $edit['log'], 'Log field displayed.');
518
  }
519
}
520

    
521
/**
522
 * Tests creating and saving a node.
523
 */
524
class NodeCreationTestCase extends DrupalWebTestCase {
525
  public static function getInfo() {
526
    return array(
527
      'name' => 'Node creation',
528
      'description' => 'Create a node and test saving it.',
529
      'group' => 'Node',
530
    );
531
  }
532

    
533
  function setUp() {
534
    // Enable dummy module that implements hook_node_insert for exceptions.
535
    parent::setUp('node_test_exception');
536

    
537
    $web_user = $this->drupalCreateUser(array('create page content', 'edit own page content'));
538
    $this->drupalLogin($web_user);
539
  }
540

    
541
  /**
542
   * Creates a "Basic page" node and verifies its consistency in the database.
543
   */
544
  function testNodeCreation() {
545
    // Create a node.
546
    $edit = array();
547
    $langcode = LANGUAGE_NONE;
548
    $edit["title"] = $this->randomName(8);
549
    $edit["body[$langcode][0][value]"] = $this->randomName(16);
550
    $this->drupalPost('node/add/page', $edit, t('Save'));
551

    
552
    // Check that the Basic page has been created.
553
    $this->assertRaw(t('!post %title has been created.', array('!post' => 'Basic page', '%title' => $edit["title"])), 'Basic page created.');
554

    
555
    // Check that the node exists in the database.
556
    $node = $this->drupalGetNodeByTitle($edit["title"]);
557
    $this->assertTrue($node, 'Node found in database.');
558
  }
559

    
560
  /**
561
   * Verifies that a transaction rolls back the failed creation.
562
   */
563
  function testFailedPageCreation() {
564
    // Create a node.
565
    $edit = array(
566
      'uid'      => $this->loggedInUser->uid,
567
      'name'     => $this->loggedInUser->name,
568
      'type'     => 'page',
569
      'language' => LANGUAGE_NONE,
570
      'title'    => 'testing_transaction_exception',
571
    );
572

    
573
    try {
574
      node_save((object) $edit);
575
      $this->fail(t('Expected exception has not been thrown.'));
576
    }
577
    catch (Exception $e) {
578
      $this->pass(t('Expected exception has been thrown.'));
579
    }
580

    
581
    if (Database::getConnection()->supportsTransactions()) {
582
      // Check that the node does not exist in the database.
583
      $node = $this->drupalGetNodeByTitle($edit['title']);
584
      $this->assertFalse($node, 'Transactions supported, and node not found in database.');
585
    }
586
    else {
587
      // Check that the node exists in the database.
588
      $node = $this->drupalGetNodeByTitle($edit['title']);
589
      $this->assertTrue($node, 'Transactions not supported, and node found in database.');
590

    
591
      // Check that the failed rollback was logged.
592
      $records = db_query("SELECT wid FROM {watchdog} WHERE message LIKE 'Explicit rollback failed%'")->fetchAll();
593
      $this->assertTrue(count($records) > 0, 'Transactions not supported, and rollback error logged to watchdog.');
594
    }
595

    
596
    // Check that the rollback error was logged.
597
    $records = db_query("SELECT wid FROM {watchdog} WHERE variables LIKE '%Test exception for rollback.%'")->fetchAll();
598
    $this->assertTrue(count($records) > 0, 'Rollback explanatory error logged to watchdog.');
599
  }
600

    
601
  /**
602
   * Create an unpublished node and confirm correct redirect behavior.
603
   */
604
  function testUnpublishedNodeCreation() {
605
    // Set "Basic page" content type to be unpublished by default.
606
    variable_set('node_options_page', array());
607
    // Set the front page to the default "node" page.
608
    variable_set('site_frontpage', 'node');
609

    
610
    // Create a node.
611
    $edit = array();
612
    $edit["title"] = $this->randomName(8);
613
    $edit["body[" . LANGUAGE_NONE . "][0][value]"] = $this->randomName(16);
614
    $this->drupalPost('node/add/page', $edit, t('Save'));
615

    
616
    // Check that the user was redirected to the home page.
617
    $this->assertText(t('Welcome to Drupal'), t('The user is redirected to the home page.'));
618
  }
619
}
620

    
621
/**
622
 * Tests the functionality of node entity edit permissions.
623
 */
624
class PageViewTestCase extends DrupalWebTestCase {
625
  public static function getInfo() {
626
    return array(
627
      'name' => 'Node edit permissions',
628
      'description' => 'Create a node and test edit permissions.',
629
      'group' => 'Node',
630
    );
631
  }
632

    
633
  /**
634
   * Tests an anonymous and unpermissioned user attempting to edit the node.
635
   */
636
  function testPageView() {
637
    // Create a node to view.
638
    $node = $this->drupalCreateNode();
639
    $this->assertTrue(node_load($node->nid), 'Node created.');
640

    
641
    // Try to edit with anonymous user.
642
    $html = $this->drupalGet("node/$node->nid/edit");
643
    $this->assertResponse(403);
644

    
645
    // Create a user without permission to edit node.
646
    $web_user = $this->drupalCreateUser(array('access content'));
647
    $this->drupalLogin($web_user);
648

    
649
    // Attempt to access edit page.
650
    $this->drupalGet("node/$node->nid/edit");
651
    $this->assertResponse(403);
652

    
653
    // Create user with permission to edit node.
654
    $web_user = $this->drupalCreateUser(array('bypass node access'));
655
    $this->drupalLogin($web_user);
656

    
657
    // Attempt to access edit page.
658
    $this->drupalGet("node/$node->nid/edit");
659
    $this->assertResponse(200);
660
  }
661
}
662

    
663
/**
664
 * Tests the summary length functionality.
665
 */
666
class SummaryLengthTestCase extends DrupalWebTestCase {
667
  public static function getInfo() {
668
    return array(
669
      'name' => 'Summary length',
670
      'description' => 'Test summary length.',
671
      'group' => 'Node',
672
    );
673
  }
674

    
675
  /**
676
   * Tests the node summary length functionality.
677
   */
678
  function testSummaryLength() {
679
    // Create a node to view.
680
    $settings = array(
681
      '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.'))),
682
      'promote' => 1,
683
    );
684
    $node = $this->drupalCreateNode($settings);
685
    $this->assertTrue(node_load($node->nid), 'Node created.');
686

    
687
    // Create user with permission to view the node.
688
    $web_user = $this->drupalCreateUser(array('access content', 'administer content types'));
689
    $this->drupalLogin($web_user);
690

    
691
    // Attempt to access the front page.
692
    $this->drupalGet("node");
693
    // The node teaser when it has 600 characters in length
694
    $expected = 'What is a Drupalism?';
695
    $this->assertRaw($expected, 'Check that the summary is 600 characters in length', 'Node');
696

    
697
    // Change the teaser length for "Basic page" content type.
698
    $instance = field_info_instance('node', 'body', $node->type);
699
    $instance['display']['teaser']['settings']['trim_length'] = 200;
700
    field_update_instance($instance);
701

    
702
    // Attempt to access the front page again and check if the summary is now only 200 characters in length.
703
    $this->drupalGet("node");
704
    $this->assertNoRaw($expected, 'Check that the summary is not longer than 200 characters', 'Node');
705
  }
706
}
707

    
708
/**
709
 * Tests XSS functionality with a node entity.
710
 */
711
class NodeTitleXSSTestCase extends DrupalWebTestCase {
712
  public static function getInfo() {
713
    return array(
714
      'name' => 'Node title XSS filtering',
715
      'description' => 'Create a node with dangerous tags in its title and test that they are escaped.',
716
      'group' => 'Node',
717
    );
718
  }
719

    
720
  /**
721
   * Tests XSS functionality with a node entity.
722
   */
723
  function testNodeTitleXSS() {
724
    // Prepare a user to do the stuff.
725
    $web_user = $this->drupalCreateUser(array('create page content', 'edit any page content'));
726
    $this->drupalLogin($web_user);
727

    
728
    $xss = '<script>alert("xss")</script>';
729
    $title = $xss . $this->randomName();
730
    $edit = array("title" => $title);
731

    
732
    $this->drupalPost('node/add/page', $edit, t('Preview'));
733
    $this->assertNoRaw($xss, 'Harmful tags are escaped when previewing a node.');
734

    
735
    $settings = array('title' => $title);
736
    $node = $this->drupalCreateNode($settings);
737

    
738
    $this->drupalGet('node/' . $node->nid);
739
    // assertTitle() decodes HTML-entities inside the <title> element.
740
    $this->assertTitle($edit["title"] . ' | Drupal', 'Title is diplayed when viewing a node.');
741
    $this->assertNoRaw($xss, 'Harmful tags are escaped when viewing a node.');
742

    
743
    $this->drupalGet('node/' . $node->nid . '/edit');
744
    $this->assertNoRaw($xss, 'Harmful tags are escaped when editing a node.');
745
  }
746
}
747

    
748
/**
749
 * Tests the availability of the syndicate block.
750
 */
751
class NodeBlockTestCase extends DrupalWebTestCase {
752
  public static function getInfo() {
753
    return array(
754
      'name' => 'Block availability',
755
      'description' => 'Check if the syndicate block is available.',
756
      'group' => 'Node',
757
    );
758
  }
759

    
760
  function setUp() {
761
    parent::setUp();
762

    
763
    // Create and login user
764
    $admin_user = $this->drupalCreateUser(array('administer blocks'));
765
    $this->drupalLogin($admin_user);
766
  }
767

    
768
  /**
769
   * Tests that the "Syndicate" block is shown when enabled.
770
   */
771
  function testSyndicateBlock() {
772
    // Set block title to confirm that the interface is available.
773
    $this->drupalPost('admin/structure/block/manage/node/syndicate/configure', array('title' => $this->randomName(8)), t('Save block'));
774
    $this->assertText(t('The block configuration has been saved.'), 'Block configuration set.');
775

    
776
    // Set the block to a region to confirm block is available.
777
    $edit = array();
778
    $edit['blocks[node_syndicate][region]'] = 'footer';
779
    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
780
    $this->assertText(t('The block settings have been updated.'), 'Block successfully move to footer region.');
781
  }
782
}
783

    
784
/**
785
 * Checks that the post information displays when enabled for a content type.
786
 */
787
class NodePostSettingsTestCase extends DrupalWebTestCase {
788
  public static function getInfo() {
789
    return array(
790
      'name' => 'Node post information display',
791
      'description' => 'Check that the post information (submitted by Username on date) text displays appropriately.',
792
      'group' => 'Node',
793
    );
794
  }
795

    
796
  function setUp() {
797
    parent::setUp();
798

    
799
    $web_user = $this->drupalCreateUser(array('create page content', 'administer content types', 'access user profiles'));
800
    $this->drupalLogin($web_user);
801
  }
802

    
803
  /**
804
   * Confirms "Basic page" content type and post information is on a new node.
805
   */
806
  function testPagePostInfo() {
807

    
808
    // Set "Basic page" content type to display post information.
809
    $edit = array();
810
    $edit['node_submitted'] = TRUE;
811
    $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
812

    
813
    // Create a node.
814
    $edit = array();
815
    $langcode = LANGUAGE_NONE;
816
    $edit["title"] = $this->randomName(8);
817
    $edit["body[$langcode][0][value]"] = $this->randomName(16);
818
    $this->drupalPost('node/add/page', $edit, t('Save'));
819

    
820
    // Check that the post information is displayed.
821
    $node = $this->drupalGetNodeByTitle($edit["title"]);
822
    $elements = $this->xpath('//div[contains(@class,:class)]', array(':class' => 'submitted'));
823
    $this->assertEqual(count($elements), 1, 'Post information is displayed.');
824
  }
825

    
826
  /**
827
   * Confirms absence of post information on a new node.
828
   */
829
  function testPageNotPostInfo() {
830

    
831
    // Set "Basic page" content type to display post information.
832
    $edit = array();
833
    $edit['node_submitted'] = FALSE;
834
    $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
835

    
836
    // Create a node.
837
    $edit = array();
838
    $langcode = LANGUAGE_NONE;
839
    $edit["title"] = $this->randomName(8);
840
    $edit["body[$langcode][0][value]"] = $this->randomName(16);
841
    $this->drupalPost('node/add/page', $edit, t('Save'));
842

    
843
    // Check that the post information is displayed.
844
    $node = $this->drupalGetNodeByTitle($edit["title"]);
845
    $this->assertNoRaw('<span class="submitted">', 'Post information is not displayed.');
846
  }
847
}
848

    
849
/**
850
 * Ensures that data added to nodes by other modules appears in RSS feeds.
851
 *
852
 * Create a node, enable the node_test module to ensure that extra data is
853
 * added to the node->content array, then verify that the data appears on the
854
 * sitewide RSS feed at rss.xml.
855
 */
856
class NodeRSSContentTestCase extends DrupalWebTestCase {
857
  public static function getInfo() {
858
    return array(
859
      'name' => 'Node RSS Content',
860
      'description' => 'Ensure that data added to nodes by other modules appears in RSS feeds.',
861
      'group' => 'Node',
862
    );
863
  }
864

    
865
  function setUp() {
866
    // Enable dummy module that implements hook_node_view.
867
    parent::setUp('node_test');
868

    
869
    // Use bypass node access permission here, because the test class uses
870
    // hook_grants_alter() to deny access to everyone on node_access
871
    // queries.
872
    $user = $this->drupalCreateUser(array('bypass node access', 'access content', 'create article content'));
873
    $this->drupalLogin($user);
874
  }
875

    
876
  /**
877
   * Ensures that a new node includes the custom data when added to an RSS feed.
878
   */
879
  function testNodeRSSContent() {
880
    // Create a node.
881
    $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
882

    
883
    $this->drupalGet('rss.xml');
884

    
885
    // Check that content added in 'rss' view mode appear in RSS feed.
886
    $rss_only_content = t('Extra data that should appear only in the RSS feed for node !nid.', array('!nid' => $node->nid));
887
    $this->assertText($rss_only_content, 'Node content designated for RSS appear in RSS feed.');
888

    
889
    // Check that content added in view modes other than 'rss' doesn't
890
    // appear in RSS feed.
891
    $non_rss_content = t('Extra data that should appear everywhere except the RSS feed for node !nid.', array('!nid' => $node->nid));
892
    $this->assertNoText($non_rss_content, 'Node content not designed for RSS doesn\'t appear in RSS feed.');
893

    
894
    // Check that extra RSS elements and namespaces are added to RSS feed.
895
    $test_element = array(
896
      'key' => 'testElement',
897
      'value' => t('Value of testElement RSS element for node !nid.', array('!nid' => $node->nid)),
898
    );
899
    $test_ns = 'xmlns:drupaltest="http://example.com/test-namespace"';
900
    $this->assertRaw(format_xml_elements(array($test_element)), 'Extra RSS elements appear in RSS feed.');
901
    $this->assertRaw($test_ns, 'Extra namespaces appear in RSS feed.');
902

    
903
    // Check that content added in 'rss' view mode doesn't appear when
904
    // viewing node.
905
    $this->drupalGet("node/$node->nid");
906
    $this->assertNoText($rss_only_content, 'Node content designed for RSS doesn\'t appear when viewing node.');
907

    
908
    // Check that the node feed page does not try to interpret additional path
909
    // components as arguments for node_feed() and returns default content.
910
    $this->drupalGet('rss.xml/' . $this->randomName() . '/' . $this->randomName());
911
    $this->assertText($rss_only_content, 'Ignore page arguments when delivering rss.xml.');
912
  }
913
}
914

    
915
/**
916
 * Tests basic node_access functionality.
917
 *
918
 * Note that hook_node_access_records() is covered in another test class.
919
 *
920
 * @todo Cover hook_node_access in a separate test class.
921
 */
922
class NodeAccessTestCase extends DrupalWebTestCase {
923
  public static function getInfo() {
924
    return array(
925
      'name' => 'Node access',
926
      'description' => 'Test node_access function',
927
      'group' => 'Node',
928
    );
929
  }
930

    
931
  /**
932
   * Asserts node_access() correctly grants or denies access.
933
   */
934
  function assertNodeAccess($ops, $node, $account) {
935
    foreach ($ops as $op => $result) {
936
      $msg = format_string("node_access returns @result with operation '@op'.", array('@result' => $result ? 'true' : 'false', '@op' => $op));
937
      $this->assertEqual($result, node_access($op, $node, $account), $msg);
938
    }
939
  }
940

    
941
  function setUp() {
942
    parent::setUp();
943
    // Clear permissions for authenticated users.
944
    db_delete('role_permission')
945
      ->condition('rid', DRUPAL_AUTHENTICATED_RID)
946
      ->execute();
947
  }
948

    
949
  /**
950
   * Runs basic tests for node_access function.
951
   */
952
  function testNodeAccess() {
953
    // Ensures user without 'access content' permission can do nothing.
954
    $web_user1 = $this->drupalCreateUser(array('create page content', 'edit any page content', 'delete any page content'));
955
    $node1 = $this->drupalCreateNode(array('type' => 'page'));
956
    $this->assertNodeAccess(array('create' => FALSE), 'page', $web_user1);
957
    $this->assertNodeAccess(array('view' => FALSE, 'update' => FALSE, 'delete' => FALSE), $node1, $web_user1);
958

    
959
    // Ensures user with 'bypass node access' permission can do everything.
960
    $web_user2 = $this->drupalCreateUser(array('bypass node access'));
961
    $node2 = $this->drupalCreateNode(array('type' => 'page'));
962
    $this->assertNodeAccess(array('create' => TRUE), 'page', $web_user2);
963
    $this->assertNodeAccess(array('view' => TRUE, 'update' => TRUE, 'delete' => TRUE), $node2, $web_user2);
964

    
965
    // User cannot 'view own unpublished content'.
966
    $web_user3 = $this->drupalCreateUser(array('access content'));
967
    $node3 = $this->drupalCreateNode(array('status' => 0, 'uid' => $web_user3->uid));
968
    $this->assertNodeAccess(array('view' => FALSE), $node3, $web_user3);
969

    
970
    // User cannot create content without permission.
971
    $this->assertNodeAccess(array('create' => FALSE), 'page', $web_user3);
972

    
973
    // User can 'view own unpublished content', but another user cannot.
974
    $web_user4 = $this->drupalCreateUser(array('access content', 'view own unpublished content'));
975
    $web_user5 = $this->drupalCreateUser(array('access content', 'view own unpublished content'));
976
    $node4 = $this->drupalCreateNode(array('status' => 0, 'uid' => $web_user4->uid));
977
    $this->assertNodeAccess(array('view' => TRUE, 'update' => FALSE), $node4, $web_user4);
978
    $this->assertNodeAccess(array('view' => FALSE), $node4, $web_user5);
979

    
980
    // Tests the default access provided for a published node.
981
    $node5 = $this->drupalCreateNode();
982
    $this->assertNodeAccess(array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE), $node5, $web_user3);
983
  }
984
}
985

    
986
/**
987
 * Tests hook_node_access_records() functionality.
988
 */
989
class NodeAccessRecordsTestCase extends DrupalWebTestCase {
990
  public static function getInfo() {
991
    return array(
992
      'name' => 'Node access records',
993
      'description' => 'Test hook_node_access_records when acquiring grants.',
994
      'group' => 'Node',
995
    );
996
  }
997

    
998
  function setUp() {
999
    // Enable dummy module that implements hook_node_grants(),
1000
    // hook_node_access_records(), hook_node_grants_alter() and
1001
    // hook_node_access_records_alter().
1002
    parent::setUp('node_test');
1003
  }
1004

    
1005
  /**
1006
   * Creates a node and tests the creation of node access rules.
1007
   */
1008
  function testNodeAccessRecords() {
1009
    // Create an article node.
1010
    $node1 = $this->drupalCreateNode(array('type' => 'article'));
1011
    $this->assertTrue(node_load($node1->nid), 'Article node created.');
1012

    
1013
    // Check to see if grants added by node_test_node_access_records made it in.
1014
    $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node1->nid))->fetchAll();
1015
    $this->assertEqual(count($records), 1, 'Returned the correct number of rows.');
1016
    $this->assertEqual($records[0]->realm, 'test_article_realm', 'Grant with article_realm acquired for node without alteration.');
1017
    $this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.');
1018

    
1019
    // Create an unpromoted "Basic page" node.
1020
    $node2 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0));
1021
    $this->assertTrue(node_load($node2->nid), 'Unpromoted basic page node created.');
1022

    
1023
    // Check to see if grants added by node_test_node_access_records made it in.
1024
    $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node2->nid))->fetchAll();
1025
    $this->assertEqual(count($records), 1, 'Returned the correct number of rows.');
1026
    $this->assertEqual($records[0]->realm, 'test_page_realm', 'Grant with page_realm acquired for node without alteration.');
1027
    $this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.');
1028

    
1029
    // Create an unpromoted, unpublished "Basic page" node.
1030
    $node3 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0, 'status' => 0));
1031
    $this->assertTrue(node_load($node3->nid), 'Unpromoted, unpublished basic page node created.');
1032

    
1033
    // Check to see if grants added by node_test_node_access_records made it in.
1034
    $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node3->nid))->fetchAll();
1035
    $this->assertEqual(count($records), 1, 'Returned the correct number of rows.');
1036
    $this->assertEqual($records[0]->realm, 'test_page_realm', 'Grant with page_realm acquired for node without alteration.');
1037
    $this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.');
1038

    
1039
    // Create a promoted "Basic page" node.
1040
    $node4 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1));
1041
    $this->assertTrue(node_load($node4->nid), 'Promoted basic page node created.');
1042

    
1043
    // Check to see if grant added by node_test_node_access_records was altered
1044
    // by node_test_node_access_records_alter.
1045
    $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node4->nid))->fetchAll();
1046
    $this->assertEqual(count($records), 1, 'Returned the correct number of rows.');
1047
    $this->assertEqual($records[0]->realm, 'test_alter_realm', 'Altered grant with alter_realm acquired for node.');
1048
    $this->assertEqual($records[0]->gid, 2, 'Altered grant with gid = 2 acquired for node.');
1049

    
1050
    // Check to see if we can alter grants with hook_node_grants_alter().
1051
    $operations = array('view', 'update', 'delete');
1052
    // Create a user that is allowed to access content.
1053
    $web_user = $this->drupalCreateUser(array('access content'));
1054
    foreach ($operations as $op) {
1055
      $grants = node_test_node_grants($op, $web_user);
1056
      $altered_grants = $grants;
1057
      drupal_alter('node_grants', $altered_grants, $web_user, $op);
1058
      $this->assertNotEqual($grants, $altered_grants, format_string('Altered the %op grant for a user.', array('%op' => $op)));
1059
    }
1060

    
1061
    // Check that core does not grant access to an unpublished node when an
1062
    // empty $grants array is returned.
1063
    $node6 = $this->drupalCreateNode(array('status' => 0, 'disable_node_access' => TRUE));
1064
    $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node6->nid))->fetchAll();
1065
    $this->assertEqual(count($records), 0, 'Returned no records for unpublished node.');
1066
  }
1067
}
1068

    
1069
/**
1070
 * Tests for Node Access with a non-node base table.
1071
 */
1072
class NodeAccessBaseTableTestCase extends DrupalWebTestCase {
1073

    
1074
  public static function getInfo() {
1075
    return array(
1076
      'name' => 'Node Access on any table',
1077
      'description' => 'Checks behavior of the node access subsystem if the base table is not node.',
1078
      'group' => 'Node',
1079
    );
1080
  }
1081

    
1082
  public function setUp() {
1083
    parent::setUp('node_access_test');
1084
    node_access_rebuild();
1085
    variable_set('node_access_test_private', TRUE);
1086
  }
1087

    
1088
  /**
1089
   * Tests the "private" node access functionality.
1090
   *
1091
   * - Create 2 users with "access content" and "create article" permissions.
1092
   * - Each user creates one private and one not private article.
1093

    
1094
   * - Test that each user can view the other user's non-private article.
1095
   * - Test that each user cannot view the other user's private article.
1096
   * - Test that each user finds only appropriate (non-private + own private)
1097
   *   in taxonomy listing.
1098
   * - Create another user with 'view any private content'.
1099
   * - Test that user 4 can view all content created above.
1100
   * - Test that user 4 can view all content on taxonomy listing.
1101
   */
1102
  function testNodeAccessBasic() {
1103
    $num_simple_users = 2;
1104
    $simple_users = array();
1105

    
1106
    // nodes keyed by uid and nid: $nodes[$uid][$nid] = $is_private;
1107
    $this->nodesByUser = array();
1108
    $titles = array(); // Titles keyed by nid
1109
    $private_nodes = array(); // Array of nids marked private.
1110
    for ($i = 0; $i < $num_simple_users; $i++) {
1111
      $simple_users[$i] = $this->drupalCreateUser(array('access content', 'create article content'));
1112
    }
1113
    foreach ($simple_users as $this->webUser) {
1114
      $this->drupalLogin($this->webUser);
1115
      foreach (array(0 => 'Public', 1 => 'Private') as $is_private => $type) {
1116
        $edit = array(
1117
          'title' => t('@private_public Article created by @user', array('@private_public' => $type, '@user' => $this->webUser->name)),
1118
        );
1119
        if ($is_private) {
1120
          $edit['private'] = TRUE;
1121
          $edit['body[und][0][value]'] = 'private node';
1122
          $edit['field_tags[und]'] = 'private';
1123
        }
1124
        else {
1125
          $edit['body[und][0][value]'] = 'public node';
1126
          $edit['field_tags[und]'] = 'public';
1127
        }
1128

    
1129
        $this->drupalPost('node/add/article', $edit, t('Save'));
1130
        $nid = db_query('SELECT nid FROM {node} WHERE title = :title', array(':title' => $edit['title']))->fetchField();
1131
        $private_status = db_query('SELECT private FROM {node_access_test} where nid = :nid', array(':nid' => $nid))->fetchField();
1132
        $this->assertTrue($is_private == $private_status, 'The private status of the node was properly set in the node_access_test table.');
1133
        if ($is_private) {
1134
          $private_nodes[] = $nid;
1135
        }
1136
        $titles[$nid] = $edit['title'];
1137
        $this->nodesByUser[$this->webUser->uid][$nid] = $is_private;
1138
      }
1139
    }
1140
    $this->publicTid = db_query('SELECT tid FROM {taxonomy_term_data} WHERE name = :name', array(':name' => 'public'))->fetchField();
1141
    $this->privateTid = db_query('SELECT tid FROM {taxonomy_term_data} WHERE name = :name', array(':name' => 'private'))->fetchField();
1142
    $this->assertTrue($this->publicTid, 'Public tid was found');
1143
    $this->assertTrue($this->privateTid, 'Private tid was found');
1144
    foreach ($simple_users as $this->webUser) {
1145
      $this->drupalLogin($this->webUser);
1146
      // Check own nodes to see that all are readable.
1147
      foreach ($this->nodesByUser as $uid => $data) {
1148
        foreach ($data as $nid => $is_private) {
1149
          $this->drupalGet('node/' . $nid);
1150
          if ($is_private) {
1151
            $should_be_visible = $uid == $this->webUser->uid;
1152
          }
1153
          else {
1154
            $should_be_visible = TRUE;
1155
          }
1156
          $this->assertResponse($should_be_visible ? 200 : 403, strtr('A %private node by user %uid is %visible for user %current_uid.', array(
1157
            '%private' => $is_private ? 'private' : 'public',
1158
            '%uid' => $uid,
1159
            '%visible' => $should_be_visible ? 'visible' : 'not visible',
1160
            '%current_uid' => $this->webUser->uid,
1161
          )));
1162
        }
1163
      }
1164

    
1165
      // Check to see that the correct nodes are shown on taxonomy/private
1166
      // and taxonomy/public.
1167
      $this->assertTaxonomyPage(FALSE);
1168
    }
1169

    
1170
    // Now test that a user with 'access any private content' can view content.
1171
    $access_user = $this->drupalCreateUser(array('access content', 'create article content', 'node test view', 'search content'));
1172
    $this->drupalLogin($access_user);
1173

    
1174
    foreach ($this->nodesByUser as $uid => $private_status) {
1175
      foreach ($private_status as $nid => $is_private) {
1176
        $this->drupalGet('node/' . $nid);
1177
        $this->assertResponse(200);
1178
      }
1179
    }
1180

    
1181
    // This user should be able to see all of the nodes on the relevant
1182
    // taxonomy pages.
1183
    $this->assertTaxonomyPage(TRUE);
1184
  }
1185

    
1186
  /**
1187
   * Checks taxonomy/term listings to ensure only accessible nodes are listed.
1188
   *
1189
   * @param $is_admin
1190
   *   A boolean indicating whether the current user is an administrator. If
1191
   *   TRUE, all nodes should be listed. If FALSE, only public nodes and the
1192
   *   user's own private nodes should be listed.
1193
   */
1194
  protected function assertTaxonomyPage($is_admin) {
1195
    foreach (array($this->publicTid, $this->privateTid) as $tid_is_private => $tid) {
1196
      $this->drupalGet("taxonomy/term/$tid");
1197
      $this->nids_visible = array();
1198
      foreach ($this->xpath("//a[text()='Read more']") as $link) {
1199
        $this->assertTrue(preg_match('|node/(\d+)$|', (string) $link['href'], $matches), 'Read more points to a node');
1200
        $this->nids_visible[$matches[1]] = TRUE;
1201
      }
1202
      foreach ($this->nodesByUser as $uid => $data) {
1203
        foreach ($data as $nid => $is_private) {
1204
          // Private nodes should be visible on the private term page,
1205
          // public nodes should be visible on the public term page.
1206
          $should_be_visible = $tid_is_private == $is_private;
1207
          // Non-administrators can only see their own nodes on the private
1208
          // term page.
1209
          if (!$is_admin && $tid_is_private) {
1210
            $should_be_visible = $should_be_visible && $uid == $this->webUser->uid;
1211
          }
1212
          $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(
1213
            '%private' => $is_private ? 'private' : 'public',
1214
            '%uid' => $uid,
1215
            '%visible' => isset($this->nids_visible[$nid]) ? 'visible' : 'not visible',
1216
            '%current_uid' => $this->webUser->uid,
1217
            '%tid_is_private' => $tid_is_private ? 'private' : 'public',
1218
          )));
1219
        }
1220
      }
1221
    }
1222
  }
1223
}
1224

    
1225
/**
1226
 * Tests node save related functionality, including import-save.
1227
 */
1228
class NodeSaveTestCase extends DrupalWebTestCase {
1229

    
1230
  public static function getInfo() {
1231
    return array(
1232
      'name' => 'Node save',
1233
      'description' => 'Test node_save() for saving content.',
1234
      'group' => 'Node',
1235
    );
1236
  }
1237

    
1238
  function setUp() {
1239
    parent::setUp('node_test');
1240
    // Create a user that is allowed to post; we'll use this to test the submission.
1241
    $web_user = $this->drupalCreateUser(array('create article content'));
1242
    $this->drupalLogin($web_user);
1243
    $this->web_user = $web_user;
1244
  }
1245

    
1246
  /**
1247
   * Checks whether custom node IDs are saved properly during an import operation.
1248
   *
1249
   * Workflow:
1250
   *  - first create a piece of content
1251
   *  - save the content
1252
   *  - check if node exists
1253
   */
1254
  function testImport() {
1255
    // Node ID must be a number that is not in the database.
1256
    $max_nid = db_query('SELECT MAX(nid) FROM {node}')->fetchField();
1257
    $test_nid = $max_nid + mt_rand(1000, 1000000);
1258
    $title = $this->randomName(8);
1259
    $node = array(
1260
      'title' => $title,
1261
      'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32)))),
1262
      'uid' => $this->web_user->uid,
1263
      'type' => 'article',
1264
      'nid' => $test_nid,
1265
      'is_new' => TRUE,
1266
    );
1267
    $node = node_submit((object) $node);
1268

    
1269
    // Verify that node_submit did not overwrite the user ID.
1270
    $this->assertEqual($node->uid, $this->web_user->uid, 'Function node_submit() preserves user ID');
1271

    
1272
    node_save($node);
1273
    // Test the import.
1274
    $node_by_nid = node_load($test_nid);
1275
    $this->assertTrue($node_by_nid, 'Node load by node ID.');
1276

    
1277
    $node_by_title = $this->drupalGetNodeByTitle($title);
1278
    $this->assertTrue($node_by_title, 'Node load by node title.');
1279
  }
1280

    
1281
  /**
1282
   * Verifies accuracy of the "created" and "changed" timestamp functionality.
1283
   */
1284
  function testTimestamps() {
1285
    // Use the default timestamps.
1286
    $edit = array(
1287
      'uid' => $this->web_user->uid,
1288
      'type' => 'article',
1289
      'title' => $this->randomName(8),
1290
    );
1291

    
1292
    node_save((object) $edit);
1293
    $node = $this->drupalGetNodeByTitle($edit['title']);
1294
    $this->assertEqual($node->created, REQUEST_TIME, 'Creating a node sets default "created" timestamp.');
1295
    $this->assertEqual($node->changed, REQUEST_TIME, 'Creating a node sets default "changed" timestamp.');
1296

    
1297
    // Store the timestamps.
1298
    $created = $node->created;
1299
    $changed = $node->changed;
1300

    
1301
    node_save($node);
1302
    $node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
1303
    $this->assertEqual($node->created, $created, 'Updating a node preserves "created" timestamp.');
1304

    
1305
    // Programmatically set the timestamps using hook_node_presave.
1306
    $node->title = 'testing_node_presave';
1307

    
1308
    node_save($node);
1309
    $node = $this->drupalGetNodeByTitle('testing_node_presave', TRUE);
1310
    $this->assertEqual($node->created, 280299600, 'Saving a node uses "created" timestamp set in presave hook.');
1311
    $this->assertEqual($node->changed, 979534800, 'Saving a node uses "changed" timestamp set in presave hook.');
1312

    
1313
    // Programmatically set the timestamps on the node.
1314
    $edit = array(
1315
      'uid' => $this->web_user->uid,
1316
      'type' => 'article',
1317
      'title' => $this->randomName(8),
1318
      'created' => 280299600, // Sun, 19 Nov 1978 05:00:00 GMT
1319
      'changed' => 979534800, // Drupal 1.0 release.
1320
    );
1321

    
1322
    node_save((object) $edit);
1323
    $node = $this->drupalGetNodeByTitle($edit['title']);
1324
    $this->assertEqual($node->created, 280299600, 'Creating a node uses user-set "created" timestamp.');
1325
    $this->assertNotEqual($node->changed, 979534800, 'Creating a node doesn\'t use user-set "changed" timestamp.');
1326

    
1327
    // Update the timestamps.
1328
    $node->created = 979534800;
1329
    $node->changed = 280299600;
1330

    
1331
    node_save($node);
1332
    $node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
1333
    $this->assertEqual($node->created, 979534800, 'Updating a node uses user-set "created" timestamp.');
1334
    $this->assertNotEqual($node->changed, 280299600, 'Updating a node doesn\'t use user-set "changed" timestamp.');
1335
  }
1336

    
1337
  /**
1338
   * Tests determing changes in hook_node_presave() and verifies the static node
1339
   * load cache is cleared upon save.
1340
   */
1341
  function testDeterminingChanges() {
1342
    // Initial creation.
1343
    $node = (object) array(
1344
      'uid' => $this->web_user->uid,
1345
      'type' => 'article',
1346
      'title' => 'test_changes',
1347
    );
1348
    node_save($node);
1349

    
1350
    // Update the node without applying changes.
1351
    node_save($node);
1352
    $this->assertEqual($node->title, 'test_changes', 'No changes have been determined.');
1353

    
1354
    // Apply changes.
1355
    $node->title = 'updated';
1356
    node_save($node);
1357

    
1358
    // The hook implementations node_test_node_presave() and
1359
    // node_test_node_update() determine changes and change the title.
1360
    $this->assertEqual($node->title, 'updated_presave_update', 'Changes have been determined.');
1361

    
1362
    // Test the static node load cache to be cleared.
1363
    $node = node_load($node->nid);
1364
    $this->assertEqual($node->title, 'updated_presave', 'Static cache has been cleared.');
1365
  }
1366

    
1367
  /**
1368
   * Tests saving a node on node insert.
1369
   *
1370
   * This test ensures that a node has been fully saved when hook_node_insert()
1371
   * is invoked, so that the node can be saved again in a hook implementation
1372
   * without errors.
1373
   *
1374
   * @see node_test_node_insert()
1375
   */
1376
  function testNodeSaveOnInsert() {
1377
    // node_test_node_insert() tiggers a save on insert if the title equals
1378
    // 'new'.
1379
    $node = $this->drupalCreateNode(array('title' => 'new'));
1380
    $this->assertEqual($node->title, 'Node ' . $node->nid, 'Node saved on node insert.');
1381
  }
1382
}
1383

    
1384
/**
1385
 * Tests related to node types.
1386
 */
1387
class NodeTypeTestCase extends DrupalWebTestCase {
1388
  public static function getInfo() {
1389
    return array(
1390
      'name' => 'Node types',
1391
      'description' => 'Ensures that node type functions work correctly.',
1392
      'group' => 'Node',
1393
    );
1394
  }
1395

    
1396
  /**
1397
   * Ensures that node type functions (node_type_get_*) work correctly.
1398
   *
1399
   * Load available node types and validate the returned data.
1400
   */
1401
  function testNodeTypeGetFunctions() {
1402
    $node_types = node_type_get_types();
1403
    $node_names = node_type_get_names();
1404

    
1405
    $this->assertTrue(isset($node_types['article']), 'Node type article is available.');
1406
    $this->assertTrue(isset($node_types['page']), 'Node type basic page is available.');
1407

    
1408
    $this->assertEqual($node_types['article']->name, $node_names['article'], 'Correct node type base has been returned.');
1409

    
1410
    $this->assertEqual($node_types['article'], node_type_get_type('article'), 'Correct node type has been returned.');
1411
    $this->assertEqual($node_types['article']->name, node_type_get_name('article'), 'Correct node type name has been returned.');
1412
    $this->assertEqual($node_types['page']->base, node_type_get_base('page'), 'Correct node type base has been returned.');
1413
  }
1414

    
1415
  /**
1416
   * Tests creating a content type programmatically and via a form.
1417
   */
1418
  function testNodeTypeCreation() {
1419
    // Create a content type programmaticaly.
1420
    $type = $this->drupalCreateContentType();
1421

    
1422
    $type_exists = db_query('SELECT 1 FROM {node_type} WHERE type = :type', array(':type' => $type->type))->fetchField();
1423
    $this->assertTrue($type_exists, 'The new content type has been created in the database.');
1424

    
1425
    // Login a test user.
1426
    $web_user = $this->drupalCreateUser(array('create ' . $type->name . ' content'));
1427
    $this->drupalLogin($web_user);
1428

    
1429
    $this->drupalGet('node/add/' . str_replace('_', '-', $type->name));
1430
    $this->assertResponse(200, 'The new content type can be accessed at node/add.');
1431

    
1432
    // Create a content type via the user interface.
1433
    $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types'));
1434
    $this->drupalLogin($web_user);
1435
    $edit = array(
1436
      'name' => 'foo',
1437
      'title_label' => 'title for foo',
1438
      'type' => 'foo',
1439
    );
1440
    $this->drupalPost('admin/structure/types/add', $edit, t('Save content type'));
1441
    $type_exists = db_query('SELECT 1 FROM {node_type} WHERE type = :type', array(':type' => 'foo'))->fetchField();
1442
    $this->assertTrue($type_exists, 'The new content type has been created in the database.');
1443
  }
1444

    
1445
  /**
1446
   * Tests editing a node type using the UI.
1447
   */
1448
  function testNodeTypeEditing() {
1449
    $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types'));
1450
    $this->drupalLogin($web_user);
1451

    
1452
    $instance = field_info_instance('node', 'body', 'page');
1453
    $this->assertEqual($instance['label'], 'Body', 'Body field was found.');
1454

    
1455
    // Verify that title and body fields are displayed.
1456
    $this->drupalGet('node/add/page');
1457
    $this->assertRaw('Title', 'Title field was found.');
1458
    $this->assertRaw('Body', 'Body field was found.');
1459

    
1460
    // Rename the title field.
1461
    $edit = array(
1462
      'title_label' => 'Foo',
1463
    );
1464
    $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
1465
    // Refresh the field information for the rest of the test.
1466
    field_info_cache_clear();
1467

    
1468
    $this->drupalGet('node/add/page');
1469
    $this->assertRaw('Foo', 'New title label was displayed.');
1470
    $this->assertNoRaw('Title', 'Old title label was not displayed.');
1471

    
1472
    // Change the name, machine name and description.
1473
    $edit = array(
1474
      'name' => 'Bar',
1475
      'type' => 'bar',
1476
      'description' => 'Lorem ipsum.',
1477
    );
1478
    $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
1479
    field_info_cache_clear();
1480

    
1481
    $this->drupalGet('node/add');
1482
    $this->assertRaw('Bar', 'New name was displayed.');
1483
    $this->assertRaw('Lorem ipsum', 'New description was displayed.');
1484
    $this->clickLink('Bar');
1485
    $this->assertEqual(url('node/add/bar', array('absolute' => TRUE)), $this->getUrl(), 'New machine name was used in URL.');
1486
    $this->assertRaw('Foo', 'Title field was found.');
1487
    $this->assertRaw('Body', 'Body field was found.');
1488

    
1489
    // Remove the body field.
1490
    $this->drupalPost('admin/structure/types/manage/bar/fields/body/delete', NULL, t('Delete'));
1491
    // Resave the settings for this type.
1492
    $this->drupalPost('admin/structure/types/manage/bar', array(), t('Save content type'));
1493
    // Check that the body field doesn't exist.
1494
    $this->drupalGet('node/add/bar');
1495
    $this->assertNoRaw('Body', 'Body field was not found.');
1496
  }
1497

    
1498
  /**
1499
   * Tests that node_types_rebuild() correctly handles the 'disabled' flag.
1500
   */
1501
  function testNodeTypeStatus() {
1502
    // Enable all core node modules, and all types should be active.
1503
    module_enable(array('blog', 'book', 'poll'), FALSE);
1504
    node_types_rebuild();
1505
    $types = node_type_get_types();
1506
    foreach (array('blog', 'book', 'poll', 'article', 'page') as $type) {
1507
      $this->assertTrue(isset($types[$type]), format_string('%type is found in node types.', array('%type' => $type)));
1508
      $this->assertTrue(isset($types[$type]->disabled) && empty($types[$type]->disabled), format_string('%type type is enabled.', array('%type' => $type)));
1509
    }
1510

    
1511
    // Disable poll module and the respective type should be marked as disabled.
1512
    module_disable(array('poll'), FALSE);
1513
    node_types_rebuild();
1514
    $types = node_type_get_types();
1515
    $this->assertTrue(!empty($types['poll']->disabled), "Poll module's node type disabled.");
1516
    $this->assertTrue(isset($types['blog']) && empty($types['blog']->disabled), "Blog module's node type still active.");
1517

    
1518
    // Disable blog module and the respective type should be marked as disabled.
1519
    module_disable(array('blog'), FALSE);
1520
    node_types_rebuild();
1521
    $types = node_type_get_types();
1522
    $this->assertTrue(!empty($types['blog']->disabled), "Blog module's node type disabled.");
1523
    $this->assertTrue(!empty($types['poll']->disabled), "Poll module's node type still disabled.");
1524

    
1525
    // Disable book module and the respective type should still be active, since
1526
    // it is not provided by hook_node_info().
1527
    module_disable(array('book'), FALSE);
1528
    node_types_rebuild();
1529
    $types = node_type_get_types();
1530
    $this->assertTrue(isset($types['book']) && empty($types['book']->disabled), "Book module's node type still active.");
1531
    $this->assertTrue(!empty($types['blog']->disabled), "Blog module's node type still disabled.");
1532
    $this->assertTrue(!empty($types['poll']->disabled), "Poll module's node type still disabled.");
1533
    $this->assertTrue(isset($types['article']) && empty($types['article']->disabled), "Article node type still active.");
1534
    $this->assertTrue(isset($types['page']) && empty($types['page']->disabled), "Basic page node type still active.");
1535

    
1536
    // Re-enable the modules and verify that the types are active again.
1537
    module_enable(array('blog', 'book', 'poll'), FALSE);
1538
    node_types_rebuild();
1539
    $types = node_type_get_types();
1540
    foreach (array('blog', 'book', 'poll', 'article', 'page') as $type) {
1541
      $this->assertTrue(isset($types[$type]), format_string('%type is found in node types.', array('%type' => $type)));
1542
      $this->assertTrue(isset($types[$type]->disabled) && empty($types[$type]->disabled), format_string('%type type is enabled.', array('%type' => $type)));
1543
    }
1544
  }
1545
}
1546

    
1547
/**
1548
 * Test node type customizations persistence.
1549
 */
1550
class NodeTypePersistenceTestCase extends DrupalWebTestCase {
1551
  public static function getInfo() {
1552
    return array(
1553
      'name' => 'Node type persist',
1554
      'description' => 'Ensures that node type customization survives module enabling and disabling.',
1555
      'group' => 'Node',
1556
    );
1557
  }
1558

    
1559
  /**
1560
   * Tests that node type customizations persist through disable and uninstall.
1561
   */
1562
  function testNodeTypeCustomizationPersistence() {
1563
    $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer modules'));
1564
    $this->drupalLogin($web_user);
1565
    $poll_key = 'modules[Core][poll][enable]';
1566
    $poll_enable = array($poll_key => "1");
1567
    $poll_disable = array($poll_key => FALSE);
1568

    
1569
    // Enable poll and verify that the node type is in the DB and is not
1570
    // disabled.
1571
    $this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
1572
    $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
1573
    $this->assertNotIdentical($disabled, FALSE, 'Poll node type found in the database');
1574
    $this->assertEqual($disabled, 0, 'Poll node type is not disabled');
1575

    
1576
    // Check that poll node type (uncustomized) shows up.
1577
    $this->drupalGet('node/add');
1578
    $this->assertText('poll', 'poll type is found on node/add');
1579

    
1580
    // Customize poll description.
1581
    $description = $this->randomName();
1582
    $edit = array('description' => $description);
1583
    $this->drupalPost('admin/structure/types/manage/poll', $edit, t('Save content type'));
1584

    
1585
    // Check that poll node type customization shows up.
1586
    $this->drupalGet('node/add');
1587
    $this->assertText($description, 'Customized description found');
1588

    
1589
    // Disable poll and check that the node type gets disabled.
1590
    $this->drupalPost('admin/modules', $poll_disable, t('Save configuration'));
1591
    $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
1592
    $this->assertEqual($disabled, 1, 'Poll node type is disabled');
1593
    $this->drupalGet('node/add');
1594
    $this->assertNoText('poll', 'poll type is not found on node/add');
1595

    
1596
    // Reenable poll and check that the customization survived the module
1597
    // disable.
1598
    $this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
1599
    $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
1600
    $this->assertNotIdentical($disabled, FALSE, 'Poll node type found in the database');
1601
    $this->assertEqual($disabled, 0, 'Poll node type is not disabled');
1602
    $this->drupalGet('node/add');
1603
    $this->assertText($description, 'Customized description found');
1604

    
1605
    // Disable and uninstall poll.
1606
    $this->drupalPost('admin/modules', $poll_disable, t('Save configuration'));
1607
    $edit = array('uninstall[poll]' => 'poll');
1608
    $this->drupalPost('admin/modules/uninstall', $edit, t('Uninstall'));
1609
    $this->drupalPost(NULL, array(), t('Uninstall'));
1610
    $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
1611
    $this->assertTrue($disabled, 'Poll node type is in the database and is disabled');
1612
    $this->drupalGet('node/add');
1613
    $this->assertNoText('poll', 'poll type is no longer found on node/add');
1614

    
1615
    // Reenable poll and check that the customization survived the module
1616
    // uninstall.
1617
    $this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
1618
    $this->drupalGet('node/add');
1619
    $this->assertText($description, 'Customized description is found even after uninstall and reenable.');
1620
  }
1621
}
1622

    
1623
/**
1624
 * Verifies the rebuild functionality for the node_access table.
1625
 */
1626
class NodeAccessRebuildTestCase extends DrupalWebTestCase {
1627
  public static function getInfo() {
1628
    return array(
1629
      'name' => 'Node access rebuild',
1630
      'description' => 'Ensures that node access rebuild functions work correctly.',
1631
      'group' => 'Node',
1632
    );
1633
  }
1634

    
1635
  function setUp() {
1636
    parent::setUp();
1637

    
1638
    $web_user = $this->drupalCreateUser(array('administer site configuration', 'access administration pages', 'access site reports'));
1639
    $this->drupalLogin($web_user);
1640
    $this->web_user = $web_user;
1641
  }
1642

    
1643
  /**
1644
   * Tests rebuilding the node access permissions table.
1645
   */
1646
  function testNodeAccessRebuild() {
1647
    $this->drupalGet('admin/reports/status');
1648
    $this->clickLink(t('Rebuild permissions'));
1649
    $this->drupalPost(NULL, array(), t('Rebuild permissions'));
1650
    $this->assertText(t('Content permissions have been rebuilt.'));
1651
  }
1652
}
1653

    
1654
/**
1655
 * Tests node administration page functionality.
1656
 */
1657
class NodeAdminTestCase extends DrupalWebTestCase {
1658
  public static function getInfo() {
1659
    return array(
1660
      'name' => 'Node administration',
1661
      'description' => 'Test node administration page functionality.',
1662
      'group' => 'Node',
1663
    );
1664
  }
1665

    
1666
  function setUp() {
1667
    parent::setUp();
1668

    
1669
    // Remove the "view own unpublished content" permission which is set
1670
    // by default for authenticated users so we can test this permission
1671
    // correctly.
1672
    user_role_revoke_permissions(DRUPAL_AUTHENTICATED_RID, array('view own unpublished content'));
1673

    
1674
    $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'access content overview', 'administer nodes', 'bypass node access'));
1675
    $this->base_user_1 = $this->drupalCreateUser(array('access content overview'));
1676
    $this->base_user_2 = $this->drupalCreateUser(array('access content overview', 'view own unpublished content'));
1677
    $this->base_user_3 = $this->drupalCreateUser(array('access content overview', 'bypass node access'));
1678
  }
1679

    
1680
  /**
1681
   * Tests that the table sorting works on the content admin pages.
1682
   */
1683
  function testContentAdminSort() {
1684
    $this->drupalLogin($this->admin_user);
1685
    foreach (array('dd', 'aa', 'DD', 'bb', 'cc', 'CC', 'AA', 'BB') as $prefix) {
1686
      $this->drupalCreateNode(array('title' => $prefix . $this->randomName(6)));
1687
    }
1688

    
1689
    // Test that the default sort by node.changed DESC actually fires properly.
1690
    $nodes_query = db_select('node', 'n')
1691
      ->fields('n', array('nid'))
1692
      ->orderBy('changed', 'DESC')
1693
      ->execute()
1694
      ->fetchCol();
1695

    
1696
    $nodes_form = array();
1697
    $this->drupalGet('admin/content');
1698
    foreach ($this->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
1699
      $nodes_form[] = $input;
1700
    }
1701
    $this->assertEqual($nodes_query, $nodes_form, 'Nodes are sorted in the form according to the default query.');
1702

    
1703
    // Compare the rendered HTML node list to a query for the nodes ordered by
1704
    // title to account for possible database-dependent sort order.
1705
    $nodes_query = db_select('node', 'n')
1706
      ->fields('n', array('nid'))
1707
      ->orderBy('title')
1708
      ->execute()
1709
      ->fetchCol();
1710

    
1711
    $nodes_form = array();
1712
    $this->drupalGet('admin/content', array('query' => array('sort' => 'asc', 'order' => 'Title')));
1713
    foreach ($this->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
1714
      $nodes_form[] = $input;
1715
    }
1716
    $this->assertEqual($nodes_query, $nodes_form, 'Nodes are sorted in the form the same as they are in the query.');
1717
  }
1718

    
1719
  /**
1720
   * Tests content overview with different user permissions.
1721
   *
1722
   * Taxonomy filters are tested separately.
1723
   *
1724
   * @see TaxonomyNodeFilterTestCase
1725
   */
1726
  function testContentAdminPages() {
1727
    $this->drupalLogin($this->admin_user);
1728

    
1729
    $nodes['published_page'] = $this->drupalCreateNode(array('type' => 'page'));
1730
    $nodes['published_article'] = $this->drupalCreateNode(array('type' => 'article'));
1731
    $nodes['unpublished_page_1'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->base_user_1->uid, 'status' => 0));
1732
    $nodes['unpublished_page_2'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->base_user_2->uid, 'status' => 0));
1733

    
1734
    // Verify view, edit, and delete links for any content.
1735
    $this->drupalGet('admin/content');
1736
    $this->assertResponse(200);
1737
    foreach ($nodes as $node) {
1738
      $this->assertLinkByHref('node/' . $node->nid);
1739
      $this->assertLinkByHref('node/' . $node->nid . '/edit');
1740
      $this->assertLinkByHref('node/' . $node->nid . '/delete');
1741
      // Verify tableselect.
1742
      $this->assertFieldByName('nodes[' . $node->nid . ']', '', 'Tableselect found.');
1743
    }
1744

    
1745
    // Verify filtering by publishing status.
1746
    $edit = array(
1747
      'status' => 'status-1',
1748
    );
1749
    $this->drupalPost(NULL, $edit, t('Filter'));
1750

    
1751
    $this->assertRaw(t('where %property is %value', array('%property' => t('status'), '%value' => 'published')), 'Content list is filtered by status.');
1752

    
1753
    $this->assertLinkByHref('node/' . $nodes['published_page']->nid . '/edit');
1754
    $this->assertLinkByHref('node/' . $nodes['published_article']->nid . '/edit');
1755
    $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/edit');
1756

    
1757
    // Verify filtering by status and content type.
1758
    $edit = array(
1759
      'type' => 'page',
1760
    );
1761
    $this->drupalPost(NULL, $edit, t('Refine'));
1762

    
1763
    $this->assertRaw(t('where %property is %value', array('%property' => t('status'), '%value' => 'published')), 'Content list is filtered by status.');
1764
    $this->assertRaw(t('and where %property is %value', array('%property' => t('type'), '%value' => 'Basic page')), 'Content list is filtered by content type.');
1765

    
1766
    $this->assertLinkByHref('node/' . $nodes['published_page']->nid . '/edit');
1767
    $this->assertNoLinkByHref('node/' . $nodes['published_article']->nid . '/edit');
1768

    
1769
    // Verify no operation links are displayed for regular users.
1770
    $this->drupalLogout();
1771
    $this->drupalLogin($this->base_user_1);
1772
    $this->drupalGet('admin/content');
1773
    $this->assertResponse(200);
1774
    $this->assertLinkByHref('node/' . $nodes['published_page']->nid);
1775
    $this->assertLinkByHref('node/' . $nodes['published_article']->nid);
1776
    $this->assertNoLinkByHref('node/' . $nodes['published_page']->nid . '/edit');
1777
    $this->assertNoLinkByHref('node/' . $nodes['published_page']->nid . '/delete');
1778
    $this->assertNoLinkByHref('node/' . $nodes['published_article']->nid . '/edit');
1779
    $this->assertNoLinkByHref('node/' . $nodes['published_article']->nid . '/delete');
1780

    
1781
    // Verify no unpublished content is displayed without permission.
1782
    $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid);
1783
    $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/edit');
1784
    $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/delete');
1785

    
1786
    // Verify no tableselect.
1787
    $this->assertNoFieldByName('nodes[' . $nodes['published_page']->nid . ']', '', 'No tableselect found.');
1788

    
1789
    // Verify unpublished content is displayed with permission.
1790
    $this->drupalLogout();
1791
    $this->drupalLogin($this->base_user_2);
1792
    $this->drupalGet('admin/content');
1793
    $this->assertResponse(200);
1794
    $this->assertLinkByHref('node/' . $nodes['unpublished_page_2']->nid);
1795
    // Verify no operation links are displayed.
1796
    $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_2']->nid . '/edit');
1797
    $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_2']->nid . '/delete');
1798

    
1799
    // Verify user cannot see unpublished content of other users.
1800
    $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid);
1801
    $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/edit');
1802
    $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/delete');
1803

    
1804
    // Verify no tableselect.
1805
    $this->assertNoFieldByName('nodes[' . $nodes['unpublished_page_2']->nid . ']', '', 'No tableselect found.');
1806

    
1807
    // Verify node access can be bypassed.
1808
    $this->drupalLogout();
1809
    $this->drupalLogin($this->base_user_3);
1810
    $this->drupalGet('admin/content');
1811
    $this->assertResponse(200);
1812
    foreach ($nodes as $node) {
1813
      $this->assertLinkByHref('node/' . $node->nid);
1814
      $this->assertLinkByHref('node/' . $node->nid . '/edit');
1815
      $this->assertLinkByHref('node/' . $node->nid . '/delete');
1816
    }
1817
  }
1818
}
1819

    
1820
/**
1821
 * Tests node title functionality.
1822
 */
1823
class NodeTitleTestCase extends DrupalWebTestCase {
1824

    
1825
  /**
1826
   * A user with permission to create and edit content and to administer nodes.
1827
   *
1828
   * @var object
1829
   */
1830
  protected $admin_user;
1831

    
1832
  public static function getInfo() {
1833
    return array(
1834
      'name' => 'Node title',
1835
      'description' => 'Test node title.',
1836
      'group' => 'Node'
1837
    );
1838
  }
1839

    
1840
  function setUp() {
1841
    parent::setUp();
1842
    $this->admin_user = $this->drupalCreateUser(array('administer nodes', 'create article content', 'create page content'));
1843
    $this->drupalLogin($this->admin_user);
1844
  }
1845

    
1846
  /**
1847
   *  Creates one node and tests if the node title has the correct value.
1848
   */
1849
  function testNodeTitle() {
1850
    // Create "Basic page" content with title.
1851
    // Add the node to the frontpage so we can test if teaser links are clickable.
1852
    $settings = array(
1853
      'title' => $this->randomName(8),
1854
      'promote' => 1,
1855
    );
1856
    $node = $this->drupalCreateNode($settings);
1857

    
1858
    // Test <title> tag.
1859
    $this->drupalGet("node/$node->nid");
1860
    $xpath = '//title';
1861
    $this->assertEqual(current($this->xpath($xpath)), $node->title .' | Drupal', 'Page title is equal to node title.', 'Node');
1862

    
1863
    // Test breadcrumb in comment preview.
1864
    $this->drupalGet("comment/reply/$node->nid");
1865
    $xpath = '//div[@class="breadcrumb"]/a[last()]';
1866
    $this->assertEqual(current($this->xpath($xpath)), $node->title, 'Node breadcrumb is equal to node title.', 'Node');
1867

    
1868
    // Test node title in comment preview.
1869
    $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');
1870

    
1871
    // Test node title is clickable on teaser list (/node).
1872
    $this->drupalGet('node');
1873
    $this->clickLink($node->title);
1874
  }
1875
}
1876

    
1877
/**
1878
 * Test the node_feed() functionality.
1879
 */
1880
class NodeFeedTestCase extends DrupalWebTestCase {
1881
  public static function getInfo() {
1882
    return array(
1883
      'name' => 'Node feed',
1884
      'description' => 'Ensures that node_feed() functions correctly.',
1885
      'group' => 'Node',
1886
   );
1887
  }
1888

    
1889
  /**
1890
   * Ensures that node_feed() accepts and prints extra channel elements.
1891
   */
1892
  function testNodeFeedExtraChannelElements() {
1893
    ob_start();
1894
    node_feed(array(), array('copyright' => 'Drupal is a registered trademark of Dries Buytaert.'));
1895
    $output = ob_get_clean();
1896

    
1897
    $this->assertTrue(strpos($output, '<copyright>Drupal is a registered trademark of Dries Buytaert.</copyright>') !== FALSE);
1898
  }
1899
}
1900

    
1901
/**
1902
 * Functional tests for the node module blocks.
1903
 */
1904
class NodeBlockFunctionalTest extends DrupalWebTestCase {
1905
  public static function getInfo() {
1906
    return array(
1907
      'name' => 'Node blocks',
1908
      'description' => 'Test node block functionality.',
1909
      'group' => 'Node',
1910
    );
1911
  }
1912

    
1913
  function setUp() {
1914
    parent::setUp('node', 'block');
1915

    
1916
    // Create users and test node.
1917
    $this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer nodes', 'administer blocks'));
1918
    $this->web_user = $this->drupalCreateUser(array('access content', 'create article content'));
1919
  }
1920

    
1921
  /**
1922
   * Tests the recent comments block.
1923
   */
1924
  function testRecentNodeBlock() {
1925
    $this->drupalLogin($this->admin_user);
1926

    
1927
    // Disallow anonymous users to view content.
1928
    user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
1929
      'access content' => FALSE,
1930
    ));
1931

    
1932
    // Set the block to a region to confirm block is available.
1933
    $edit = array(
1934
      'blocks[node_recent][region]' => 'sidebar_first',
1935
    );
1936
    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
1937
    $this->assertText(t('The block settings have been updated.'), 'Block saved to first sidebar region.');
1938

    
1939
    // Set block title and variables.
1940
    $block = array(
1941
      'title' => $this->randomName(),
1942
      'node_recent_block_count' => 2,
1943
    );
1944
    $this->drupalPost('admin/structure/block/manage/node/recent/configure', $block, t('Save block'));
1945
    $this->assertText(t('The block configuration has been saved.'), 'Block saved.');
1946

    
1947
    // Test that block is not visible without nodes
1948
    $this->drupalGet('');
1949
    $this->assertText(t('No content available.'), 'Block with "No content available." found.');
1950

    
1951
    // Add some test nodes.
1952
    $default_settings = array('uid' => $this->web_user->uid, 'type' => 'article');
1953
    $node1 = $this->drupalCreateNode($default_settings);
1954
    $node2 = $this->drupalCreateNode($default_settings);
1955
    $node3 = $this->drupalCreateNode($default_settings);
1956

    
1957
    // Change the changed time for node so that we can test ordering.
1958
    db_update('node')
1959
      ->fields(array(
1960
        'changed' => $node1->changed + 100,
1961
      ))
1962
      ->condition('nid', $node2->nid)
1963
      ->execute();
1964
    db_update('node')
1965
      ->fields(array(
1966
        'changed' => $node1->changed + 200,
1967
      ))
1968
      ->condition('nid', $node3->nid)
1969
      ->execute();
1970

    
1971
    // Test that a user without the 'access content' permission cannot
1972
    // see the block.
1973
    $this->drupalLogout();
1974
    $this->drupalGet('');
1975
    $this->assertNoText($block['title'], 'Block was not found.');
1976

    
1977
    // Test that only the 2 latest nodes are shown.
1978
    $this->drupalLogin($this->web_user);
1979
    $this->assertNoText($node1->title, 'Node not found in block.');
1980
    $this->assertText($node2->title, 'Node found in block.');
1981
    $this->assertText($node3->title, 'Node found in block.');
1982

    
1983
    // Check to make sure nodes are in the right order.
1984
    $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.');
1985

    
1986
    // Set the number of recent nodes to show to 10.
1987
    $this->drupalLogout();
1988
    $this->drupalLogin($this->admin_user);
1989
    $block = array(
1990
      'node_recent_block_count' => 10,
1991
    );
1992
    $this->drupalPost('admin/structure/block/manage/node/recent/configure', $block, t('Save block'));
1993
    $this->assertText(t('The block configuration has been saved.'), 'Block saved.');
1994

    
1995
    // Post an additional node.
1996
    $node4 = $this->drupalCreateNode($default_settings);
1997

    
1998
    // Test that all four nodes are shown.
1999
    $this->drupalGet('');
2000
    $this->assertText($node1->title, 'Node found in block.');
2001
    $this->assertText($node2->title, 'Node found in block.');
2002
    $this->assertText($node3->title, 'Node found in block.');
2003
    $this->assertText($node4->title, 'Node found in block.');
2004

    
2005
    // Create the custom block.
2006
    $custom_block = array();
2007
    $custom_block['info'] = $this->randomName();
2008
    $custom_block['title'] = $this->randomName();
2009
    $custom_block['types[article]'] = TRUE;
2010
    $custom_block['body[value]'] = $this->randomName(32);
2011
    $custom_block['regions[' . variable_get('theme_default', 'bartik') . ']'] = 'content';
2012
    if ($admin_theme = variable_get('admin_theme')) {
2013
      $custom_block['regions[' . $admin_theme . ']'] = 'content';
2014
    }
2015
    $this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
2016

    
2017
    $bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
2018
    $this->assertTrue($bid, 'Custom block with visibility rule was created.');
2019

    
2020
    // Verify visibility rules.
2021
    $this->drupalGet('');
2022
    $this->assertNoText($custom_block['title'], 'Block was displayed on the front page.');
2023
    $this->drupalGet('node/add/article');
2024
    $this->assertText($custom_block['title'], 'Block was displayed on the node/add/article page.');
2025
    $this->drupalGet('node/' . $node1->nid);
2026
    $this->assertText($custom_block['title'], 'Block was displayed on the node/N.');
2027

    
2028
    // Delete the created custom block & verify that it's been deleted.
2029
    $this->drupalPost('admin/structure/block/manage/block/' . $bid . '/delete', array(), t('Delete'));
2030
    $bid = db_query("SELECT 1 FROM {block_node_type} WHERE module = 'block' AND delta = :delta", array(':delta' => $bid))->fetchField();
2031
    $this->assertFalse($bid, 'Custom block was deleted.');
2032
  }
2033
}
2034
/**
2035
 * Tests basic options of multi-step node forms.
2036
 */
2037
class MultiStepNodeFormBasicOptionsTest extends DrupalWebTestCase {
2038
  public static function getInfo() {
2039
    return array(
2040
      'name' => 'Multistep node form basic options',
2041
      'description' => 'Test the persistence of basic options through multiple steps.',
2042
      'group' => 'Node',
2043
    );
2044
  }
2045

    
2046
  function setUp() {
2047
    parent::setUp('poll');
2048
    $web_user = $this->drupalCreateUser(array('administer nodes', 'create poll content'));
2049
    $this->drupalLogin($web_user);
2050
  }
2051

    
2052
  /**
2053
   * Tests changing the default values of basic options to ensure they persist.
2054
   */
2055
  function testMultiStepNodeFormBasicOptions() {
2056
    $edit = array(
2057
      'title' => 'a',
2058
      'status' => FALSE,
2059
      'promote' => FALSE,
2060
      'sticky' => 1,
2061
      'choice[new:0][chtext]' => 'a',
2062
      'choice[new:1][chtext]' => 'a',
2063
    );
2064
    $this->drupalPost('node/add/poll', $edit, t('More choices'));
2065
    $this->assertNoFieldChecked('edit-status', 'status stayed unchecked');
2066
    $this->assertNoFieldChecked('edit-promote', 'promote stayed unchecked');
2067
    $this->assertFieldChecked('edit-sticky', 'sticky stayed checked');
2068
  }
2069
}
2070

    
2071
/**
2072
 * Test to ensure that a node's content is always rebuilt.
2073
 */
2074
class NodeBuildContent extends DrupalWebTestCase {
2075

    
2076
  public static function getInfo() {
2077
    return array(
2078
      'name' => 'Rebuild content',
2079
      'description' => 'Test the rebuilding of content for different build modes.',
2080
      'group' => 'Node',
2081
    );
2082
  }
2083

    
2084
 /**
2085
  * Ensures that content array is rebuilt on every call to node_build_content().
2086
  */
2087
  function testNodeRebuildContent() {
2088
    $node = $this->drupalCreateNode();
2089

    
2090
    // Set a property in the content array so we can test for its existence later on.
2091
    $node->content['test_content_property'] = array('#value' => $this->randomString());
2092
    $content = node_build_content($node);
2093

    
2094
    // If the property doesn't exist it means the node->content was rebuilt.
2095
    $this->assertFalse(isset($content['test_content_property']), 'Node content was emptied prior to being built.');
2096
  }
2097
}
2098

    
2099
/**
2100
 * Tests node_query_node_access_alter().
2101
 */
2102
class NodeQueryAlter extends DrupalWebTestCase {
2103

    
2104
  public static function getInfo() {
2105
    return array(
2106
      'name' => 'Node query alter',
2107
      'description' => 'Test that node access queries are properly altered by the node module.',
2108
      'group' => 'Node',
2109
    );
2110
  }
2111

    
2112
  /**
2113
   * User with permission to view content.
2114
   *
2115
   * @var object
2116
   */
2117
  protected $accessUser;
2118

    
2119
  /**
2120
   * User without permission to view content.
2121
   *
2122
   * @var object
2123
   */
2124
  protected $noAccessUser;
2125

    
2126
  function setUp() {
2127
    parent::setUp('node_access_test');
2128
    node_access_rebuild();
2129

    
2130
    // Create some content.
2131
    $this->drupalCreateNode();
2132
    $this->drupalCreateNode();
2133
    $this->drupalCreateNode();
2134
    $this->drupalCreateNode();
2135

    
2136
    // Create user with simple node access permission. The 'node test view'
2137
    // permission is implemented and granted by the node_access_test module.
2138
    $this->accessUser = $this->drupalCreateUser(array('access content overview', 'access content', 'node test view'));
2139
    $this->noAccessUser = $this->drupalCreateUser(array('access content overview', 'access content'));
2140
    $this->noAccessUser2 = $this->drupalCreateUser(array('access content overview', 'access content'));
2141
  }
2142

    
2143
  /**
2144
   * Tests that node access permissions are followed.
2145
   */
2146
  function testNodeQueryAlterWithUI() {
2147
    // Verify that a user with access permission can see at least one node.
2148
    $this->drupalLogin($this->accessUser);
2149
    $this->drupalGet('node_access_test_page');
2150
    $this->assertText('Yes, 4 nodes', "4 nodes were found for access user");
2151
    $this->assertNoText('Exception', "No database exception");
2152

    
2153
    // Test the content overview page.
2154
    $this->drupalGet('admin/content');
2155
    $table_rows = $this->xpath('//tbody/tr');
2156
    $this->assertEqual(4, count($table_rows), "4 nodes were found for access user");
2157

    
2158
    // Verify that a user with no access permission cannot see nodes.
2159
    $this->drupalLogin($this->noAccessUser);
2160
    $this->drupalGet('node_access_test_page');
2161
    $this->assertText('No nodes', "No nodes were found for no access user");
2162
    $this->assertNoText('Exception', "No database exception");
2163

    
2164
    $this->drupalGet('admin/content');
2165
    $this->assertText(t('No content available.'));
2166
  }
2167

    
2168
  /**
2169
   * Tests 'node_access' query alter, for user with access.
2170
   *
2171
   * Verifies that a non-standard table alias can be used, and that a user with
2172
   * node access can view the nodes.
2173
   */
2174
  function testNodeQueryAlterLowLevelWithAccess() {
2175
    // User with access should be able to view 4 nodes.
2176
    try {
2177
      $query = db_select('node', 'mytab')
2178
        ->fields('mytab');
2179
      $query->addTag('node_access');
2180
      $query->addMetaData('op', 'view');
2181
      $query->addMetaData('account', $this->accessUser);
2182

    
2183
      $result = $query->execute()->fetchAll();
2184
      $this->assertEqual(count($result), 4, 'User with access can see correct nodes');
2185
    }
2186
    catch (Exception $e) {
2187
      $this->fail(t('Altered query is malformed'));
2188
    }
2189
  }
2190

    
2191
  /**
2192
   * Tests 'node_access' query alter, for user without access.
2193
   *
2194
   * Verifies that a non-standard table alias can be used, and that a user
2195
   * without node access cannot view the nodes.
2196
   */
2197
  function testNodeQueryAlterLowLevelNoAccess() {
2198
    // User without access should be able to view 0 nodes.
2199
    try {
2200
      $query = db_select('node', 'mytab')
2201
        ->fields('mytab');
2202
      $query->addTag('node_access');
2203
      $query->addMetaData('op', 'view');
2204
      $query->addMetaData('account', $this->noAccessUser);
2205

    
2206
      $result = $query->execute()->fetchAll();
2207
      $this->assertEqual(count($result), 0, 'User with no access cannot see nodes');
2208
    }
2209
    catch (Exception $e) {
2210
      $this->fail(t('Altered query is malformed'));
2211
    }
2212
  }
2213

    
2214
  /**
2215
   * Tests 'node_access' query alter, for edit access.
2216
   *
2217
   * Verifies that a non-standard table alias can be used, and that a user with
2218
   * view-only node access cannot edit the nodes.
2219
   */
2220
  function testNodeQueryAlterLowLevelEditAccess() {
2221
    // User with view-only access should not be able to edit nodes.
2222
    try {
2223
      $query = db_select('node', 'mytab')
2224
        ->fields('mytab');
2225
      $query->addTag('node_access');
2226
      $query->addMetaData('op', 'update');
2227
      $query->addMetaData('account', $this->accessUser);
2228

    
2229
      $result = $query->execute()->fetchAll();
2230
      $this->assertEqual(count($result), 0, 'User with view-only access cannot edit nodes');
2231
    }
2232
    catch (Exception $e) {
2233
      $this->fail($e->getMessage());
2234
      $this->fail((string) $query);
2235
      $this->fail(t('Altered query is malformed'));
2236
    }
2237
  }
2238

    
2239
  /**
2240
   * Tests 'node_access' query alter override.
2241
   *
2242
   * Verifies that node_access_view_all_nodes() is called from
2243
   * node_query_node_access_alter(). We do this by checking that a user who
2244
   * normally would not have view privileges is able to view the nodes when we
2245
   * add a record to {node_access} paired with a corresponding privilege in
2246
   * hook_node_grants().
2247
   */
2248
  function testNodeQueryAlterOverride() {
2249
    $record = array(
2250
      'nid' => 0,
2251
      'gid' => 0,
2252
      'realm' => 'node_access_all',
2253
      'grant_view' => 1,
2254
      'grant_update' => 0,
2255
      'grant_delete' => 0,
2256
    );
2257
    drupal_write_record('node_access', $record);
2258

    
2259
    // Test that the noAccessUser still doesn't have the 'view'
2260
    // privilege after adding the node_access record.
2261
    drupal_static_reset('node_access_view_all_nodes');
2262
    try {
2263
      $query = db_select('node', 'mytab')
2264
        ->fields('mytab');
2265
      $query->addTag('node_access');
2266
      $query->addMetaData('op', 'view');
2267
      $query->addMetaData('account', $this->noAccessUser);
2268

    
2269
      $result = $query->execute()->fetchAll();
2270
      $this->assertEqual(count($result), 0, 'User view privileges are not overridden');
2271
    }
2272
    catch (Exception $e) {
2273
      $this->fail(t('Altered query is malformed'));
2274
    }
2275

    
2276
    // Have node_test_node_grants return a node_access_all privilege,
2277
    // to grant the noAccessUser 'view' access.  To verify that
2278
    // node_access_view_all_nodes is properly checking the specified
2279
    // $account instead of the global $user, we will log in as
2280
    // noAccessUser2.
2281
    $this->drupalLogin($this->noAccessUser2);
2282
    variable_set('node_test_node_access_all_uid', $this->noAccessUser->uid);
2283
    drupal_static_reset('node_access_view_all_nodes');
2284
    try {
2285
      $query = db_select('node', 'mytab')
2286
        ->fields('mytab');
2287
      $query->addTag('node_access');
2288
      $query->addMetaData('op', 'view');
2289
      $query->addMetaData('account', $this->noAccessUser);
2290

    
2291
      $result = $query->execute()->fetchAll();
2292
      $this->assertEqual(count($result), 4, 'User view privileges are overridden');
2293
    }
2294
    catch (Exception $e) {
2295
      $this->fail(t('Altered query is malformed'));
2296
    }
2297
    variable_del('node_test_node_access_all_uid');
2298
  }
2299
}
2300

    
2301

    
2302
/**
2303
 * Tests node_query_entity_field_access_alter().
2304
 */
2305
class NodeEntityFieldQueryAlter extends DrupalWebTestCase {
2306

    
2307
  public static function getInfo() {
2308
    return array(
2309
      'name' => 'Node entity query alter',
2310
      'description' => 'Test that node access entity queries are properly altered by the node module.',
2311
      'group' => 'Node',
2312
    );
2313
  }
2314

    
2315
  /**
2316
   * User with permission to view content.
2317
   *
2318
   * @var object
2319
   */
2320
  protected $accessUser;
2321

    
2322
  /**
2323
   * User without permission to view content.
2324
   *
2325
   * @var object
2326
   */
2327
  protected $noAccessUser;
2328

    
2329
  function setUp() {
2330
    parent::setUp('node_access_test');
2331
    node_access_rebuild();
2332

    
2333
    // Creating 4 nodes with an entity field so we can test that sort of query
2334
    // alter. All field values starts with 'A' so we can identify and fetch them
2335
    // in the node_access_test module.
2336
    $settings = array('language' => LANGUAGE_NONE);
2337
    for ($i = 0; $i < 4; $i++) {
2338
      $body = array(
2339
        'value' => 'A' . $this->randomName(32),
2340
        'format' => filter_default_format(),
2341
      );
2342
      $settings['body'][LANGUAGE_NONE][0] = $body;
2343
      $this->drupalCreateNode($settings);
2344
    }
2345

    
2346
    // Create user with simple node access permission. The 'node test view'
2347
    // permission is implemented and granted by the node_access_test module.
2348
    $this->accessUser = $this->drupalCreateUser(array('access content', 'node test view'));
2349
    $this->noAccessUser = $this->drupalCreateUser(array('access content'));
2350
  }
2351

    
2352
  /**
2353
   * Tests that node access permissions are followed.
2354
   */
2355
  function testNodeQueryAlterWithUI() {
2356
    // Verify that a user with access permission can see at least one node.
2357
    $this->drupalLogin($this->accessUser);
2358
    $this->drupalGet('node_access_entity_test_page');
2359
    $this->assertText('Yes, 4 nodes', "4 nodes were found for access user");
2360
    $this->assertNoText('Exception', "No database exception");
2361

    
2362
    // Verify that a user with no access permission cannot see nodes.
2363
    $this->drupalLogin($this->noAccessUser);
2364
    $this->drupalGet('node_access_entity_test_page');
2365
    $this->assertText('No nodes', "No nodes were found for no access user");
2366
    $this->assertNoText('Exception', "No database exception");
2367
  }
2368
}
2369

    
2370
/**
2371
 * Test node token replacement in strings.
2372
 */
2373
class NodeTokenReplaceTestCase extends DrupalWebTestCase {
2374
  public static function getInfo() {
2375
    return array(
2376
      'name' => 'Node token replacement',
2377
      'description' => 'Generates text using placeholders for dummy content to check node token replacement.',
2378
      'group' => 'Node',
2379
    );
2380
  }
2381

    
2382
  /**
2383
   * Creates a node, then tests the tokens generated from it.
2384
   */
2385
  function testNodeTokenReplacement() {
2386
    global $language;
2387
    $url_options = array(
2388
      'absolute' => TRUE,
2389
      'language' => $language,
2390
    );
2391

    
2392
    // Create a user and a node.
2393
    $account = $this->drupalCreateUser();
2394
    $settings = array(
2395
      'type' => 'article',
2396
      'uid' => $account->uid,
2397
      'title' => '<blink>Blinking Text</blink>',
2398
      'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(32), 'summary' => $this->randomName(16)))),
2399
    );
2400
    $node = $this->drupalCreateNode($settings);
2401

    
2402
    // Load node so that the body and summary fields are structured properly.
2403
    $node = node_load($node->nid);
2404
    $instance = field_info_instance('node', 'body', $node->type);
2405

    
2406
    // Generate and test sanitized tokens.
2407
    $tests = array();
2408
    $langcode = entity_language('node', $node);
2409
    $tests['[node:nid]'] = $node->nid;
2410
    $tests['[node:vid]'] = $node->vid;
2411
    $tests['[node:tnid]'] = $node->tnid;
2412
    $tests['[node:type]'] = 'article';
2413
    $tests['[node:type-name]'] = 'Article';
2414
    $tests['[node:title]'] = check_plain($node->title);
2415
    $tests['[node:body]'] = _text_sanitize($instance, $langcode, $node->body[$langcode][0], 'value');
2416
    $tests['[node:summary]'] = _text_sanitize($instance, $langcode, $node->body[$langcode][0], 'summary');
2417
    $tests['[node:language]'] = check_plain($langcode);
2418
    $tests['[node:url]'] = url('node/' . $node->nid, $url_options);
2419
    $tests['[node:edit-url]'] = url('node/' . $node->nid . '/edit', $url_options);
2420
    $tests['[node:author]'] = check_plain(format_username($account));
2421
    $tests['[node:author:uid]'] = $node->uid;
2422
    $tests['[node:author:name]'] = check_plain(format_username($account));
2423
    $tests['[node:created:since]'] = format_interval(REQUEST_TIME - $node->created, 2, $language->language);
2424
    $tests['[node:changed:since]'] = format_interval(REQUEST_TIME - $node->changed, 2, $language->language);
2425

    
2426
    // Test to make sure that we generated something for each token.
2427
    $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
2428

    
2429
    foreach ($tests as $input => $expected) {
2430
      $output = token_replace($input, array('node' => $node), array('language' => $language));
2431
      $this->assertEqual($output, $expected, format_string('Sanitized node token %token replaced.', array('%token' => $input)));
2432
    }
2433

    
2434
    // Generate and test unsanitized tokens.
2435
    $tests['[node:title]'] = $node->title;
2436
    $tests['[node:body]'] = $node->body[$langcode][0]['value'];
2437
    $tests['[node:summary]'] = $node->body[$langcode][0]['summary'];
2438
    $tests['[node:language]'] = $langcode;
2439
    $tests['[node:author:name]'] = format_username($account);
2440

    
2441
    foreach ($tests as $input => $expected) {
2442
      $output = token_replace($input, array('node' => $node), array('language' => $language, 'sanitize' => FALSE));
2443
      $this->assertEqual($output, $expected, format_string('Unsanitized node token %token replaced.', array('%token' => $input)));
2444
    }
2445
  }
2446
}
2447

    
2448
/**
2449
 * Tests user permissions for node revisions.
2450
 */
2451
class NodeRevisionPermissionsTestCase extends DrupalWebTestCase {
2452

    
2453
  /**
2454
   * Nodes used by the test.
2455
   *
2456
   * @var array
2457
   */
2458
  protected $node_revisions = array();
2459

    
2460
  /**
2461
   * Users with different revision permission used by the test.
2462
   *
2463
   * @var array
2464
   */
2465
  protected $accounts = array();
2466

    
2467
  /**
2468
   * Map revision permission names to node revision access ops.
2469
   *
2470
   * @var array
2471
   */
2472
  protected $map = array(
2473
    'view' => 'view revisions',
2474
    'update' => 'revert revisions',
2475
    'delete' => 'delete revisions',
2476
  );
2477

    
2478
  public static function getInfo() {
2479
    return array(
2480
      'name' => 'Node revision permissions',
2481
      'description' => 'Tests user permissions for node revision operations.',
2482
      'group' => 'Node',
2483
    );
2484
  }
2485

    
2486
  function setUp() {
2487
    parent::setUp();
2488

    
2489
    // Create a node with several revisions.
2490
    $node = $this->drupalCreateNode();
2491
    $this->node_revisions[] = $node;
2492

    
2493
    for ($i = 0; $i < 3; $i++) {
2494
      // Create a revision for the same nid and settings with a random log.
2495
      $revision = clone $node;
2496
      $revision->revision = 1;
2497
      $revision->log = $this->randomName(32);
2498
      node_save($revision);
2499
      $this->node_revisions[] = $revision;
2500
    }
2501

    
2502
    // Create three users, one with each revision permission.
2503
    foreach ($this->map as $op => $permission) {
2504
      // Create the user.
2505
      $account = $this->drupalCreateUser(
2506
        array(
2507
          'access content',
2508
          'edit any page content',
2509
          'delete any page content',
2510
          $permission,
2511
        )
2512
      );
2513
      $account->op = $op;
2514
      $this->accounts[] = $account;
2515
    }
2516

    
2517
    // Create an admin account (returns TRUE for all revision permissions).
2518
    $admin_account = $this->drupalCreateUser(array('access content', 'administer nodes'));
2519
    $admin_account->is_admin = TRUE;
2520
    $this->accounts['admin'] = $admin_account;
2521

    
2522
    // Create a normal account (returns FALSE for all revision permissions).
2523
    $normal_account = $this->drupalCreateUser();
2524
    $normal_account->op = FALSE;
2525
    $this->accounts[] = $normal_account;
2526
  }
2527

    
2528
  /**
2529
   * Tests the _node_revision_access() function.
2530
   */
2531
  function testNodeRevisionAccess() {
2532
    $revision = $this->node_revisions[1];
2533

    
2534
    $parameters = array(
2535
      'op' => array_keys($this->map),
2536
      'account' => $this->accounts,
2537
    );
2538

    
2539
    $permutations = $this->generatePermutations($parameters);
2540
    foreach ($permutations as $case) {
2541
      if (!empty($case['account']->is_admin) || $case['op'] == $case['account']->op) {
2542
        $this->assertTrue(_node_revision_access($revision, $case['op'], $case['account']), "{$this->map[$case['op']]} granted.");
2543
      }
2544
      else {
2545
        $this->assertFalse(_node_revision_access($revision, $case['op'], $case['account']), "{$this->map[$case['op']]} not granted.");
2546
      }
2547
    }
2548

    
2549
    // Test that access is FALSE for a node administrator with an invalid $node
2550
    // or $op parameters.
2551
    $admin_account = $this->accounts['admin'];
2552
    $this->assertFalse(_node_revision_access(FALSE, 'view', $admin_account), '_node_revision_access() returns FALSE with an invalid node.');
2553
    $this->assertFalse(_node_revision_access($revision, 'invalid-op', $admin_account), '_node_revision_access() returns FALSE with an invalid op.');
2554

    
2555
    // Test that the $account parameter defaults to the "logged in" user.
2556
    $original_user = $GLOBALS['user'];
2557
    $GLOBALS['user'] = $admin_account;
2558
    $this->assertTrue(_node_revision_access($revision, 'view'), '_node_revision_access() returns TRUE when used with global user.');
2559
    $GLOBALS['user'] = $original_user;
2560
  }
2561
}
2562

    
2563
/**
2564
 * Tests pagination with a node access module enabled.
2565
 */
2566
class NodeAccessPagerTestCase extends DrupalWebTestCase {
2567

    
2568
  public static function getInfo() {
2569
    return array(
2570
      'name' => 'Node access pagination',
2571
      'description' => 'Test access controlled node views have the right amount of comment pages.',
2572
      'group' => 'Node',
2573
    );
2574
  }
2575

    
2576
  public function setUp() {
2577
    parent::setUp('node_access_test', 'comment', 'forum');
2578
    node_access_rebuild();
2579
    $this->web_user = $this->drupalCreateUser(array('access content', 'access comments', 'node test view'));
2580
  }
2581

    
2582
  /**
2583
   * Tests the comment pager for nodes with multiple grants per realm.
2584
   */
2585
  public function testCommentPager() {
2586
    // Create a node.
2587
    $node = $this->drupalCreateNode();
2588

    
2589
    // Create 60 comments.
2590
    for ($i = 0; $i < 60; $i++) {
2591
      $comment = new stdClass();
2592
      $comment->cid = 0;
2593
      $comment->pid = 0;
2594
      $comment->uid = $this->web_user->uid;
2595
      $comment->nid = $node->nid;
2596
      $comment->subject = $this->randomName();
2597
      $comment->comment_body = array(
2598
        LANGUAGE_NONE => array(
2599
          array('value' => $this->randomName()),
2600
        ),
2601
      );
2602
      comment_save($comment);
2603
    }
2604

    
2605
    $this->drupalLogin($this->web_user);
2606

    
2607
    // View the node page. With the default 50 comments per page there should
2608
    // be two pages (0, 1) but no third (2) page.
2609
    $this->drupalGet('node/' . $node->nid);
2610
    $this->assertText($node->title);
2611
    $this->assertText(t('Comments'));
2612
    $this->assertRaw('page=1');
2613
    $this->assertNoRaw('page=2');
2614
  }
2615

    
2616
  /**
2617
   * Tests the forum node pager for nodes with multiple grants per realm.
2618
   */
2619
  public function testForumPager() {
2620
    // Look up the forums vocabulary ID.
2621
    $vid = variable_get('forum_nav_vocabulary', 0);
2622
    $this->assertTrue($vid, 'Forum navigation vocabulary ID is set.');
2623

    
2624
    // Look up the general discussion term.
2625
    $tree = taxonomy_get_tree($vid, 0, 1);
2626
    $tid = reset($tree)->tid;
2627
    $this->assertTrue($tid, 'General discussion term is found in the forum vocabulary.');
2628

    
2629
    // Create 30 nodes.
2630
    for ($i = 0; $i < 30; $i++) {
2631
      $this->drupalCreateNode(array(
2632
        'nid' => NULL,
2633
        'type' => 'forum',
2634
        'taxonomy_forums' => array(
2635
          LANGUAGE_NONE => array(
2636
            array('tid' => $tid, 'vid' => $vid, 'vocabulary_machine_name' => 'forums'),
2637
          ),
2638
        ),
2639
      ));
2640
    }
2641

    
2642
    // View the general discussion forum page. With the default 25 nodes per
2643
    // page there should be two pages for 30 nodes, no more.
2644
    $this->drupalLogin($this->web_user);
2645
    $this->drupalGet('forum/' . $tid);
2646
    $this->assertRaw('page=1');
2647
    $this->assertNoRaw('page=2');
2648
  }
2649
}
2650

    
2651

    
2652
/**
2653
 * Tests the interaction of the node access system with fields.
2654
 */
2655
class NodeAccessFieldTestCase extends NodeWebTestCase {
2656

    
2657
  public static function getInfo() {
2658
    return array(
2659
      'name' => 'Node access and fields',
2660
      'description' => 'Tests the interaction of the node access system with fields.',
2661
      'group' => 'Node',
2662
    );
2663
  }
2664

    
2665
  public function setUp() {
2666
    parent::setUp('node_access_test', 'field_ui');
2667
    node_access_rebuild();
2668

    
2669
    // Create some users.
2670
    $this->admin_user = $this->drupalCreateUser(array('access content', 'bypass node access'));
2671
    $this->content_admin_user = $this->drupalCreateUser(array('access content', 'administer content types'));
2672

    
2673
    // Add a custom field to the page content type.
2674
    $this->field_name = drupal_strtolower($this->randomName() . '_field_name');
2675
    $this->field = field_create_field(array('field_name' => $this->field_name, 'type' => 'text'));
2676
    $this->instance = field_create_instance(array(
2677
      'field_name' => $this->field_name,
2678
      'entity_type' => 'node',
2679
      'bundle' => 'page',
2680
    ));
2681
  }
2682

    
2683
  /**
2684
   * Tests administering fields when node access is restricted.
2685
   */
2686
  function testNodeAccessAdministerField() {
2687
    // Create a page node.
2688
    $langcode = LANGUAGE_NONE;
2689
    $field_data = array();
2690
    $value = $field_data[$langcode][0]['value'] = $this->randomName();
2691
    $node = $this->drupalCreateNode(array($this->field_name => $field_data));
2692

    
2693
    // Log in as the administrator and confirm that the field value is present.
2694
    $this->drupalLogin($this->admin_user);
2695
    $this->drupalGet("node/{$node->nid}");
2696
    $this->assertText($value, 'The saved field value is visible to an administrator.');
2697

    
2698
    // Log in as the content admin and try to view the node.
2699
    $this->drupalLogin($this->content_admin_user);
2700
    $this->drupalGet("node/{$node->nid}");
2701
    $this->assertText('Access denied', 'Access is denied for the content admin.');
2702

    
2703
    // Modify the field default as the content admin.
2704
    $edit = array();
2705
    $default = 'Sometimes words have two meanings';
2706
    $edit["{$this->field_name}[$langcode][0][value]"] = $default;
2707
    $this->drupalPost(
2708
      "admin/structure/types/manage/page/fields/{$this->field_name}",
2709
      $edit,
2710
      t('Save settings')
2711
    );
2712

    
2713
    // Log in as the administrator.
2714
    $this->drupalLogin($this->admin_user);
2715

    
2716
    // Confirm that the existing node still has the correct field value.
2717
    $this->drupalGet("node/{$node->nid}");
2718
    $this->assertText($value, 'The original field value is visible to an administrator.');
2719

    
2720
    // Confirm that the new default value appears when creating a new node.
2721
    $this->drupalGet('node/add/page');
2722
    $this->assertRaw($default, 'The updated default value is displayed when creating a new node.');
2723
  }
2724
}
2725

    
2726
/**
2727
 * Tests changing view modes for nodes.
2728
 */
2729
class NodeEntityViewModeAlterTest extends NodeWebTestCase {
2730

    
2731
  public static function getInfo() {
2732
    return array(
2733
      'name' => 'Node entity view mode',
2734
      'description' => 'Test changing view mode.',
2735
      'group' => 'Node'
2736
    );
2737
  }
2738

    
2739
  function setUp() {
2740
    parent::setUp(array('node_test'));
2741
  }
2742

    
2743
  /**
2744
   * Create a "Basic page" node and verify its consistency in the database.
2745
   */
2746
  function testNodeViewModeChange() {
2747
    $web_user = $this->drupalCreateUser(array('create page content', 'edit own page content'));
2748
    $this->drupalLogin($web_user);
2749

    
2750
    // Create a node.
2751
    $edit = array();
2752
    $langcode = LANGUAGE_NONE;
2753
    $edit["title"] = $this->randomName(8);
2754
    $edit["body[$langcode][0][value]"] = t('Data that should appear only in the body for the node.');
2755
    $edit["body[$langcode][0][summary]"] = t('Extra data that should appear only in the teaser for the node.');
2756
    $this->drupalPost('node/add/page', $edit, t('Save'));
2757

    
2758
    $node = $this->drupalGetNodeByTitle($edit["title"]);
2759

    
2760
    // Set the flag to alter the view mode and view the node.
2761
    variable_set('node_test_change_view_mode', 'teaser');
2762
    $this->drupalGet('node/' . $node->nid);
2763

    
2764
    // Check that teaser mode is viewed.
2765
    $this->assertText('Extra data that should appear only in the teaser for the node.', 'Teaser text present');
2766
    // Make sure body text is not present.
2767
    $this->assertNoText('Data that should appear only in the body for the node.', 'Body text not present');
2768

    
2769
    // Test that the correct build mode has been set.
2770
    $build = node_view($node);
2771
    $this->assertEqual($build['#view_mode'], 'teaser', 'The view mode has correctly been set to teaser.');
2772
  }
2773
}
2774

    
2775
/**
2776
 * Tests the cache invalidation of node operations.
2777
 */
2778
class NodePageCacheTest extends NodeWebTestCase {
2779

    
2780
  /**
2781
   * An admin user with administrative permissions for nodes.
2782
   */
2783
  protected $admin_user;
2784

    
2785
  public static function getInfo() {
2786
    return array(
2787
        'name' => 'Node page cache test',
2788
        'description' => 'Test cache invalidation of node operations.',
2789
        'group' => 'Node',
2790
    );
2791
  }
2792

    
2793
  function setUp() {
2794
    parent::setUp();
2795

    
2796
    variable_set('cache', 1);
2797
    variable_set('page_cache_maximum_age', 300);
2798

    
2799
    $this->admin_user = $this->drupalCreateUser(array(
2800
        'bypass node access',
2801
        'access content overview',
2802
        'administer nodes',
2803
    ));
2804
  }
2805

    
2806
  /**
2807
   * Tests deleting nodes clears page cache.
2808
   */
2809
  public function testNodeDelete() {
2810
    $node_path = 'node/' . $this->drupalCreateNode()->nid;
2811

    
2812
    // Populate page cache.
2813
    $this->drupalGet($node_path);
2814

    
2815
    // Login and delete the node.
2816
    $this->drupalLogin($this->admin_user);
2817
    $this->drupalPost($node_path . '/delete', array(), t('Delete'));
2818

    
2819
    // Logout and check the node is not available.
2820
    $this->drupalLogout();
2821
    $this->drupalGet($node_path);
2822
    $this->assertResponse(404);
2823

    
2824
    // Create two new nodes.
2825
    $nodes[0] = $this->drupalCreateNode();
2826
    $nodes[1] = $this->drupalCreateNode();
2827
    $node_path = 'node/' . $nodes[0]->nid;
2828

    
2829
    // Populate page cache.
2830
    $this->drupalGet($node_path);
2831

    
2832
    // Login and delete the nodes.
2833
    $this->drupalLogin($this->admin_user);
2834
    $this->drupalGet('admin/content');
2835
    $edit = array(
2836
        'operation' => 'delete',
2837
        'nodes[' . $nodes[0]->nid . ']' => TRUE,
2838
        'nodes[' . $nodes[1]->nid . ']' => TRUE,
2839
    );
2840
    $this->drupalPost(NULL, $edit, t('Update'));
2841
    $this->drupalPost(NULL, array(), t('Delete'));
2842

    
2843
    // Logout and check the node is not available.
2844
    $this->drupalLogout();
2845
    $this->drupalGet($node_path);
2846
    $this->assertResponse(404);
2847
  }
2848
}