<?php

/**
 * @file
 * Test FAQ functionality Base test class. All tests inherits this one.
 * Hugely based on code from the test file block.test by boombatower
 */

/**
 * Base class that is extended by test cases.
 */
class FaqTestCase extends DrupalWebTestCase {


  protected $admin_user, $faq_user;
  protected $taxonomy;
  protected $term, $faq1, $faq2;

  public static function getInfo() {
    return array(
      'name' => t('FAQ functionality'),
      'description' => t('Base class. No tests here.'),
      'group' => t('Frequently Asked Questions'),
    );
  }

  function setUp() {

    // Install FAQ Module.
    parent::setUp('taxonomy', 'faq');

    // Create and log in user with administer taxonomy permissions.
    $this->admin_user = $this->drupalCreateUser(array('administer taxonomy', 'administer faq', 'administer faq order', 'administer blocks'));
    $this->faq_user = $this->drupalCreateUser(array('create faq', 'edit faq', 'delete faq content', 'view faq page', 'access content'));
    $this->view_faq_user = $this->drupalCreateUser(array('view faq page', 'access content'));
    $this->drupalLogin($this->admin_user);

    // Set up the vocab and terms.
    $this->setupTaxonomy();

    // Categorize questions.
    $this->drupalPost('admin/settings/faq/categories', array('faq_use_categories' => '1'), t('Save configuration'));

    // Set answer_user as default expert.
    $roles = $this->faq_user->roles;
    end($roles);  // Set to last role (the unique one)

    // Start all tests logged out.
    $this->drupalLogout();

  }

  /**
   * Tear the whole thing down again
   */
  function tearDown() {

    // Things to tidy up like vars and stuff
    parent::tearDown();
  }

 /**
   * Generates a random string of ASCII numeric characters (values 48 to 57).
   *
   * @param $length
   *   Length of random string to generate .
   * @return
   *   Randomly generated string.
   */
  protected static function randomNumber($length = 8) {
    $str = '';
    for ($i = 0; $i < $length; $i++) {
      $str .= chr(mt_rand(48, 57));
    }
    return $str;
  }

 /**
   * Verify that current user has no access to page.
   *
   * @param $url
   *   URL to verify.
   */
  function faqVerifyNoAccess($url) {
    // Test that page returns 403 Access Denied
    $this->drupalGet($url);
    $this->assertResponse(403);
  }

  /**
   * Set up the taxonomy - all vocabularies and stuff
   * Values also stored in protected variable $tax
   */
  function setupTaxonomy() {

    // Create vocabulary.
    $this->taxonomy = array();
    $this->taxonomy['name'] = $this->randomName(8);  // Create taxonomy vocabulary name
    $this->taxonomy['description'] = $this->randomName(64);
    $this->taxonomy['nodes[faq]'] = '1';  // Assign vocab to FAQ node types
    $this->taxonomy['tags'] = '1';  // Users may create tags
    $this->taxonomy['multiple'] = '1';  // may have more than one tag
    $this->taxonomy['required'] = '1';  // but minimum 1 tag
    $this->drupalPost('admin/content/taxonomy/add/vocabulary', $this->taxonomy, t('Save'));
    $this->assertText(t('Created new vocabulary @name', array('@name' => $this->taxonomy['name'])));

    $this->assertText(t('FAQ'));

    // Add term
    // Click the last occurrence of the link.
    $this->clickLink(t('add terms'), substr_count($this->drupalGetContent(), 'add terms') - 1);
    $this->assertText(t('Add term to @name', array('@name' => $this->taxonomy['name']) ));

    $url = parse_url($this->getUrl());
    if ($url['query'] == '') {
      $array = split('/', $url['path']);
      $this->taxonomy['id'] = $array[4];
    }
    else {
      $array = split('/', $url['query']);
      $this->taxonomy['id'] = $array[3];
    }
    $this->pass(var_export($array, TRUE));

    $url = $this->getUrl();
    $this->term = array();
    $this->term['name'] = $this->randomName(8);  // Create taxonomy vocabulary name
    $this->term['description'] = $this->randomName(64);
    $this->drupalPost($url, $this->term, t('Save'));
    $this->assertText(t('Created new term @name', array('@name' => $this->term['name'])));

  }

}

class FaqAccessTestClass extends FaqTestCase {

  public static function getInfo() {
    return array(
      'name' => t('Access to FAQ pages'),
      'description' => t('Access to pages by anonymous user and logged in user with rights.'),
      'group' => t('Frequently Asked Questions'),
    );
  }

  function testFaqAccess() {

    // Verify that anonymous user has no access to the faq page
    $this->faqVerifyNoAccess('faq');

    // Create and login user
    $normal_user = $this->drupalCreateUser();
    $this->drupalLogin($normal_user);

    // Verify that logged in user has no access to the faq page
    $this->faqVerifyNoAccess('faq');
    $this->drupalLogout();

    $this->drupalLogin($this->view_faq_user);

    // Verify that the faq page is visible and available but empty
    $this->drupalGet('faq');
    $this->assertText(t('Frequently Asked Questions'), t('FAQ page is available for view faq page permissions.'));

  }
}


class CRUDFaqTestCase extends FaqTestCase {

