You are here

authcache_forum.test in Authenticated User Page Caching (Authcache) 7.2

Test cases for the Authcache Forum module.

File

modules/authcache_forum/authcache_forum.test
View source
<?php

/**
 * @file
 * Test cases for the Authcache Forum module.
 */

/**
 * Tests for markup substitution.
 */
class AuthcacheForumTest extends DrupalWebTestCase {
  protected $stubmod;
  protected $member1;
  protected $member2;
  protected $editor;
  protected $forum;
  protected $topic;

  /**
   * {@inheritdoc}
   */
  public static function getInfo() {
    return array(
      'name' => 'Authcache Forum',
      'description' => 'Test markup substitution and fragment generation for Forum',
      'group' => 'Authcache Forum',
    );
  }

  /**
   * {@inheritdoc}
   */
  public function setUp() {

    // FIXME: Provide separate test stub module in order to resolve the
    // dependency for the menu-module. Stub module needs to hide all forum
    // action links, otherwise the default authcache mechanism kicks in
    // cancelling page caching.
    parent::setUp(array(
      'authcache_forum',
      'authcache_menu',
      'authcache_p13n_test',
    ));
    $this->member1 = $this
      ->drupalCreateUser(array(
      'create forum content',
      'access comments',
      'post comments',
      'edit own comments',
    ));
    $this->member2 = $this
      ->drupalCreateUser(array(
      'create forum content',
      'access comments',
      'post comments',
      'edit own comments',
    ));
    $this->editor = $this
      ->drupalCreateUser(array(
      'create forum content',
      'administer comments',
      'administer forums',
    ));
    $authcache_roles = array(
      DRUPAL_ANONYMOUS_RID => DRUPAL_ANONYMOUS_RID,
      DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID,
    ) + $this->member1->roles + $this->member2->roles + $this->editor->roles;

    // Setup authcache.
    variable_set('authcache_roles', $authcache_roles);
    $pagecaching = _authcache_default_pagecaching();
    $pagecaching[0]['roles']['roles'] = $authcache_roles;
    variable_set('authcache_pagecaching', $pagecaching);
    $this
      ->drupalLogin($this->editor);
    $this->forum = $this
      ->createForum('forum');
    $this
      ->drupalLogin($this->member1);
    $this->topic = $this
      ->createForumTopic($this->forum);

    // HookStub.
    $this->stubmod = new ModuleStub('authcache_p13n_test');
  }

  /**
   * Test whether the given stub passes the invocation verifier.
   */
  protected function assertStub(HookStubProxy $stub, $verifier, $message = NULL) {
    $result = $stub
      ->verify($verifier, $error);
    if (!$message) {
      $message = t('Verify invocation of hook @hook.', array(
        '@hook' => $stub
          ->hookname(),
      ));
    }
    if (!$result && is_string($error)) {
      $message .= ' ' . $error;
    }
    $this
      ->assertTrue($result, $message);
  }

  /**
   * Creates a forum container or a forum.
   *
   * @see ForumTestCase::createForum()
   */
  protected function createForum($type, $parent = 0) {

    // Generate a random name/description.
    $name = $this
      ->randomName(10);
    $description = $this
      ->randomName(100);
    $edit = array(
      'name' => $name,
      'description' => $description,
      'parent[0]' => $parent,
      'weight' => '0',
    );

    // Create forum.
    $this
      ->drupalPost('admin/structure/forum/add/' . $type, $edit, t('Save'));
    $this
      ->assertResponse(200);
    $type = $type == 'container' ? 'forum container' : 'forum';
    $this
      ->assertRaw(t('Created new @type %term.', array(
      '%term' => $name,
      '@type' => t($type),
    )), format_string('@type was created', array(
      '@type' => ucfirst($type),
    )));

    // Verify forum.
    $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();
    $this
      ->assertTrue(!empty($term), 'The ' . $type . ' exists in the database');

    // Verify forum hierarchy.
    $tid = $term['tid'];
    $parent_tid = db_query("SELECT t.parent FROM {taxonomy_term_hierarchy} t WHERE t.tid = :tid", array(
      ':tid' => $tid,
    ))
      ->fetchField();
    $this
      ->assertTrue($parent == $parent_tid, 'The ' . $type . ' is linked to its container');
    return $term;
  }

