| 1 |
<?php
|
| 2 |
// $Id: forum.test,v 1.36 2009/10/24 05:13:44 webchick Exp $
|
| 3 |
|
| 4 |
class ForumTestCase extends DrupalWebTestCase {
|
| 5 |
protected $admin_user;
|
| 6 |
protected $own_user;
|
| 7 |
protected $any_user;
|
| 8 |
protected $nid_user;
|
| 9 |
protected $container;
|
| 10 |
protected $forum;
|
| 11 |
protected $root_forum;
|
| 12 |
protected $nids;
|
| 13 |
|
| 14 |
public static function getInfo() {
|
| 15 |
return array(
|
| 16 |
'name' => 'Forum functionality',
|
| 17 |
'description' => 'Create, view, edit, delete, and change forum entries and verify its consistency in the database.',
|
| 18 |
'group' => 'Forum',
|
| 19 |
);
|
| 20 |
}
|
| 21 |
|
| 22 |
/**
|
| 23 |
* Enable modules and create users with specific permissions.
|
| 24 |
*/
|
| 25 |
function setUp() {
|
| 26 |
parent::setUp('taxonomy', 'comment', 'forum');
|
| 27 |
// Create users.
|
| 28 |
$this->admin_user = $this->drupalCreateUser(array('administer blocks', 'administer forums', 'administer menu', 'administer taxonomy', 'create forum content')); // 'access administration pages'));
|
| 29 |
$this->own_user = $this->drupalCreateUser(array('create forum content', 'edit own forum content', 'delete own forum content'));
|
| 30 |
$this->any_user = $this->drupalCreateUser(array('create forum content', 'edit any forum content', 'delete any forum content', 'access administration pages'));
|
| 31 |
$this->nid_user = $this->drupalCreateUser(array());
|
| 32 |
}
|
| 33 |
|
| 34 |
/**
|
| 35 |
* Login users, create forum nodes, and test forum functionality through the admin and user interfaces.
|
| 36 |
*/
|
| 37 |
function testForum() {
|
| 38 |
// Do the admin tests.
|
| 39 |
$this->doAdminTests($this->admin_user);
|
| 40 |
// Generate topics to populate the active forum block.
|
| 41 |
$this->generateForumTopics($this->forum);
|
| 42 |
|
| 43 |
// Login the nid user to view the forum topics and generate an active forum
|
| 44 |
// topics list.
|
| 45 |
$this->drupalLogin($this->nid_user);
|
| 46 |
$this->viewForumTopics($this->nids);
|
| 47 |
|
| 48 |
// Do basic tests for the any forum user.
|
| 49 |
$this->doBasicTests($this->any_user, TRUE);
|
| 50 |
|
| 51 |
// Create another forum node for the any forum user.
|
| 52 |
$node = $this->createForumTopic($this->forum, FALSE);
|
| 53 |
|
| 54 |
// Do basic tests for the own forum user.
|
| 55 |
$this->doBasicTests($this->own_user, FALSE);
|
| 56 |
|
| 57 |
// Verify the own forum user only has access to the forum view node.
|
| 58 |
$this->verifyForums($this->any_user, $node, FALSE, 403);
|
| 59 |
// Create another forum node for the own forum user.
|
| 60 |
$node = $this->createForumTopic($this->forum, FALSE);
|
| 61 |
|
| 62 |
// Login the any forum user.
|
| 63 |
$this->drupalLogin($this->any_user);
|
| 64 |
// Verify the any forum user has access to all the forum nodes.
|
| 65 |
$this->verifyForums($this->own_user, $node, TRUE);
|
| 66 |
|
| 67 |
// Verify the topic and post counts on the forum page.
|
| 68 |
$this->drupalGet('forum');
|
| 69 |
$this->assertRaw("<td class=\"topics\">\n 6 </td>");
|
| 70 |
$this->assertRaw('<td class="posts">6</td>');
|
| 71 |
|
| 72 |
// Test loading multiple forum nodes on the front page.
|
| 73 |
$this->drupalLogin($this->drupalCreateUser(array('administer content types', 'create forum content')));
|
| 74 |
$this->drupalPost('admin/structure/types/manage/forum', array('node_options[promote]' => 'promote'), t('Save content type'));
|
| 75 |
$this->createForumTopic($this->forum, FALSE);
|
| 76 |
$this->createForumTopic($this->forum, FALSE);
|
| 77 |
$this->drupalGet('node');
|
| 78 |
}
|
| 79 |
|
| 80 |
/**
|
| 81 |
* Run admin tests on the admin user.
|
| 82 |
*
|
| 83 |
* @param object $user The logged in user.
|
| 84 |
*/
|
| 85 |
private function doAdminTests($user) {
|
| 86 |
// Login the user.
|
| 87 |
$this->drupalLogin($user);
|
| 88 |
|
| 89 |
// Enable the active forum block.
|
| 90 |
$edit = array();
|
| 91 |
$edit['forum_active[region]'] = 'sidebar_second';
|
| 92 |
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
| 93 |
$this->assertResponse(200);
|
| 94 |
$this->assertText(t('The block settings have been updated.'), t('Active forum topics forum block was enabled'));
|
| 95 |
|
| 96 |
// Enable the new forum block.
|
| 97 |
$edit = array();
|
| 98 |
$edit['forum_new[region]'] = 'sidebar_second';
|
| 99 |
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
| 100 |
$this->assertResponse(200);
|
| 101 |
$this->assertText(t('The block settings have been updated.'), t('[New forum topics] Forum block was enabled'));
|
| 102 |
|
| 103 |
// Retrieve forum menu id.
|
| 104 |
$mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = 'forum' AND menu_name = 'navigation' AND module = 'system' ORDER BY mlid ASC", 0, 1)->fetchField();
|
| 105 |
|
| 106 |
// Add forum to navigation menu.
|
| 107 |
$edit = array();
|
| 108 |
$this->drupalPost('admin/structure/menu/manage/navigation', $edit, t('Save configuration'));
|
| 109 |
$this->assertResponse(200);
|
| 110 |
|
| 111 |
// Edit forum taxonomy.
|
| 112 |
// Restoration of the settings fails and causes subsequent tests to fail.
|
| 113 |
$this->container = $this->editForumTaxonomy();
|
| 114 |
// Create forum container.
|
| 115 |
$this->container = $this->createForum('container');
|
| 116 |
// Create forum inside the forum container.
|
| 117 |
$this->forum = $this->createForum('forum', $this->container['tid']);
|
| 118 |
// Create second forum in container.
|
| 119 |
$this->delete_forum = $this->createForum('forum', $this->container['tid']);
|
| 120 |
// Delete this second form.
|
| 121 |
$this->deleteForum($this->delete_forum['tid']);
|
| 122 |
// Create forum at the top (root) level.
|
| 123 |
$this->root_forum = $this->createForum('forum');
|
| 124 |
}
|
| 125 |
|
| 126 |
/**
|
| 127 |
* Edit the forum taxonomy.
|
| 128 |
*/
|
| 129 |
function editForumTaxonomy() {
|
| 130 |
// Backup forum taxonomy.
|
| 131 |
$vid = variable_get('forum_nav_vocabulary', '');
|
| 132 |
$original_settings = taxonomy_vocabulary_load($vid);
|
| 133 |
|
| 134 |
// Generate a random name/description.
|
| 135 |
$title = $this->randomName(10);
|
| 136 |
$description = $this->randomName(100);
|
| 137 |
|
| 138 |
$edit = array(
|
| 139 |
'name' => $title,
|
| 140 |
'description' => $description,
|
| 141 |
'machine_name' => drupal_strtolower(drupal_substr($this->randomName(), 3, 9)),
|
| 142 |
);
|
| 143 |
|
| 144 |
// Edit the vocabulary.
|
| 145 |
$this->drupalPost('admin/structure/taxonomy/' . $vid, $edit, t('Save'));
|
| 146 |
$this->assertResponse(200);
|
| 147 |
$this->assertRaw(t('Updated vocabulary %name.', array('%name' => $title)), t('Vocabulary was edited'));
|
| 148 |
|
| 149 |
// Grab the newly edited vocabulary.
|
| 150 |
entity_get_controller('taxonomy_vocabulary')->resetCache();
|
| 151 |
$current_settings = taxonomy_vocabulary_load($vid);
|
| 152 |
|
| 153 |
// Make sure we actually edited the vocabulary properly.
|
| 154 |
$this->assertEqual($current_settings->name, $title, t('The name was updated'));
|
| 155 |
$this->assertEqual($current_settings->description, $description, t('The description was updated'));
|
| 156 |
|
| 157 |
// Restore the original vocabulary.
|
| 158 |
taxonomy_vocabulary_save($original_settings);
|
| 159 |
drupal_static_reset('taxonomy_vocabulary_load');
|
| 160 |
$current_settings = taxonomy_vocabulary_load($vid);
|
| 161 |
$this->assertEqual($current_settings->name, $original_settings->name, 'The original vocabulary settings were restored');
|
| 162 |
}
|
| 163 |
|
| 164 |
/**
|
| 165 |
* Create a forum container or a forum.
|
| 166 |
*
|
| 167 |
* @param $type
|
| 168 |
* Forum type (forum container or forum).
|
| 169 |
* @param $parent
|
| 170 |
* Forum parent (default = 0 = a root forum; >0 = a forum container or
|
| 171 |
* another forum).
|
| 172 |
* @return
|
| 173 |
* taxonomy_term_data created.
|
| 174 |
*/
|
| 175 |
function createForum($type, $parent = 0) {
|
| 176 |
// Generate a random name/description.
|
| 177 |
$name = $this->randomName(10);
|
| 178 |
$description = $this->randomName(100);
|
| 179 |
|
| 180 |
$edit = array(
|
| 181 |
'name' => $name,
|
| 182 |
'description' => $description,
|
| 183 |
'parent[0]' => $parent,
|
| 184 |
'weight' => '0',
|
| 185 |
);
|
| 186 |
|
| 187 |
// Create forum.
|
| 188 |
$this->drupalPost('admin/structure/forum/add/' . $type, $edit, t('Save'));
|
| 189 |
$this->assertResponse(200);
|
| 190 |
$type = ($type == 'container') ? 'forum container' : 'forum';
|
| 191 |
$this->assertRaw(t('Created new @type %term.', array('%term' => $name, '@type' => t($type))), t(ucfirst($type) . ' was created'));
|
| 192 |
|
| 193 |
// Verify forum.
|
| 194 |
$term = db_query("SELECT * FROM {taxonomy_term_data} t WHERE t.vid = :vid AND t.name = :name AND t.description = :desc", array(':vid' => variable_get('forum_nav_vocabulary', ''), ':name' => $name, ':desc' => $description))->fetchAssoc();
|
| 195 |
$this->assertTrue(!empty($term), 'The ' . $type . ' exists in the database');
|
| 196 |
|
| 197 |
// Verify forum hierarchy.
|
| 198 |
$tid = $term['tid'];
|
| 199 |
$parent_tid = db_query("SELECT t.parent FROM {taxonomy_term_hierarchy} t WHERE t.tid = :tid", array(':tid' => $tid))->fetchField();
|
| 200 |
$this->assertTrue($parent == $parent_tid, 'The ' . $type . ' is linked to its container');
|
| 201 |
|
| 202 |
return $term;
|
| 203 |
}
|
| 204 |
|
| 205 |
/**
|
| 206 |
* Delete a forum.
|
| 207 |
*
|
| 208 |
* @param $tid
|
| 209 |
* The forum ID.
|
| 210 |
*/
|
| 211 |
function deleteForum($tid) {
|
| 212 |
// Delete the forum.
|
| 213 |
$this->drupalPost('admin/structure/forum/edit/forum/' . $tid, array(), t('Delete'));
|
| 214 |
$this->drupalPost(NULL, array(), t('Delete'));
|
| 215 |
|
| 216 |
// Assert that the forum no longer exists.
|
| 217 |
$this->drupalGet('forum/' . $tid);
|
| 218 |
$this->assertRaw(t('No forums defined'), 'The forum was not found');
|
| 219 |
}
|
| 220 |
|
| 221 |
/**
|
| 222 |
* Run basic tests on the indicated user.
|
| 223 |
*
|
| 224 |
* @param $user
|
| 225 |
* The logged in user.
|
| 226 |
* @param $admin
|
| 227 |
* User has 'access administration pages' privilege.
|
| 228 |
*/
|
| 229 |
private function doBasicTests($user, $admin) {
|
| 230 |
// Login the user.
|
| 231 |
$this->drupalLogin($user);
|
| 232 |
// Attempt to create forum topic under a container.
|
| 233 |
$this->createForumTopic($this->container, TRUE);
|
| 234 |
// Create forum node.
|
| 235 |
$node = $this->createForumTopic($this->forum, FALSE);
|
| 236 |
// Verify the user has access to all the forum nodes.
|
| 237 |
$this->verifyForums($user, $node, $admin);
|
| 238 |
}
|
| 239 |
|
| 240 |
/**
|
| 241 |
* Create forum topic.
|
| 242 |
*
|
| 243 |
* @param array $forum Forum array.
|
| 244 |
* @param boolean $container True if $forum is a container.
|
| 245 |
* @return object Topic node created.
|
| 246 |
*/
|
| 247 |
function createForumTopic($forum, $container = FALSE) {
|
| 248 |
// Generate a random subject/body.
|
| 249 |
$title = $this->randomName(20);
|
| 250 |
$body = $this->randomName(200);
|
| 251 |
|
| 252 |
// Without this being set, post variable equals the first non-blank in
|
| 253 |
// select items list.
|
| 254 |
$tid = $forum['tid'];
|
| 255 |
|
| 256 |
$langcode = FIELD_LANGUAGE_NONE;
|
| 257 |
$edit = array(
|
| 258 |
"title[$langcode][0][value]" => $title,
|
| 259 |
"body[$langcode][0][value]" => $body,
|
| 260 |
"taxonomy_forums[$langcode][value]" => $tid,
|
| 261 |
);
|
| 262 |
|
| 263 |
// TODO The taxonomy select value is set by drupal code when the tid is part
|
| 264 |
// of the url. However, unless a tid is passed in the edit array, when
|
| 265 |
// drupalPost() runs, the select value is not preserved. Instead, the post
|
| 266 |
// variables seem to pick up the first non-blank value in the select list.
|
| 267 |
// Create forum topic.
|
| 268 |
$this->drupalPost('node/add/forum/', $edit, t('Save'));
|
| 269 |
$type = t('Forum topic');
|
| 270 |
if ($container) {
|
| 271 |
$this->assertNoRaw(t('@type %title has been created.', array('@type' => $type, '%title' => $title)), t('Forum topic was not created'));
|
| 272 |
$this->assertRaw(t('The item %title is only a container for forums.', array('%title' => $forum['name'])), t('Error message was shown'));
|
| 273 |
return;
|
| 274 |
}
|
| 275 |
else {
|
| 276 |
$this->assertRaw(t('@type %title has been created.', array('%title' => $title, '@type' => $type)), t('Forum topic was created'));
|
| 277 |
$this->assertNoRaw(t('The item %title is only a container for forums.', array('%title' => $forum['name'])), t('No error message was shown'));
|
| 278 |
}
|
| 279 |
|
| 280 |
// Retrieve node object.
|
| 281 |
$node = $this->drupalGetNodeByTitle($title);
|
| 282 |
$this->assertTrue($node != NULL, t('Node @title was loaded', array('@title' => $title)));
|
| 283 |
|
| 284 |
// View forum topic.
|
| 285 |
$this->drupalGet('node/' . $node->nid);
|
| 286 |
$this->assertRaw($title, t('Subject was found'));
|
| 287 |
$this->assertRaw($body, t('Body was found'));
|
| 288 |
|
| 289 |
return $node;
|
| 290 |
}
|
| 291 |
|
| 292 |
/**
|
| 293 |
* Verify the logged in user has access to a forum nodes.
|
| 294 |
*
|
| 295 |
* @param $node_user
|
| 296 |
* The user who creates the node.
|
| 297 |
* @param $node
|
| 298 |
* The node being checked.
|
| 299 |
* @param $admin
|
| 300 |
* Boolean to indicate whether the user can 'access administration pages'.
|
| 301 |
* @param $response
|
| 302 |
* The exptected HTTP response code.
|
| 303 |
*/
|
| 304 |
private function verifyForums($node_user, stdClass $node, $admin, $response = 200) {
|
| 305 |
$crumb = '›';
|
| 306 |
$quote = ''';
|
| 307 |
|
| 308 |
$response2 = ($admin) ? 200 : 403;
|
| 309 |
|
| 310 |
// View forum help node.
|
| 311 |
$this->drupalGet('admin/help/forum');
|
| 312 |
$this->assertResponse($response2);
|
| 313 |
if ($response2 == 200) {
|
| 314 |
$this->assertTitle(t('Forum | Drupal'), t('Forum help title was displayed'));
|
| 315 |
$this->assertText(t('Forum'), t('Forum help node was displayed'));
|
| 316 |
}
|
| 317 |
|
| 318 |
// Verify the forum blocks were displayed.
|
| 319 |
$this->drupalGet('');
|
| 320 |
$this->assertResponse(200);
|
| 321 |
$this->assertText(t('New forum topics'), t('[New forum topics] Forum block was displayed'));
|
| 322 |
|
| 323 |
// View forum container page.
|
| 324 |
$this->verifyForumView($this->container);
|
| 325 |
// View forum page.
|
| 326 |
$this->verifyForumView($this->forum, $this->container);
|
| 327 |
// View root forum page.
|
| 328 |
$this->verifyForumView($this->root_forum);
|
| 329 |
|
| 330 |
// View forum node.
|
| 331 |
$this->drupalGet('node/' . $node->nid);
|
| 332 |
$this->assertResponse(200);
|
| 333 |
$this->assertTitle($node->title[FIELD_LANGUAGE_NONE][0]['value'] . ' | Drupal', t('Forum node was displayed'));
|
| 334 |
$this->assertText(t('Home ' . $crumb . ' Forums ' . $crumb . ' @container ' . $crumb . ' @forum', array('@container' => $this->container['name'], '@forum' => $this->forum['name'])), t('Breadcrumbs were displayed'));
|
| 335 |
|
| 336 |
// View forum edit node.
|
| 337 |
$this->drupalGet('node/' . $node->nid . '/edit');
|
| 338 |
$this->assertResponse($response);
|
| 339 |
if ($response == 200) {
|
| 340 |
$this->assertTitle('Edit Forum topic ' . $node->title[FIELD_LANGUAGE_NONE][0]['value'] . ' | Drupal', t('Forum edit node was displayed'));
|
| 341 |
}
|
| 342 |
|
| 343 |
if ($response == 200) {
|
| 344 |
// Edit forum node (including moving it to another forum).
|
| 345 |
$edit = array();
|
| 346 |
$langcode = FIELD_LANGUAGE_NONE;
|
| 347 |
$edit["title[$langcode][0][value]"] = 'node/' . $node->nid;
|
| 348 |
$edit["body[$langcode][0][value]"] = $this->randomName(256);
|
| 349 |
// Assume the topic is initially associated with $forum.
|
| 350 |
$edit["taxonomy_forums[$langcode][value]"] = $this->root_forum['tid'];
|
| 351 |
$edit['shadow'] = TRUE;
|
| 352 |
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
| 353 |
$this->assertRaw(t('Forum topic %title has been updated.', array('%title' => $edit["title[$langcode][0][value]"])), t('Forum node was edited'));
|
| 354 |
|
| 355 |
// Verify topic was moved to a different forum.
|
| 356 |
$forum_tid = db_query("SELECT tid FROM {forum} WHERE nid = :nid AND vid = :vid", array(
|
| 357 |
':nid' => $node->nid,
|
| 358 |
':vid' => $node->vid,
|
| 359 |
))->fetchField();
|
| 360 |
$this->assertTrue($forum_tid == $this->root_forum['tid'], 'The forum topic is linked to a different forum');
|
| 361 |
|
| 362 |
// Delete forum node.
|
| 363 |
$this->drupalPost('node/' . $node->nid . '/delete', array(), t('Delete'));
|
| 364 |
$this->assertResponse($response);
|
| 365 |
$this->assertRaw(t('Forum topic %title has been deleted.', array('%title' => $edit["title[$langcode][0][value]"])), t('Forum node was deleted'));
|
| 366 |
}
|
| 367 |
}
|
| 368 |
|
| 369 |
/**
|
| 370 |
* Verify display of forum page.
|
| 371 |
*
|
| 372 |
* @param $forum
|
| 373 |
* A row from taxonomy_term_data table in array.
|
| 374 |
*/
|
| 375 |
private function verifyForumView($forum, $parent = NULL) {
|
| 376 |
$crumb = '›';
|
| 377 |
|
| 378 |
// View forum page.
|
| 379 |
$this->drupalGet('forum/' . $forum['tid']);
|
| 380 |
$this->assertResponse(200);
|
| 381 |
$this->assertTitle($forum['name'] . ' | Drupal', t('Forum name was displayed'));
|
| 382 |
if (isset($parent)) {
|
| 383 |
$this->assertText(t('Home ' . $crumb . ' Forums ' . $crumb . ' @name', array('@name' => $parent['name'])), t('Breadcrumbs were displayed'));
|
| 384 |
}
|
| 385 |
else {
|
| 386 |
$this->assertText(t('Home ' . $crumb . ' Forums'), t('Breadcrumbs were displayed'));
|
| 387 |
}
|
| 388 |
}
|
| 389 |
|
| 390 |
/**
|
| 391 |
* Generate forum topics to test display of active forum block.
|
| 392 |
*
|
| 393 |
* @param array $forum Forum array (a row from taxonomy_term_data table).
|
| 394 |
*/
|
| 395 |
private function generateForumTopics($forum) {
|
| 396 |
$this->nids = array();
|
| 397 |
for ($i = 0; $i < 5; $i++) {
|
| 398 |
$node = $this->createForumTopic($this->forum, FALSE);
|
| 399 |
$this->nids[] = $node->nid;
|
| 400 |
}
|
| 401 |
}
|
| 402 |
|
| 403 |
/**
|
| 404 |
* View forum topics to test display of active forum block.
|
| 405 |
*
|
| 406 |
* @todo The logic here is completely incorrect, since the active
|
| 407 |
* forum topics block is determined by comments on the node, not by views.
|
| 408 |
* @todo DIE
|
| 409 |
*
|
| 410 |
* @param $nids
|
| 411 |
* An array of forum node IDs.
|
| 412 |
*/
|
| 413 |
private function viewForumTopics($nids) {
|
| 414 |
$crumb = '›';
|
| 415 |
|
| 416 |
for ($i = 0; $i < 2; $i++) {
|
| 417 |
foreach ($nids as $nid) {
|
| 418 |
$this->drupalGet('node/' . $nid);
|
| 419 |
$this->drupalGet('node/' . $nid);
|
| 420 |
$this->drupalGet('node/' . $nid);
|
| 421 |
}
|
| 422 |
}
|
| 423 |
}
|
| 424 |
}
|