<?php
// $Id: path_redirect.test,v 1.1.2.23 2010/08/09 18:39:59 davereid Exp $

/**
 * @file
 * Tests for the path_redirect module.
 */

class PathRedirectTestHelper extends DrupalWebTestCase {
  function setUp() {
    $args = func_get_args();

    // Call parent::setUp() allowing test cases to pass further modules.
    $modules = array('path', 'path_redirect');
    if (isset($args[0]) && is_array($args[0])) {
      $modules = array_merge($modules, $args[0]);
    }

    $parent_callback = 'parent::setUp';
    if (version_compare(PHP_VERSION, '5.3.0', '<')) {
      $parent_callback = array($this, 'parent::setUp');
    }
    call_user_func_array($parent_callback, $modules);
  }

  protected function assertRedirect($request, $redirect, $code = FALSE) {
    $this->drupalGet($request);
    if ($code) {
      $this->assertResponse($code);
    }
    $this->assertEqual($this->getUrl(), url($redirect, array('absolute' => TRUE)), t('Redirected from %request to %redirect.', array('%request' => $request, '%redirect' => $redirect)));
  }

  protected function addRedirect($source, $redirect, $options = array()) {
    $redirect = array(
      'source' => $source,
      'redirect' => $redirect,
    ) + $options;
    path_redirect_save($redirect);
    return $redirect;
  }

  /**
   * Runs cron in the Drupal installed by Simpletest.
   */
  protected function cronRun() {
    $this->drupalGet($GLOBALS['base_url'] . '/cron.php', array('external' => TRUE));
  }
}

class PathRedirectUnitTest extends PathRedirectTestHelper {
  public static function getInfo() {
    return array(
      'name' => 'Path redirect unit tests',
      'description' => 'Test basic functionality.',
      'group' => 'Path redirect',
    );
  }

  function testCompareArray() {
    $haystack = array('a' => 'aa', 'b' => 'bb', 'c' => array('c1' => 'cc1', 'c2' => 'cc2'));
    $cases = array(
      array('query' => array('a' => 'aa', 'b' => 'invalid'), 'result' => FALSE),
      array('query' => array('b' => 'bb', 'b' => 'bb'), 'result' => TRUE),
      array('query' => array('b' => 'bb', 'c' => 'invalid'), 'result' => FALSE),
      array('query' => array('b' => 'bb', 'c' => array()), 'result' => TRUE),
      array('query' => array('b' => 'bb', 'c' => array('invalid')), 'result' => FALSE),
      array('query' => array('b' => 'bb', 'c' => array('c2' => 'invalid')), 'result' => FALSE),
      array('query' => array('b' => 'bb', 'c' => array('c2' => 'cc2')), 'result' => TRUE),
    );
    foreach ($cases as $index => $case) {
      $this->assertEqual($case['result'], path_redirect_compare_array($case['query'], $haystack));
    }
  }

  function testRedirects() {
    // Test a basic redirect (with and without a trailing slash requested).
    $this->addRedirect('/test/', 'node');
    $this->assertRedirect('test', 'node');
    $this->assertRedirect('test/', 'node');

    // Test a unicode URL.
    $this->addRedirect('FrançAIS', 'http://example.com/');
    $this->assertRedirect('FrançAIS', 'http://example.com/');

    // Test an URL with special characters.
    $this->addRedirect('foo_/ferzle-foo.bar', '<front>');
    $this->assertRedirect('foo_/ferzle-foo.bar', '<front>');
  }

  function testNoCleanURLs() {
    $clean_url = (bool) variable_get('clean_url', 0);
    variable_set('clean_url', !$clean_url);
    $this->testRedirects();
    variable_set('clean_url', (int) $clean_url);
  }
}

/*class PathRedirectPathautoUnitTest extends PathRedirectTestHelper {
  public static function getInfo() {
    return array(
      'name' => t('Pathauto integration'),
      'description' => t('Test integration with the pathauto module.'),
      'group' => t('Path redirect'),
      'dependencies' => array('pathauto', 'token'),
    );
  }

  function setUp() {
    parent::setUp('path', 'token', 'pathauto', 'path_redirect');

    $this->admin_user = $this->drupalCreateUser(array('administer nodes', 'administer redirects', 'create url aliases'));
    $this->drupalLogin($this->admin_user);
    variable_set('pathauto_update_action', 3);
    //variable_set('pathauto_verbose', FALSE);
  }

  function testPathautoIntegration() {
    $node = $this->drupalCreateNode(array('title' => 'test1'));
    $this->assertIdentical('content/test1', drupal_get_path_alias('node/' . $node->nid));

    $edit = array(
      'title' => 'test2',
      'pathauto_perform_alias' => TRUE,
    );
    $this->drupalPost("node/{$node->nid}/edit", $edit, t('Save'));
    $this->assertRaw(t('%title has been updated.', array('%title' => $edit['title'])), t('Node saved.'));
    $this->assertTrue(path_redirect_load(array('source' => 'content/test1', 'redirect' => 'node/' . $node->nid)), t('Redirect created.'));

    $edit = array(
      'title' => 'test3',
      'pathauto_perform_alias' => TRUE,
    );
    $this->drupalPost("node/{$node->nid}/edit", $edit, t('Save'));
    $this->assertRaw(t('%title has been updated.', array('%title' => $edit['title'])), t('Node saved.'));
    $this->assertTrue(path_redirect_load(array('source' => 'content/test1', 'redirect' => 'node/' . $node->nid)), t('Redirect created.'));
    $this->assertTrue(path_redirect_load(array('source' => 'content/test2', 'redirect' => 'node/' . $node->nid)), t('Redirect created.'));
  }
}*/