  /**
   * Creates forum topic.
   *
   * @see ForumTestCase::createForumTopic()
   */
  protected function createForumTopic($forum, $container = FALSE) {

    // Generate a random subject/body.
    $title = $this
      ->randomName(20);
    $body = $this
      ->randomName(200);
    $langcode = LANGUAGE_NONE;
    $edit = array(
      "title" => $title,
      "body[{$langcode}][0][value]" => $body,
    );
    $tid = $forum['tid'];

    // Create the forum topic, preselecting the forum ID via a URL parameter.
    $this
      ->drupalPost('node/add/forum/' . $tid, $edit, t('Save'));
    $type = t('Forum topic');
    if ($container) {
      $this
        ->assertNoRaw(t('@type %title has been created.', array(
        '@type' => $type,
        '%title' => $title,
      )), 'Forum topic was not created');
      $this
        ->assertRaw(t('The item %title is a forum container, not a forum.', array(
        '%title' => $forum['name'],
      )), 'Error message was shown');
      return;
    }
    else {
      $this
        ->assertRaw(t('@type %title has been created.', array(
        '@type' => $type,
        '%title' => $title,
      )), 'Forum topic was created');
      $this
        ->assertNoRaw(t('The item %title is a forum container, not a forum.', array(
        '%title' => $forum['name'],
      )), 'No error message was shown');
    }

    // Retrieve node object, ensure that the topic was created and in the proper
    // forum.
    $node = $this
      ->drupalGetNodeByTitle($title);
    $this
      ->assertTrue($node != NULL, format_string('Node @title was loaded', array(
      '@title' => $title,
    )));
    $this
      ->assertEqual($node->taxonomy_forums[LANGUAGE_NONE][0]['tid'], $tid, 'Saved forum topic was in the expected forum');

    // View forum topic.
    $this
      ->drupalGet('node/' . $node->nid);
    $this
      ->assertRaw($title, 'Subject was found');
    $this
      ->assertRaw($body, 'Body was found');
    return $node;
  }

  /**
   * Post comment.
   *
   * @see CommentHelperCase::postComment()
   */
  protected function postComment($node, $comment, $subject = '', $contact = NULL) {
    $langcode = LANGUAGE_NONE;
    $edit = array();
    $edit['comment_body[' . $langcode . '][0][value]'] = $comment;
    $preview_mode = variable_get('comment_preview_article', DRUPAL_OPTIONAL);
    $subject_mode = variable_get('comment_subject_field_article', 1);

    // Must get the page before we test for fields.
    if ($node !== NULL) {
      $this
        ->drupalGet('comment/reply/' . $node->nid);
    }
    if ($subject_mode == TRUE) {
      $edit['subject'] = $subject;
    }
    else {
      $this
        ->assertNoFieldByName('subject', '', 'Subject field not found.');
    }
    if ($contact !== NULL && is_array($contact)) {
      $edit += $contact;
    }
    switch ($preview_mode) {
      case DRUPAL_REQUIRED:

        // Preview required so no save button should be found.
        $this
          ->assertNoFieldByName('op', t('Save'), 'Save button not found.');
        $this
          ->drupalPost(NULL, $edit, t('Preview'));

      // Don't break here so that we can test post-preview field presence and
      // function below.
      case DRUPAL_OPTIONAL:
        $this
          ->assertFieldByName('op', t('Preview'), 'Preview button found.');
        $this
          ->assertFieldByName('op', t('Save'), 'Save button found.');
        $this
          ->drupalPost(NULL, $edit, t('Save'));
        break;
      case DRUPAL_DISABLED:
        $this
          ->assertNoFieldByName('op', t('Preview'), 'Preview button not found.');
        $this
          ->assertFieldByName('op', t('Save'), 'Save button found.');
        $this
          ->drupalPost(NULL, $edit, t('Save'));
        break;
    }
    $match = array();

    // Get comment ID.
    preg_match('/#comment-([0-9]+)/', $this
      ->getURL(), $match);

    // Get comment.
    if ($contact !== TRUE) {
      if ($subject) {
        $this
          ->assertText($subject, 'Comment subject posted.');
      }
      $this
        ->assertText($comment, 'Comment body posted.');
      $this
        ->assertTrue(!empty($match) && !empty($match[1]), 'Comment id found.');
    }
    if (isset($match[1])) {
      return (object) array(
        'id' => $match[1],
        'subject' => $subject,
        'comment' => $comment,
      );
    }
  }

