<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace ZendTest\Code\Annotation;

use PHPUnit\Framework\TestCase;
use Zend\Code\Annotation\Parser\DoctrineAnnotationParser;
use Zend\Code\Exception\InvalidArgumentException;
use Zend\EventManager\Event;

use function getenv;

class DoctrineAnnotationParserTest extends TestCase
{
    /**
     * @var DoctrineAnnotationParser
     */
    private $parser;

    protected function setUp() : void
    {
        if (! getenv('TESTS_ZEND_CODE_ANNOTATION_DOCTRINE_SUPPORT')) {
            $this->markTestSkipped(
                'Enable TESTS_ZEND_CODE_ANNOTATION_DOCTRINE_SUPPORT to test doctrine annotation parsing'
            );
        }

        $this->parser = new DoctrineAnnotationParser();
    }

    public function getEvent()
    {
        $event = new Event();
        $event->setParams([
            'class'   => __NAMESPACE__ . '\TestAsset\DoctrineAnnotation',
            'content' => '(foo="bar")',
            'raw'     => '@' . __NAMESPACE__ . '\TestAsset\DoctrineAnnotation(foo="bar")',
        ]);
        return $event;
    }

    public function testParserCreatesNewAnnotationInstances()
    {
        $this->parser->registerAnnotation(__NAMESPACE__ . '\TestAsset\DoctrineAnnotation');

        $event = $this->getEvent();
        $test  = $this->parser->onCreateAnnotation($event);
        self::assertInstanceOf(__NAMESPACE__ . '\TestAsset\DoctrineAnnotation', $test);
        self::assertEquals(['foo' => 'bar'], $test->value);
    }

    public function testReturnsFalseDuringCreationIfAnnotationIsNotRegistered()
    {
        $event = $this->getEvent();
        self::assertFalse($this->parser->onCreateAnnotation($event));
    }

    public function testReturnsFalseClassNotSet()
    {
        self::assertFalse($this->parser->onCreateAnnotation(new Event()));
    }

    public function testReturnsFalseRawNotSet()
    {
        $this->parser->registerAnnotation(__NAMESPACE__ . '\TestAsset\DoctrineAnnotation');
        $event = $this->getEvent();
        $event->setParam('raw', false);

        self::assertFalse($this->parser->onCreateAnnotation($event));
    }

    public function testReturnsFalseEmptyAnnotations()
    {
        $this->parser->registerAnnotation(__NAMESPACE__ . '\TestAsset\DoctrineAnnotation');
        $event = $this->getEvent();
        $event->setParam('raw', 'foo');
        self::assertFalse($this->parser->onCreateAnnotation($event));
    }

    public function testRegisterAnnotationsThrowsException()
    {
        $this->expectException(InvalidArgumentException::class);
        $this->parser->registerAnnotations('some string');
    }

    public function testRegisterAnnotations()
    {
        $this->parser->registerAnnotations([__NAMESPACE__ . '\TestAsset\DoctrineAnnotation']);
        $event = $this->getEvent();
        $test  = $this->parser->onCreateAnnotation($event);
        self::assertInstanceOf(__NAMESPACE__ . '\TestAsset\DoctrineAnnotation', $test);
        self::assertEquals(['foo' => 'bar'], $test->value);
    }
}
