You are here

book_access_test_case.test in Book access 7.2

File

book_access_test_case.test
View source
<?php

class BookAccessTestCase extends DrupalWebTestCase {
  protected $profile = 'testing';
  protected $books;
  protected $nodes;
  private $author;
  private $adminRole;
  public static function getInfo() {
    return array(
      'name' => 'Book Access tester',
      'description' => 'Unit test cases for book access module.',
      'group' => 'Book access',
    );
  }
  function setUp() {
    parent::setUp('book', 'book_access', 'book_access_ui');
    $this
      ->resetTestData();
  }
  protected function resetTestData() {
    $this->author = $this
      ->drupalCreateUser(array(
      'administer access of own books',
      'add content to books',
      'create book content',
      'create new books',
      'edit own book content',
      'access content',
    ));
    $this->adminRole = $this
      ->drupalCreateRole(array(
      'administer nodes',
      'access content',
    ), 'administrator');

    // invoke the initialization manually
    module_invoke('book_access', 'init');
    $this->books = array();
    $this->nodes = array();
    $this
      ->createBook($this->books, $this->nodes, $this->author);
  }

  /*
   * Creates books programmatically instead of by faking a form submit
   * since it's much, much faster
   */
  protected function createBook(&$books, &$nodes, $author, $pages = 2) {
    static $mlid = 1;
    static $counter = 1;
    $firstNode = NULL;
    while ($pages--) {
      $node = new stdClass();
      $node->title = "top-level book page #{$counter}";
      $node->body = "dummy content {$counter}";
      $node->uid = $author->uid;
      $node->type = 'page';
      $node->status = 1;
      if ($firstNode === NULL) {
        $node->book['bid'] = 'new';
      }
      else {
        $node->book['bid'] = $firstNode;
      }
      node_save($node);
      if ($firstNode === NULL) {
        $books[] = $node;
        $firstNode = $node->nid;
      }
      $nodes[] = $node;
      ++$counter;
    }
  }
  function testCases() {

    // module-level permissions
    $this
      ->caseNoSpecialBookAccess();
    $this
      ->caseAdministerBookAccess();
    $this
      ->caseAdministerAnyBookAccess();
    $this
      ->caseAdministerOwnBookAccess();

    // grants
    $this
      ->caseUpdatePreservesGrants();
    $this
      ->caseAuthorVsAdminDefaults();
    $this
      ->caseAuthorDefaultsPropagateToNewNode();
    $this
      ->caseRoleDefaultsPropagateToNewNode();
    $this
      ->caseChildDefaultsDoNotAffectParentBook();
    $this
      ->caseAuthorDefaultsPropagateToUpdatedNode();
    $this
      ->caseRoleWithIntentionalNoPermissionsAvoidsDefault();
    $this
      ->caseDeletingBookDoesNotDeleteGrants();
    $this
      ->caseResetToDefaults();
  }
  private function caseNoSpecialBookAccess() {
    $user = $this
      ->drupalCreateUser(array(
      'access content',
    ));
    $this
      ->drupalLogin($user);
    foreach ($this->nodes as $node) {
      $nid = $node->nid;
      $this
        ->drupalGet("node/{$nid}");
      $this
        ->assertResponse('200', t('Can access content'));
      $this
        ->drupalGet("book_access/delete/user_permission/{$nid}/{$this->author->uid}");
      $this
        ->assertResponse('403', t('Cannot modify book_access permissions'));
      $this
        ->drupalGet("node/{$nid}/book_access");
      $this
        ->assertResponse('403', t('Cannot change book access'));
    }
    $this
      ->drupalLogout();
  }
  private function caseAdministerBookAccess() {
    $user = $this
      ->drupalCreateUser(array(
      'administer book access',
      'access content',
    ));
    $this
      ->drupalLogin($user);
    foreach ($this->nodes as $node) {
      $nid = $node->nid;
      $this
        ->drupalGet("node/{$nid}");
      $this
        ->assertResponse('200', t('Can access content'));
      $this
        ->drupalGet("book_access/delete/user_permission/{$nid}/{$this->author->uid}");
      $this
        ->assertResponse('200', t('Can modify book_access permissions'));
      $this
        ->drupalGet("node/{$nid}/book_access");
      $this
        ->assertResponse('200', t('Can change book access'));
    }
    $this
      ->drupalLogout();
  }
  private function caseAdministerAnyBookAccess() {
    $user = $this
      ->drupalCreateUser(array(
      'administer access of any book',
      'access content',
    ));
    $this
      ->drupalLogin($user);
    foreach ($this->nodes as $node) {
      $nid = $node->nid;
      $this
        ->drupalGet("node/{$nid}");
      $this
        ->assertResponse('200', t('Can access content'));
      $this
        ->drupalGet("book_access/delete/user_permission/{$nid}/{$this->author->uid}");
      $this
        ->assertResponse('403', t('Cannot modify book_access permissions'));
      $this
        ->drupalGet("node/{$nid}/book_access");
      $this
        ->assertResponse('200', t('Can change book access'));
    }
    $this
      ->drupalLogout();
  }
  private function caseAdministerOwnBookAccess() {
    $user = $this
      ->drupalCreateUser(array(
      'administer access of own books',
      'access content',
    ));
    $this
      ->drupalLogin($user);
    $userBooks = array();
    $userNodes = array();
    $this
      ->createBook($userBooks, $userNodes, $user);
    foreach ($this->nodes as $node) {
      $nid = $node->nid;
      $this
        ->drupalGet("node/{$nid}");
      $this
        ->assertResponse('200', t('Can access content'));
      $this
        ->drupalGet("book_access/delete/user_permission/{$nid}/{$this->author->uid}");
      $this
        ->assertResponse('403', t('Cannot modify book_access permissions'));
      $this
        ->drupalGet("node/{$nid}/book_access");
      $this
        ->assertResponse('403', t('Cannot change book access'));
    }
    foreach ($userNodes as $node) {
      $nid = $node->nid;
      $this
        ->drupalGet("node/{$nid}/book_access");
      $this
        ->assertResponse('200', t('Can change book access for own book'));
    }
    $this
      ->drupalLogout();
  }
  private function caseUpdatePreservesGrants() {
    $user = $this
      ->drupalCreateUser(array(
      'access content',
    ));
    $grants = array(
      'grant_update' => array(
        $user->uid => 1,
      ),
      'grant_delete' => array(
        $user->uid => 1,
      ),
      'grant_admin_access' => array(
        $user->uid => 1,
      ),
      'grant_add_child' => array(
        $user->uid => 1,
      ),
      'grant_edit_outline' => array(
        $user->uid => 1,
      ),
    );

    // precondition checks
    foreach ($grants as $grant => $data) {
      $this
        ->assertFalse(BookAccess::checkGrant($this->books[0]->nid, $grant, $user), t('Sanity check of initial state for "@grant" failed; should be false', array(
        '@grant' => $grant,
      )));
    }
    BookAccess::addUserGrants($this->books[0]->nid, array(
      $user->uid,
    ), $grants);

    // make sure initial add worked
    foreach ($grants as $grant => $data) {
      $this
        ->assertTrue(BookAccess::checkGrant($this->books[0]->nid, $grant, $user), t('Sanity check of "@grant" failed; should be true', array(
        '@grant' => $grant,
      )));
    }

    // update the node
    module_invoke('book_access', 'node_update', $this->books[0]);

    // post-test checks
    foreach ($grants as $grant => $data) {
      $this
        ->assertTrue(BookAccess::checkGrant($this->books[0]->nid, $grant, $user), t('"@grant" should stay true after node update', array(
        '@grant' => $grant,
      )));
    }
  }
  private function caseAuthorVsAdminDefaults() {
    $adminGrantsToCheck = drupal_map_assoc(BookAccess::grantIDs());
    $authorGrantsToCheck = drupal_map_assoc(BookAccess::grantIDs());
    $authorGrantsToCheck['grant_admin_access'] = FALSE;
    $user = $this
      ->drupalCreateUser(array(
      'access content',
    ));
    $userBooks = array();
    $userNodes = array();
    $this
      ->createBook($userBooks, $userNodes, $user);
    foreach ($authorGrantsToCheck as $grant => $value) {
      $this
        ->assertEqual($value, BookAccess::checkGrant($userBooks[0]->nid, $grant, $user), t('Author (no admin role) should have @grant set to @value', array(
        '@grant' => $grant,
        '@value' => $value ? "TRUE" : "FALSE",
      )));
    }
    $adminRole = user_role_load_by_name('administrator');
    if ($adminRole === FALSE) {
      $this
        ->fail(t('Couldn\'t load role \'administrator\''));
    }
    user_multiple_role_edit(array(
      $user->uid,
    ), 'add_role', $adminRole->rid);
    $user = user_load($user->uid);
    foreach ($adminGrantsToCheck as $grant => $value) {
      $this
        ->assertEqual($value, BookAccess::checkGrant($userBooks[0]->nid, $grant, $user), t('Author (with admin role) should have @grant set to @value', array(
        '@grant' => $grant,
        '@value' => $value ? "TRUE" : "FALSE",
      )));
    }
  }
  private function caseAuthorDefaultsPropagateToNewNode() {
    $originalDefaults = variable_get("book_access_default_author_access");
    $newDefaults = array(
      'grant_view',
      'grant_delete',
    );
    variable_set("book_access_default_author_access", $newDefaults);
    $userBooks = array();
    $userNodes = array();
    $this
      ->createBook($userBooks, $userNodes, $this->author);

    // verify that our db data is correct, too
    $resultSet = db_select('book_access_author', 'book_access_author')
      ->condition('uid', $this->author->uid, '=')
      ->condition('nid', $userBooks[0]->nid, '=')
      ->fields('book_access_author')
      ->execute();
    $this
      ->assertTrue($resultSet
      ->rowCount() == 1, t('Exactly one entry in the database'));
    $row = $resultSet
      ->fetchAssoc();
    foreach ($originalDefaults as $grant) {
      if (in_array($grant, $newDefaults)) {
        $this
          ->assertTrue(BookAccess::checkGrant($userBooks[0]->nid, $grant, $this->author), t('New author default for grant "@grant" should be TRUE', array(
          '@grant' => $grant,
        )));
        $this
          ->assertEqual(1, $row[$grant], t('DB entry for node @nid, author @uid, grant "@grant" should be 1', array(
          '@nid' => $userBooks[0]->nid,
          '@uid' => $this->author->uid,
          '@grant' => $grant,
        )));
      }
      else {
        $this
          ->assertFalse(BookAccess::checkGrant($userBooks[0]->nid, $grant, $this->author), t('New author default for grant "@grant" should be FALSE', array(
          '@grant' => $grant,
        )));
        $this
          ->assertEqual(0, $row[$grant], t('DB entry for node @nid, author @uid, grant "@grant" should be 0', array(
          '@nid' => $userBooks[0]->nid,
          '@uid' => $this->author->uid,
          '@grant' => $grant,
        )));
      }
    }
    variable_set("book_access_default_author_access", $originalDefaults);
  }
  private function caseRoleDefaultsPropagateToNewNode() {
    $enabledGrants = array(
      'grant_view',
      'grant_update',
    );

    // precondition checks
    $grantsToCheck = array(
      'grant_delete' => FALSE,
      'grant_view' => TRUE,
    );
    $rid = $this
      ->drupalCreateRole(array(
      'access content',
    ));
    if ($rid === FALSE) {
      $this
        ->fail('Couldn\'t create test role');
    }
    $roles = array();
    $roleGrants = BookAccess::getRoleGrants($this->books[0], $roles);
    foreach ($grantsToCheck as $grant => $value) {
      $this
        ->assertEqual($value, $roleGrants[$grant][$rid], t('Grant "@grant" should be @value', array(
        '@grant' => $grant,
        '@value' => $value ? "true" : "false",
      )));
    }

    // change the default and create a new book
    variable_set("book_access_default_role_{$rid}_access", $enabledGrants);
    $roleBooks = array();
    $roleNodes = array();
    $roleUser = $this
      ->drupalCreateUser();
    user_multiple_role_edit(array(
      $roleUser->uid,
    ), 'add_role', $rid);
    $this
      ->createBook($roleBooks, $roleNodes, $roleUser);
    foreach ($enabledGrants as $grant) {
      $this
        ->assertTrue(BookAccess::checkGrant($roleBooks[0]->nid, $grant, $roleUser), t('New book\'s grant "@grant" should be enabled', array(
        '@grant' => $grant,
      )));
    }
  }
  private function caseChildDefaultsDoNotAffectParentBook() {
    $originalDefaults = variable_get("book_access_default_author_access");
    $userBooks = array();
    $userNodes = array();
    $this
      ->createBook($userBooks, $userNodes, $this->author);
    $this
      ->assertTrue(BookAccess::checkGrant($userBooks[0]->nid, 'grant_delete', $this->author), t('Sanity checking that parent book does have grant_delete'));

    // now change our defaults for creating a child node
    $newDefaults = array(
      'grant_view',
    );
    variable_set("book_access_default_author_access", $newDefaults);
    $newNode = new stdClass();
    $newNode->title = "child node";
    $newNode->body = "dummy content";
    $newNode->uid = $this->author->uid;
    $newNode->type = 'page';
    $newNode->stats = 1;
    $newNode->book['bid'] = $userBooks[0]->nid;
    node_save($newNode);
    $this
      ->assertTrue(BookAccess::checkGrant($userBooks[0]->nid, 'grant_delete', $this->author), t('Parent must remain un-changed in its permissions'));
    variable_set("book_access_default_author_access", $originalDefaults);
  }
  private function caseAuthorDefaultsPropagateToUpdatedNode() {
    $newNode = new stdClass();
    $newNode->title = "un-booked node";
    $newNode->body = "dummy content";
    $newNode->uid = $this->author->uid;
    $newNode->type = 'page';
    $newNode->stats = 1;
    node_save($newNode);
    $query = db_select('book_access_author', 'book_access_author')
      ->condition('nid', $newNode, '=')
      ->condition('uid', $this->author->uid)
      ->fields('book_access_author');
    $resultSet = $query
      ->execute();
    $this
      ->assertEqual(0, $resultSet
      ->rowCount(), t('There should not be any entry in the book_access_author table'));

    // upgrade the node to a book
    $newNode->book['bid'] = 'new';
    node_save($newNode);
    $query = db_select('book_access_author', 'book_access_author')
      ->condition('nid', $newNode->book['bid'], '=')
      ->condition('uid', $this->author->uid, '=')
      ->fields('book_access_author');
    $resultSet = $query
      ->execute();
    $this
      ->assertEqual(1, $resultSet
      ->rowCount(), t('There should be an entry in the book_access_author table post-update'));
  }
  private function caseRoleWithIntentionalNoPermissionsAvoidsDefault() {
    $rid = $this
      ->drupalCreateRole(array(
      'access content',
    ));
    if ($rid === FALSE) {
      $this
        ->fail('Couldn\'t create test role');
    }
    $roleBooks = array();
    $roleNodes = array();
    $roleUser = $this
      ->drupalCreateUser();
    user_multiple_role_edit(array(
      $roleUser->uid,
    ), 'add_role', $rid);
    $this
      ->createBook($roleBooks, $roleNodes, $roleUser);
    $defaultRoleGrants = variable_get("book_access_default_role_{$rid}_access");
    $this
      ->assertTrue(in_array('grant_view', $defaultRoleGrants), t('New book\'s grant_view should be on by default'));
    variable_set("book_access_default_role_{$rid}_access", array());
    $defaultRoleGrants = variable_get("book_access_default_role_{$rid}_access");
    $this
      ->assertFalse(in_array('grant_view', $defaultRoleGrants), t('Sanity check to make sure grant_view is gone.'));
    module_invoke('book_access', 'init');
    $defaultRoleGrants = variable_get("book_access_default_role_{$rid}_access");
    $this
      ->assertFalse(in_array('grant_view', $defaultRoleGrants), t('grant_view should not have come back'));
  }
  private function caseDeletingBookDoesNotDeleteGrants() {
    $roleBooks = array();
    $roleNodes = array();
    $this
      ->createBook($roleBooks, $roleNodes, $this->author);
    $this
      ->assertTrue(BookAccess::checkGrant($roleBooks[0]->nid, 'grant_view', $this->author), t('Sanity checking that newly-created book has grant_view'));
    $this
      ->assertTrue(BookAccess::checkGrant($this->books[0]->nid, 'grant_view', $this->author), t('Sanity checking that base test-case book has grant_view'));
    node_delete($roleBooks[0]->nid);
    $this
      ->assertTrue(BookAccess::checkGrant($this->books[0]->nid, 'grant_view', $this->author), t('Base test-case book should maintain its permissions'));
  }
  private function caseResetToDefaults() {

    // grants that will be set to true
    // after a default reset
    $grantsToCheck = array(
      'grant_delete',
      'grant_view',
      'grant_update',
    );

    // set up user/role
    $rid = $this
      ->drupalCreateRole(array(
      'access content',
    ));
    if ($rid === FALSE) {
      $this
        ->fail('Couldn\'t create test role');
    }
    $roleBooks = array();
    $roleNodes = array();
    $roleUser = $this
      ->drupalCreateUser();
    foreach ($roleUser->roles as $rid => $rname) {
      user_multiple_role_edit(array(
        $roleUser->uid,
      ), 'remove_role', $rid);
    }
    user_multiple_role_edit(array(
      $roleUser->uid,
    ), 'add_role', $rid);
    $roleUser = user_load($roleUser->uid);

    // clear defaults
    variable_set("book_access_default_role_{$rid}_access", array());

    // create with a different author, check defaults
    $this
      ->createBook($roleBooks, $roleNodes, $this->author);
    foreach ($grantsToCheck as $grant) {
      $this
        ->assertFalse(BookAccess::checkGrant($roleBooks[0]->nid, $grant, $roleUser), t('New book\'s grant "@grant" should be disabled', array(
        '@grant' => $grant,
      )));
    }

    // change defaults
    variable_set("book_access_default_role_{$rid}_access", $grantsToCheck);
    BookAccess::resetToDefault($roleBooks[0]->nid);
    foreach ($grantsToCheck as $grant) {
      $this
        ->assertTrue(BookAccess::checkGrant($roleBooks[0]->nid, $grant, $roleUser), t('New book\'s grant "@grant" should be reset to the new default of enabled', array(
        '@grant' => $grant,
      )));
    }
  }

}

Classes

Namesort descending Description
BookAccessTestCase