  /**
   * Markup substitution forum overview page.
   *
   * Cover authcache_forum_preprocess_forum_list().
   *
   * @see AuthcacheCommentTest::testNumberOfNewComments()
   */
  public function testForumList() {
    $this->stubmod
      ->hook('authcache_p13n_client', array(
      'authcache_p13n_test' => array(
        'title' => t('Test Client'),
        'enabled' => TRUE,
      ),
    ));

    // M2: Post a comment on the topic.
    $this
      ->drupalLogin($this->member2);
    $comment = $this
      ->postComment($this->topic, $this
      ->randomName(8));
    $this
      ->drupalLogout();

    // Simulate M1 visiting the node a minute ago.
    db_merge('history')
      ->key(array(
      'uid' => $this->member1->uid,
      'nid' => $this->topic->nid,
    ))
      ->fields(array(
      'timestamp' => time() - 60,
    ))
      ->execute();

    // M1: Accesses the forum list. Normally a link '1 new' will be shown next
    // to the forum. However Authcache Forum will substitute the
    // number-of-topics-with-new-comments link with a placeholder.
    $this
      ->drupalLogin($this->member1);
    $setting_markup = $this
      ->randomName(8);
    $setting_stub = HookStub::on('theme_authcache_p13n_setting__authcache_p13n_test', $setting_markup);
    $this
      ->drupalGet('forum');
    $this
      ->assertNoText('1 new');
    $default_icons = $this
      ->xpath('//div[contains(@class, :icon) and contains(@class, :status)]', array(
      ':icon' => 'icon',
      ':status' => 'forum-status-default',
    ));
    $this
      ->assertTrue($default_icons, 'Icons with default status present');
    $new_icons = $this
      ->xpath('//div[contains(@class, :icon) and contains(@class, :status)]', array(
      ':icon' => 'icon',
      ':status' => 'forum-status-new',
    ));
    $this
      ->assertFalse($new_icons, 'No icons with new-status present');
    $this
      ->assertText($setting_markup, 'Replace "1 new" link with a setting');
    $this
      ->assertStub($setting_stub, HookStub::once());
    $this
      ->assertIdentical(1, count($this
      ->xpath('//span[@class=:class and @data-p13n-tid=:tid]', array(
      ':class' => 'authcache-forum-num-new',
      ':tid' => $this->forum['tid'],
    ))), 'Replace "1 new" link with placeholder markup');

    // M1: Visit the topic in order to clear the new-comments marker.
    $this
      ->drupalGet('node/' . $this->topic->nid);

    // M1: Repeat the test on the forum-list. Even though there are no new
    // topics, the markup substitution must still take place.
    $setting_markup = $this
      ->randomName(8);
    $setting_stub = HookStub::on('theme_authcache_p13n_setting__authcache_p13n_test', $setting_markup);
    $this
      ->drupalGet('forum');
    $this
      ->assertText($setting_markup, 'Render setting even though there is no new topic');
    $this
      ->assertStub($setting_stub, HookStub::once());
    $this
      ->assertIdentical(1, count($this
      ->xpath('//span[@class=:class and @data-p13n-tid=:tid]', array(
      ':class' => 'authcache-forum-num-new',
      ':tid' => $this->forum['tid'],
    ))), 'Generate placeholder markup even though there is no new topic');
  }

