<?php

/**
 * @file
 * Simpletest case for Date Popup Authored.
 *
 * Verify Date Popup Authored functionality.
 */

/**
 * Functionality tests for Date Popup Authored.
 */
class DatePopupAuthoredTestCase extends PageEditTestCase {

  public static function getInfo() {
    return array(
      'name' => 'Page editing with Date Popup Authored',
      'description' => 'Verify Date Popup Authored does not interfere with page editing.',
      'group' => 'Date Popup Authored',
    );
  }

  function setUp() {
    // Enable the module.
    DrupalWebTestCase::setUp('date_popup_authored');

    // Create users for test cases.
    $this->web_user = $this->drupalCreateUser(array('edit own page content', 'create page content'));
    $this->admin_user = $this->drupalCreateUser(array('bypass node access', 'administer nodes'));
  }

  /**
   * Check changing node authored on fields.
   */
  function testPageAuthoredOnEdit() {
    $this->drupalLogin($this->admin_user);

    // Create node to edit.
    $langcode = LANGUAGE_NONE;
    $body_key = "body[$langcode][0][value]";
    $edit = array();
    $edit['title'] = $this->randomName(8);
    $edit[$body_key] = $this->randomName(16);
    $this->drupalPost('node/add/page', $edit, t('Save'));

    $node = $this->drupalGetNodeByTitle($edit['title']);
    $node->date = format_date($node->created, 'custom', 'Y-m-d H:i:s O');

    // Check that the Authored On field's format does not mangle the saved date.
    $this->checkAuthoredOnWithFormat('M d, Y', $node);
    $this->checkAuthoredOnWithFormat('M, Y', $node);
    $this->checkAuthoredOnWithFormat('M d, Y H:i', $node);
    $this->checkAuthoredOnWithFormat('m/d/Y - H:i:s', $node);
    $this->checkAuthoredOnWithFormat('d M Y - g:i A', $node);
  }

  /**
   * Check to see if Date Popup Authored keeps the Authored On field intact.
   *
   * Date Popup cleverly handles how to replace regular text fields: if the date
   * format has both a date and time component, it creates one textfield for the
   * date and one for the time.
   *
   * Because of this, the node date needs to be split into date and time parts
   * so it can be compared with the date popup on the node submission form.
   *
   * @param $format
   *  The date format to test.
   * @param $node
   *  The node object to test the date format with.
   * @param $timezone
   *  Optionally, a timezone to test with.
   */
  function checkAuthoredOnWithFormat($format, $node, $timezone = '') {
    debug('Format: ' . $format);

    $timezone = !empty($timezone) ? $timezone : date_default_timezone_object();

    // Extract the date and time format parts
    $granularity = date_format_order($format);
    $date_format = date_limit_format($format, array_intersect($granularity, array('month', 'day', 'year')));
    $time_format = date_popup_format_to_popup_time(date_limit_format($format, array_intersect($granularity, array('hour', 'minute', 'second'))));

    // Generate a DateObject object for the node date.
    $node_date = DateObject::createFromFormat('Y-m-d H:i:s O', $node->date, $timezone);
    debug($node_date->format($date_format), 'Node date');
    debug($node_date->format($time_format), 'Node time');

    // Extract the date and time parts as seen on the node submission form
    $default_format = variable_get('date_popup_authored_format_page', variable_get('date_format_short', 'm/d/Y - H:i'));
    variable_set('date_popup_authored_format_page', $format);

    $this->drupalGet('node/' . $node->nid . '/edit');
    $elements = $this->xpath("//input[starts-with(@name, 'date[')]");

    $submitted_date_string = '';
    foreach ($elements as $element) {
      if ((string) $element['name'] === 'date[date]') {
        debug((string) $element['value'], 'Submitted date');
        $this->assertIdentical($node_date->format($date_format), (string) $element['value'], 'The node date and submission form have identical dates.');
      }
      elseif ((string) $element['name'] === 'date[time]') {
        debug((string) $element['value'], 'Submitted time');
        $this->assertIdentical($node_date->format($time_format), (string) $element['value'], 'The node date and submission form have identical times.');
      }
    }

    // Reset format back to default
    variable_set('date_popup_authored_format_page', $format);
  }

  /**
   * Tests form field validation.
   */
  function testFieldValidation() {
    // Define some test cases.
    $test_cases = array(
      array(
        'description' => 'a valid date field and a missing time field',
        'date' => '02/07/2014',
        'time' => '',
        'valid' => FALSE,
      ),
      array(
        'description' => 'a valid date field and a valid time field',
        'date' => '02/07/2014',
        'time' => '12:00',
        'valid' => TRUE,
      ),
    );

    // Log in as administrator.
    $this->drupalLogin($this->admin_user);

    // Test the test cases.
    foreach ($test_cases as $test_case) {
      $edit = array(
        'title' => $this->randomString(),
        'date[date]' => $test_case['date'],
        'date[time]' => $test_case['time'],
      );
      $this->drupalPost('node/add/page', $edit, t('Save'));

      $error_messages = $this->xpath('//div[contains(@class, "error")]');

      $message = format_string('When submitting a node with @description the form validation correctly @result.', array(
        '@description' => $test_case['description'],
        '@result' => $test_case['valid'] ? 'succeeds' : 'fails',
      ));
      $this->assertEqual(empty($error_messages), $test_case['valid'], $message);
    }
  }

  /**
   * Tests variable cleanup after a content type is removed.
   */
  function testVariableCleanupAfterNodeTypeRemoval() {
    $node_type_name = strtolower($this->randomName(8) . '_test');
    $node_type = $this->drupalCreateContentType(array('name' => $node_type_name, 'type' => $node_type_name));

    variable_set('date_popup_authored_enabled_' . $node_type_name, 'foo');
    variable_set('date_popup_authored_format_' . $node_type_name, 'foo');
    variable_set('date_popup_authored_year_range_' . $node_type_name, 'foo');

    node_type_delete($node_type_name);

    $this->assertNull(variable_get('date_popup_authored_enabled_' . $node_type_name));
    $this->assertNull(variable_get('date_popup_authored_format_' . $node_type_name));
    $this->assertNull(variable_get('date_popup_authored_year_range_' . $node_type_name));
  }

  /**
   * Tests variable cleanup after Date Popup Authored is uninstalled.
   */
  function testVariableCleanupAfterUninstall() {
    variable_set('date_popup_authored_enabled_page', 'foo');
    variable_set('date_popup_authored_format_page', 'foo');
    variable_set('date_popup_authored_year_range_page', 'foo');

    module_disable(array('date_popup_authored'));
    drupal_uninstall_modules(array('date_popup_authored'));

    $this->assertNull(variable_get('date_popup_authored_enabled_page'));
    $this->assertNull(variable_get('date_popup_authored_format_page'));
    $this->assertNull(variable_get('date_popup_authored_year_range_page'));
  }
}