  public static function getInfo() {
    return array(
      'name' => t('CRUD FAQ node'),
      'description' => t('Create, Read, Update and Delete a FAQ node.'),
      'group' => t('Frequently Asked Questions'),
    );
  }

  /**
   * Test creating a FAQ node
   */
  function testFaqCreate() {

    // Log in user with create FAQ permissions
    $this->drupalLogin($this->faq_user);

    // Fill in the Create FAQ node 1 form and post it
    $this->faq1 = array();
    $this->faq1['title'] = $this->randomName(8);
    $this->faq1['taxonomy[tags][1]'] = $this->term['name'];  // Add existing term
    $this->faq1['detailed_question'] = $this->randomName(16);
    $this->faq1['body'] = $this->randomName(16);
    $this->drupalPost('node/add/faq', $this->faq1, t('Save'));

    // Check that new FAQ node has actually been created
    $this->assertText(t('FAQ @title has been created.', array('@title' => $this->faq1['title'])));

    // Fill in the Create FAQ node 2 form and post it
    $this->faq2 = array();
    $this->faq2['title'] = $this->randomName(8);
    $this->faq2['taxonomy[tags][1]'] = $this->randomName(8);  // Add new term
    $this->faq2['detailed_question'] = $this->randomName(16);
    $this->faq2['body'] = $this->randomName(16);
    $this->drupalPost('node/add/faq', $this->faq2, t('Save'));

    // Check that new FAQ node has actually been created
    $this->assertText(t('FAQ @title has been created.', array('@title' => $this->faq2['title'])));

    $this->drupalLogout();

    // Check that the FAQ page is available and that the correct term is listed as grouping for the new FAQ node
    $this->drupalLogin($this->view_faq_user);
    $this->drupalGet('faq');
    $this->assertText(t('Frequently Asked Questions'), t('FAQ page is available for view faq page permissions.'));
    $this->assertText($this->faq1['title'], t('Created FAQ node 1 available on FAQ page.'));
    $this->assertText($this->faq1['taxonomy[tags][1]'], t('Term for node 1  available on FAQ page.'));
    $this->assertText($this->faq2['title'], t('Created FAQ node 2 available on FAQ page.'));
    $this->assertText($this->faq2['taxonomy[tags][1]'], t('Term for node 2  available on FAQ page.'));

    // Navigate to FAQ node created on FAQ page
    $this->clickLink(t($this->faq1['title']));
    $this->assertText(t($this->faq1['body']));

    // Log in user with administer FAQ settings.
    $this->drupalLogin($this->admin_user);

    // Enable categorisation of FAQ nodes
    // faq_use_categories
    $conf = array();
    $conf['faq_use_categories'] = '1';  // Enable categorised FAQs
    $this->drupalPost('admin/settings/faq/categories', $conf, t('Save configuration'));
    $this->drupalLogout();

    $this->drupalLogin($this->view_faq_user);
    $this->drupalGet('faq');
    $this->assertText(t('Frequently Asked Questions'), t('FAQ page is available for view faq page permissions.'));
    $this->assertText($this->faq1['title'], t('Created FAQ node 1 available on FAQ page.'));
    $this->assertText($this->faq1['taxonomy[tags][1]'], t('Term for node 1 not available on FAQ page.'));
    $this->assertText($this->faq2['title'], t('Created FAQ node 2 available on FAQ page.'));
    $this->assertText($this->faq2['taxonomy[tags][1]'], t('Term for node 2 not available on FAQ page.'));

  }

  /**
   * Test editing and deleting of an FAQ node.
   */
  public function testFaqEditDelete() {

    // Log in user with create FAQ permissions
    $this->drupalLogin($this->faq_user);

    // Create a FAQ node.
    $edit = array();
    $edit['title'] = $this->randomName(8);
    $edit['taxonomy[tags][' . $this->taxonomy['id'] . ']'] = $this->randomName(8);
    $edit['detailed_question'] = $this->randomName(64);
    $edit['body'] = $this->randomString(264);
    $this->drupalPost('node/add/faq', $edit, t('Save'));
    $this->assertText(t('FAQ @title has been created.', array('@title' => $edit['title'])));

    // Check status for FAQ node - should be published
    $node = $this->drupalGetNodeByTitle($edit['title']);
    $this->assertTrue($node->status);

    // Update FAQ
    $this->drupalGet('node/' . $node->nid . '/edit');  // Open edit page with node
    $edit2['title'] = 'title-' . $this->randomName(8);
    $edit2['body']  = 'body-' . $this->randomName(64);
    $this->drupalPost('node/' . $node->nid . '/edit', array('title' => $edit2['title'], 'body' => $edit2['body']), t('Save'));
    $this->assertText(t('FAQ @title has been updated.', array('@title' => $edit2['title'])));
    $this->assertText($edit2['title'], 'Title has changed');
    $this->assertText($edit2['body'], 'Body has changed');

    // Delete FAQ
    $this->drupalPost('node/' . $node->nid . '/edit', array(), t('Delete'));
    $this->assertText(t('Are you sure you want to delete @title?', array('@title' => $edit2['title'])));
    $this->drupalPost('node/' . $node->nid . '/delete', array(), t('Delete'));
    $this->assertText(t('FAQ @title has been deleted.', array('@title' => $edit2['title'])));
  }
}