class PathRedirectFunctionalTest extends PathRedirectTestHelper {
  public static function getInfo() {
    return array(
      'name' => t('Path redirect administration'),
      'description' => t('Test redirect administration interface.'),
      'group' => t('Path redirect'),
    );
  }

  function setUp() {
    parent::setUp();

    $this->admin_user = $this->drupalCreateUser(array('administer redirects', 'administer nodes', 'create url aliases'));
    $this->drupalLogin($this->admin_user);
  }

  function testAliasRedirection() {
    $node = $this->drupalCreateNode(array('title' => 'test1'));
    $edit = array(
      'path' => 'test1',
    );
    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
    $this->assertRaw(t('@type %title has been updated.', array('@type' => 'Page', '%title' => $node->title)), t('Node saved.'));
    $this->assertFalse(path_redirect_load_multiple(NULL, array('redirect' => 'node/' . $node->nid)), t('No redirects created yet.'));

    $edit = array(
      'path' => 'test2',
    );
    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
    $this->assertRaw(t('@type %title has been updated.', array('@type' => 'Page', '%title' => $node->title)), t('Node saved.'));
    $this->assertTrue(path_redirect_load_multiple(NULL, array('source' => 'test1', 'redirect' => 'node/' . $node->nid)), t('Redirect created.'));

    $this->drupalPost('node/' . $node->nid . '/delete', array(), t('Delete'));
    $this->assertFalse(path_redirect_load_multiple(NULL, array('redirect' => 'node/' . $node->nid)), t("Deleted node's redirects deleted."));
  }

  function testInactivePurging() {
    // Add two inactive redirects to the database.
    $time = time();
    $r1 = $this->addRedirect('test1', 'node', array('last_used' => $time - 620000));
    $r2 = $this->addRedirect('test2', 'node', array('last_used' => $time - 620000));

    // Purging is disabled by default, so after running cron both redirects should not be removed.
    $this->cronRun();
    $this->assertTrue(path_redirect_load($r1['rid']), t('Inactive redirect not removed.'));
    $this->assertTrue(path_redirect_load($r2['rid']), t('Inactive redirect not removed.'));

    // Enable purging of inactive redirects.
    $edit = array('path_redirect_purge_inactive' => 604800);
    $this->drupalPost('admin/build/path-redirect/settings', $edit, t('Save configuration'));
    $this->assertText(t('The configuration options have been saved.'));

    // Run one of the redirects and test that the last used timestamp was updated.
    $this->drupalGet('test1');
    $this->assertTrue(db_result(db_query("SELECT last_used FROM {path_redirect} WHERE source = 'test1'")) >= $time, t('Last used timestamp was updated.'));

    // Run cron and test that the inactive redirect was removed.
    $this->cronRun();
    $this->assertTrue(path_redirect_load($r1['rid']), t('Active redirect not removed.'));
    $this->assertFalse(path_redirect_load($r2['rid']), t('Inactive redirect removed.'));
  }

  function testAutocomplete() {
    // Create 404 errors.
    $this->drupalGet('test1');
    $this->drupalGet('test2');
    $this->drupalGet('test2');
    $this->drupalGet('tst3');

    // Create a 404 and then create a valid redirect for it.
    $this->drupalGet('test3');
    $this->addRedirect('test3', 'node');

    // Create a 404 and then create a valid path for it.
    $this->drupalGet('node/1');
    $node = $this->drupalCreateNode();
    $this->assertEqual($node->nid, 1, t('Node 1 created'));

    // Test that only the valid 404s are found in the autocomplete.
    $this->drupalGet('js/path_redirect/autocomplete_404/e');
    $this->assertText('test1');
    $this->assertText('test2');
    $this->assertNoText('node');
    $this->assertNoText('test3');
    $this->assertNoText('tst3');

    // Test that the 404 with the greater hits is listed first.
    $this->assertTrue(strpos($this->drupalGetContent(), 'test1') > strpos($this->drupalGetContent(), 'test2'), t('Paths ordered correctly.'));
  }
}