  /**
   * Markup substitution on forum topic list.
   *
   * Covers authcache_forum_preprocess_forum_topic_list,
   * authcache_forum_preprocess_forum_icon.
   */
  public function testForumTopicList() {
    $this->stubmod
      ->hook('authcache_p13n_client', array(
      'authcache_p13n_test' => array(
        'title' => t('Test Client'),
        'enabled' => TRUE,
      ),
    ));

    // M2: Post a comment on the topic.
    $this
      ->drupalLogin($this->member2);
    $comment = $this
      ->postComment($this->topic, $this
      ->randomName(8));
    $this
      ->drupalLogout();

    // Simulate M1 visiting the node a minute ago.
    db_merge('history')
      ->key(array(
      'uid' => $this->member1->uid,
      'nid' => $this->topic->nid,
    ))
      ->fields(array(
      'timestamp' => time() - 60,
    ))
      ->execute();

    // M1: Accesses the topic list. Normally a link '1 new' will be shown next
    // to the topic. However Authcache Forum will substitute the
    // number-of-new-comments link with a placeholder.
    $this
      ->drupalLogin($this->member1);
    $setting_markup = $this
      ->randomName(8);
    $setting_stub = HookStub::on('theme_authcache_p13n_setting__authcache_p13n_test', $setting_markup);
    $this
      ->drupalGet('forum/' . $this->forum['tid']);
    $this
      ->assertNoText('1 new');
    $default_icons = $this
      ->xpath('//div[contains(@class, :class)]', array(
      ':class' => 'topic-status-default',
    ));
    $this
      ->assertTrue($default_icons, 'Icons with default status present');
    $new_icons = $this
      ->xpath('//div[contains(@class, :class)]', array(
      ':class' => 'topic-status-new',
    ));
    $this
      ->assertFalse($new_icons, 'No icons with new-status present');
    $this
      ->assertText($setting_markup, 'Replace "1 new" link with a setting');
    $this
      ->assertStub($setting_stub, HookStub::once());
    $this
      ->assertIdentical(1, count($this
      ->xpath('//span[@class=:class and @data-p13n-nid=:nid]', array(
      ':class' => 'authcache-forum-topic-num-new',
      ':nid' => $this->topic->nid,
    ))), 'Replace "1 new" link with placeholder markup');

    // M1: Access it again but with lower hot-threshold in order to ensure that
    // icon class still does not change.
    variable_set('forum_hot_topic', 0);
    $setting_markup = $this
      ->randomName(8);
    $setting_stub = HookStub::on('theme_authcache_p13n_setting__authcache_p13n_test', $setting_markup);
    $this
      ->drupalGet('forum/' . $this->forum['tid']);
    $this
      ->assertNoText('1 new');
    $default_icons = $this
      ->xpath('//div[contains(@class, :class)]', array(
      ':class' => 'topic-status-hot',
    ));
    $this
      ->assertTrue($default_icons, 'Icons with hot status present');
    $new_icons = $this
      ->xpath('//div[contains(@class, :class)]', array(
      ':class' => 'topic-status-hot-new',
    ));
    $this
      ->assertFalse($new_icons, 'No icons with hot-new-status present');
    $this
      ->assertText($setting_markup, 'Replace "1 new" link with a setting');
    $this
      ->assertStub($setting_stub, HookStub::once());
    $this
      ->assertIdentical(1, count($this
      ->xpath('//span[@class=:class and @data-p13n-nid=:nid]', array(
      ':class' => 'authcache-forum-topic-num-new',
      ':nid' => $this->topic->nid,
    ))), 'Replace "1 new" link with placeholder markup');
    variable_del('forum_hot_topic');

    // M1: Visit the topic in order to clear the new-comments marker.
    $this
      ->drupalGet('node/' . $this->topic->nid);

    // M1: Repeat the test on the forum-list. Even though there are no new
    // comments, the markup substitution must still take place.
    $setting_markup = $this
      ->randomName(8);
    $setting_stub = HookStub::on('theme_authcache_p13n_setting__authcache_p13n_test', $setting_markup);
    $this
      ->drupalGet('forum/' . $this->forum['tid']);
    $this
      ->assertText($setting_markup, 'Render setting even though there is no new comment');
    $this
      ->assertStub($setting_stub, HookStub::once());
    $this
      ->assertIdentical(1, count($this
      ->xpath('//span[@class=:class and @data-p13n-nid=:nid]', array(
      ':class' => 'authcache-forum-topic-num-new',
      ':nid' => $this->topic->nid,
    ))), 'Generate placeholder markup even though there is no new comment');
  }

  /**
   * Ensure that the number of new topics is reported accurately.
   *
   * Covers AuthcacheForumListNewTopicsFragment
   */
  public function testAuthcacheForumListNewTopicsFragment() {

    // M1: Login and retrieve number-of-new-topics-setting for forum list.
    $this
      ->drupalLogin($this->member1);
    $url = authcache_p13n_request_get_callback('setting/forum-num-new', array(
      'fn' => array(
        $this->forum['tid'],
      ),
    ));
    $this
      ->assertTrue($url);
    $result = $this
      ->drupalGetAJAX($GLOBALS['base_root'] . $url['path'], $url['options'], array(
      'X-Authcache: 1',
    ));
    $expect = array(
      'authcacheForumNumNew' => array(),
    );
    $this
      ->assertEqual($expect, $result, 'Should not report any new topics, member1 is the owner of the topic');

    // M2: Login and retrieve number-of-new-topics-setting for forum list.
    $this
      ->drupalLogin($this->member2);
    $result = $this
      ->drupalGetAJAX($GLOBALS['base_root'] . $url['path'], $url['options'], array(
      'X-Authcache: 1',
    ));
    $expect = array(
      'authcacheForumNumNew' => array(
        $this->forum['tid'] => 1,
      ),
    );
    $this
      ->assertEqual($expect, $result, 'Should report one new topic for member2');
  }

}

Classes

Namesort descending Description
AuthcacheForumTest Tests for markup substitution.