<?php
/**
 * core.framework
 *
 * @category   Core
 * @package    Core_Validate
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 */

/**
 * @category   Core
 * @package    Core_Validate
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 * @group      Core_Validate
 */
class Core_Validate_CreditcardTest extends Core_Validate_TestAbstract
{
    /**
     * @var array Items considered valid
     */
    protected $_valid   = array(
        // Visa
        '4341792000000044' => array('4341792000000044'),
        '4058400000000005' => array('4058400000000005'),

        // MasterCard
        '5464000000000008' => array('5464000000000008'),
        '5466100000000004' => array('5466100000000004'),
    );

    /**
     * @var array Items considered invalid
     */
    protected $_invalid = array(
        // invalid checksum
        '5464000000000009'             => array('5464000000000009'),
        '5466100000000003'             => array('5466100000000003'),

        // correct checksum, invalid length
        '5464000000000000000000009991' => array('5464000000000000000000009991'),
        '5466100004'                   => array('5466100004'),
    );

    /**
     * @var Core_Validate_Phone
     */
    protected $_object;

    protected function setUp()
    {
        $this->_object = new Core_Validate_Creditcard('cc');
    }

    /**
     * @param string $creditcard
     *
     * @covers Core_Validate_Creditcard::isValid
     * @covers Core_Validate_Creditcard::<protected>
     * @dataProvider getValid
     */
    public function testIsValid($creditcard)
    {
        parent::testIsValid($creditcard);
    }

    /**
     * @param string $creditcard
     *
     * @covers Core_Validate_Creditcard::isValid
     * @covers Core_Validate_Creditcard::<protected>
     * @dataProvider getInvalid
     */
    public function testIsNotValid($creditcard)
    {
        parent::testIsNotValid($creditcard);
    }

    /**
     * @covers Core_Validate_Creditcard::setValidTypes
     * @covers Core_Validate_Creditcard::getValidTypes
     */
    public function testCanSetAndGetValidTypes()
    {
        $validTypes = array(
            Core_Validate_Creditcard::TYPE_VISA,
            Core_Validate_Creditcard::TYPE_MASTERCARD
        );
        $this->_object->setValidTypes($validTypes);
        $this->assertEquals($validTypes, $this->_object->getValidTypes());
    }

    /**
     * @covers Core_Validate_Creditcard::addValidType
     */
    public function testCanAddValidType()
    {
        $this->_object->addValidType(Core_Validate_Creditcard::TYPE_MAESTRO);

        $this->assertEquals(array(Core_Validate_Creditcard::TYPE_MAESTRO), $this->_object->getValidTypes());
    }


    /**
     * @covers Core_Validate_Creditcard::addValidType
     */
    public function testAddingAnUnknownCardTypeAsValidThrowsAnInvalidArgumentException()
    {
        $this->setExpectedException('InvalidArgumentException');

        $this->_object->addValidType('WTF?!');
    }

    /**
     * @covers Core_Validate_Creditcard::getValidTypes
     */
    public function testAllKnownTypesAreValidByDefault()
    {
        $knownTypes = array(
            Core_Validate_Creditcard::TYPE_AMERICAN_EXPRESS,
            Core_Validate_Creditcard::TYPE_DINERS,
            Core_Validate_Creditcard::TYPE_MAESTRO,
            Core_Validate_Creditcard::TYPE_MASTERCARD,
            Core_Validate_Creditcard::TYPE_VISA,
        );
        $this->assertEquals($knownTypes, $this->_object->getValidTypes());
    }

    /**
     * @covers Core_Validate_Creditcard::isValid
     * @covers Core_Validate_Creditcard::<protected>
     */
    public function testWillAcceptValidNumberIfTypeAllowed()
    {
        $this->_object->addValidType(Core_Validate_Creditcard::TYPE_MASTERCARD);

        // valid MasterCard
        $this->assertTrue($this->_object->isValid('5464000000000008'));
    }

    /**
     * @covers Core_Validate_Creditcard::isValid
     * @covers Core_Validate_Creditcard::<protected>
     */
    public function testWillNotAcceptValidNumberIfTypeNotAllowed()
    {
        $this->_object->addValidType(Core_Validate_Creditcard::TYPE_VISA);

        // valid MasterCard
        $this->assertFalse($this->_object->isValid('5464000000000008'));
    }

    /**
     * @covers Core_Validate_Creditcard::getCurrentType
     */
    public function testCanGetCurrentTypeAfterValidation()
    {
        // valid MasterCard
        $this->assertTrue($this->_object->isValid('5464000000000008'));

        $this->assertEquals(Core_Validate_Creditcard::TYPE_MASTERCARD, $this->_object->getCurrentType());
    }

    /**
     * @covers Core_Validate_Creditcard::getCurrentType
     */
    public function testGetCurrentTypeWithNoNumberValidatedWillThrowAnRuntimeException()
    {
        $this->setExpectedException('RuntimeException');
        $this->_object->getCurrentType();
    }

    /**
     * @covers Core_Validate_Creditcard::getCurrentType
     * @depends testGetCurrentTypeWithNoNumberValidatedWillThrowAnRuntimeException
     */
    public function testGetCurrentTypeWithInvalidNumberValidatedWillThrowAnRuntimeException()
    {
        // invalid MasterCard checksum (should be 7)
        $this->assertFalse($this->_object->isValid('5464000000000006'));

        // it's the same as no number at all
        $this->setExpectedException('RuntimeException');
        $this->_object->getCurrentType();
    }
}