<?php

/*
 * @copyright NetMonsters <team@netmonsters.ru>
 * @link http://netmonsters.ru
 * @package Majestic
 * @subpackage UnitTests
 * @since 2011-10-07
 *
 * Unit tests for Form class
 */

require_once dirname(__FILE__) . '/../../form/Form.php';
require_once dirname(__FILE__) . '/../../form/FormField.php';
require_once dirname(__FILE__) . '/../../validator/iValidator.php';
require_once dirname(__FILE__) . '/../../validator/Validator.php';
require_once dirname(__FILE__) . '/../../validator/RegexValidator.php';
require_once dirname(__FILE__) . '/../../validator/NotEmptyValidator.php';
require_once dirname(__FILE__) . '/../../validator/EmailValidator.php';
require_once dirname(__FILE__) . '/../../exception/InitializationException.php';

class FormTest extends PHPUnit_Framework_TestCase
{
    public function testAddFieldEmptyMessage()
    {
        $form_field = new FormField();
        $stub = $this->getMockForAbstractClass('Form');
        $method = new ReflectionMethod('Form', 'addField');
        $method->setAccessible(true);
        $return_object = $method->invokeArgs($stub, array('login'));

        $this->assertInstanceOf('FormField', $return_object);
        $this->assertEquals($form_field, $return_object);
    }

    public function testAddFieldWithMessage()
    {
        $message = 'Test message';
        $form_field = new FormField($message);
        $stub = $this->getMockForAbstractClass('Form');
        $method = new ReflectionMethod('Form', 'addField');
        $method->setAccessible(true);
        $return_object = $method->invokeArgs($stub, array('login', $message));
        
        $this->assertInstanceOf('FormField', $return_object);
        $this->assertEquals($form_field, $return_object);
        $this->assertAttributeEquals($message, 'default_message', $return_object);
    }

    public function testIsValidWithNotArray()
    {
        $form = new NotEmptyForm();
        // @TODO Fix exception type
        $this->setExpectedException('InitializationException', 'Form::Form::isValid expects an array');
        $form->isValid('');
    }

    public function testIsValidCorrectFields()
    {
        $form = new NotEmptyForm();
        $test_array = array(
            'login' => 'login',
            'password' => 'password'
        );

        $this->assertSame(1, $form->isValid($test_array));
    }

    public function testIsValidMissingField()
    {
        $form = new NotEmptyForm();
        $test_array = array(
            'password' => 'password'
        );

        $this->assertSame(0, $form->isValid($test_array));
        $data['messages'] = $form->getMessages();
        $data['values'] = $form->getSourceValues();
        $this->assertSame($_SESSION['NotEmptyForm'], $data);
    }

    public function testGetValues()
    {
        $form = new NotEmptyForm();
        $test_array = array(
            'login' => 'login',
            'password' => 'password'
        );

        $this->assertSame(1, $form->isValid($test_array));
        $this->assertSame($test_array, $form->getValues());
    }


    public function testGetValuesWithFieldIsIgnored()
    {
        $form = new WithIgnoredFieldForm();
        $test_array = array(
            'login' => 'login',
            'password' => 'password',
            'remember' => true
        );

        $this->assertSame(1, $form->isValid($test_array));
        $this->assertSame(array(
                               'login' => 'login',
                               'password' => 'password'), $form->getValues());
        $this->assertSame($test_array, $form->getSourceValues());
    }


    public function testGetValueCorrect()
    {
        $form = new NotEmptyForm();
        $test_array = array(
            'login' => 'login',
            'password' => 'password'
        );

        $this->assertSame(1, $form->isValid($test_array));
        $this->assertSame($test_array['login'], $form->getValue('login'));
        $this->assertSame($test_array['password'], $form->getValue('password'));
    }


    public function testGetValueEmpty()
    {
        $form = new NotEmptyForm();
        $test_array = array(
            'login' => 'login'
        );

        $this->assertSame(0, $form->isValid($test_array));
        $this->assertSame('login', $form->getValue('login'));
        $this->assertNull($form->getValue('password'));
    }


    public function testGetValueMissing()
    {
        $form = new NotEmptyForm();
        $test_array = array(
            'login' => 'login',
            'password' => 'password'
        );

        $this->assertSame(1, $form->isValid($test_array));
        $this->assertSame('login', $form->getValue('login'));
        $this->assertSame('password', $form->getValue('password'));
        $this->assertFalse($form->getValue('missing'));
    }


    public function testGetMessageTypeCorrect()
    {
        $form = new NotEmptyForm();
        $test_array = array(
            'login' => 'login',
            'password' => 'password'
        );

        $this->assertSame(1, $form->isValid($test_array));
        $this->assertSame('success', Form::SUCCESS);
        $this->assertSame($form->getMessageType(), Form::SUCCESS);
    }

    public function testGetMessageTypeMissing()
    {
        $form = new NotEmptyForm();
        $test_array = array(
            'login' => '',
            'password' => ''
        );

        $this->assertSame(0, $form->isValid($test_array));
        $this->assertSame('error', Form::ERROR);
        $this->assertSame($form->getMessageType(), Form::ERROR);
    }

    public function testGetMessageCorrect()
    {
        $form = new NotEmptyForm();
        $message = 'Test message';
        $test_array = array(
            'login' => 'login',
            'password' => 'password'
        );

        $this->assertSame(1, $form->isValid($test_array));
        $form->setSuccessMessage($message);
        $this->assertSame($message, $form->getMessage());
    }

    public function testGetMessageMissing()
    {
        $form = new NotEmptyForm();
        $message = 'Test message';
        $test_array = array(
            'login' => ''
        );

        $this->assertSame(0, $form->isValid($test_array));
        $form->setErrorMessage($message);
        $this->assertSame($message, $form->getMessage());
    }

    public function testSetSuccessMessage()
    {
        $form = new NotEmptyForm();
        $test_array = array(
            'login' => 'login',
            'password' => 'password'
        );

        $this->assertSame(1, $form->isValid($test_array));
        $message = 'Form data valid';
        $form->setSuccessMessage($message);
        $this->assertSame($message, $form->getMessage());
    }

    public function testSetErrorMessage()
    {
        $form = new NotEmptyForm();
        $test_array = array(
            'login' => ''
        );

        $this->assertSame(0, $form->isValid($test_array));
        $message = 'Form data invalid';
        $form->setErrorMessage($message);
        $this->assertSame($message, $form->getMessage());
    }
}


class NotEmptyForm extends Form
{
    public function init()
    {
        $validator = new NotEmptyValidator();
        $validator->setMessage('Enter login name.');
        $this->addField('login')->addValidator($validator);

        $validator = new NotEmptyValidator();
        $validator->setMessage('Enter your password.');
        $this->addField('password')->addValidator($validator);
    }
}

class WithIgnoredFieldForm extends Form
{
    public function init()
    {
        $validator = new NotEmptyValidator();
        $validator->setMessage('Enter login name.');
        $this->addField('login')->addValidator($validator);

        $validator = new NotEmptyValidator();
        $validator->setMessage('Enter your password.');
        $this->addField('password')->addValidator($validator);

        $validator = new NotEmptyValidator();
        $validator->setMessage('Remember');
        $this->addField('remember')->addValidator($validator)->setIgnored(true);
    }
}