<commit_before><?php

namespace AvalancheDevelopment\SwaggerRouterMiddleware;

use AvalancheDevelopment\SwaggerRouterMiddleware\Parser\ParserInterface;
use DateTime;
use PHPUnit_Framework_TestCase;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\UriInterface;
use ReflectionClass;

class ParameterParserTest extends PHPUnit_Framework_TestCase
{

    public function testInvokeCallsGetParser()
    {
        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [ 'something here' ];
        $mockRoute = '/some-route';
        $mockValue = 'some value';

        $mockParser = $this->createMock(ParserInterface::class);
        $mockParser->method('getValue')
            ->willReturn($mockValue);

        $parameterParser = $this->getMockBuilder(ParameterParser::class)
            ->setMethods([ 'getParser', 'castType' ])
            ->getMock();
        $parameterParser->expects($this->once())
            ->method('getParser')
            ->with($mockRequest, $mockParameter, $mockRoute)
            ->willReturn($mockParser);
        $parameterParser->method('castType')
            ->will($this->returnArgument(0));

        $parameterParser->__invoke($mockRequest, $mockParameter, $mockRoute);
    }

    public function testInvokeUsesParserFromGetParser()
    {
        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [ 'something here' ];
        $mockRoute = '/some-route';
        $mockValue = 'some value';

        $mockParser = $this->createMock(ParserInterface::class);
        $mockParser->expects($this->once())
            ->method('getValue')
            ->willReturn($mockValue);

        $parameterParser = $this->getMockBuilder(ParameterParser::class)
            ->setMethods([ 'getParser', 'castType' ])
            ->getMock();
        $parameterParser->method('getParser')
            ->willReturn($mockParser);
        $parameterParser->method('castType')
            ->will($this->returnArgument(0));

        $parameterParser->__invoke($mockRequest, $mockParameter, $mockRoute);
    }

    public function testInvokeReturnsDefaultValue()
    {
        $expectedValue = 'some default value';

        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [
            'default' => $expectedValue,
        ];
        $mockRoute = '/some-route';
        $mockValue = null;

        $mockParser = $this->createMock(ParserInterface::class);
        $mockParser->method('getValue')
            ->willReturn($mockValue);

        $parameterParser = $this->getMockBuilder(ParameterParser::class)
            ->setMethods([ 'getParser', 'castType' ])
            ->getMock();
        $parameterParser->method('getParser')
            ->willReturn($mockParser);
        $parameterParser->expects($this->once())
            ->method('castType')
            ->with($expectedValue, $mockParameter)
            ->will($this->returnArgument(0));

        $parameterParser->__invoke($mockRequest, $mockParameter, $mockRoute);
    }

    public function testInvokeUsesValueFromParser()
    {
        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [ 'something here' ];
        $mockRoute = '/some-route';
        $mockValue = 'some value';

        $mockParser = $this->createMock(ParserInterface::class);
        $mockParser->method('getValue')
            ->willReturn($mockValue);

        $parameterParser = $this->getMockBuilder(ParameterParser::class)
            ->setMethods([ 'getParser', 'castType' ])
            ->getMock();
        $parameterParser->method('getParser')
            ->willReturn($mockParser);
        $parameterParser->expects($this->once())
            ->method('castType')
            ->with($mockValue, $mockParameter)
            ->will($this->returnArgument(0));

        $parameterParser->__invoke($mockRequest, $mockParameter, $mockRoute);
    }

    public function testInvokeReturnsCastValue()
    {
        $expectedValue = 'some value';

        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [ 'something here' ];
        $mockRoute = '/some-route';
        $mockValue = 'some other value';

        $mockParser = $this->createMock(ParserInterface::class);
        $mockParser->method('getValue')
            ->willReturn($mockValue);

        $parameterParser = $this->getMockBuilder(ParameterParser::class)
            ->setMethods([ 'getParser', 'castType' ])
            ->getMock();
        $parameterParser->method('getParser')
            ->willReturn($mockParser);
        $parameterParser->method('castType')
            ->willReturn($expectedValue);

        $result = $parameterParser->__invoke($mockRequest, $mockParameter, $mockRoute);

        $this->assertSame($expectedValue, $result);
    }

    public function testCastTypeHandlesArray()
    {
        $parameter = [
            'items' => [
                'type' => 'string',
            ],
        ];
        $value = [
            123,
            456,<commit_msg>Adds rest of tests around new parameter parser structure<commit_after><?php

namespace AvalancheDevelopment\SwaggerRouterMiddleware;

use AvalancheDevelopment\SwaggerRouterMiddleware\Parser\ParserInterface;
use DateTime;
use PHPUnit_Framework_TestCase;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\UriInterface;
use ReflectionClass;

class ParameterParserTest extends PHPUnit_Framework_TestCase
{

    public function testInvokeCallsGetParser()
    {
        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [ 'something here' ];
        $mockRoute = '/some-route';
        $mockValue = 'some value';

        $mockParser = $this->createMock(ParserInterface::class);
        $mockParser->method('getValue')
            ->willReturn($mockValue);

        $parameterParser = $this->getMockBuilder(ParameterParser::class)
            ->setMethods([ 'getParser', 'castType' ])
            ->getMock();
        $parameterParser->expects($this->once())
            ->method('getParser')
            ->with($mockRequest, $mockParameter, $mockRoute)
            ->willReturn($mockParser);
        $parameterParser->method('castType')
            ->will($this->returnArgument(0));

        $parameterParser->__invoke($mockRequest, $mockParameter, $mockRoute);
    }

    public function testInvokeUsesParserFromGetParser()
    {
        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [ 'something here' ];
        $mockRoute = '/some-route';
        $mockValue = 'some value';

        $mockParser = $this->createMock(ParserInterface::class);
        $mockParser->expects($this->once())
            ->method('getValue')
            ->willReturn($mockValue);

        $parameterParser = $this->getMockBuilder(ParameterParser::class)
            ->setMethods([ 'getParser', 'castType' ])
            ->getMock();
        $parameterParser->method('getParser')
            ->willReturn($mockParser);
        $parameterParser->method('castType')
            ->will($this->returnArgument(0));

        $parameterParser->__invoke($mockRequest, $mockParameter, $mockRoute);
    }

    public function testInvokeReturnsDefaultValue()
    {
        $expectedValue = 'some default value';

        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [
            'default' => $expectedValue,
        ];
        $mockRoute = '/some-route';
        $mockValue = null;

        $mockParser = $this->createMock(ParserInterface::class);
        $mockParser->method('getValue')
            ->willReturn($mockValue);

        $parameterParser = $this->getMockBuilder(ParameterParser::class)
            ->setMethods([ 'getParser', 'castType' ])
            ->getMock();
        $parameterParser->method('getParser')
            ->willReturn($mockParser);
        $parameterParser->expects($this->once())
            ->method('castType')
            ->with($expectedValue, $mockParameter)
            ->will($this->returnArgument(0));

        $parameterParser->__invoke($mockRequest, $mockParameter, $mockRoute);
    }

    public function testInvokeUsesValueFromParser()
    {
        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [ 'something here' ];
        $mockRoute = '/some-route';
        $mockValue = 'some value';

        $mockParser = $this->createMock(ParserInterface::class);
        $mockParser->method('getValue')
            ->willReturn($mockValue);

        $parameterParser = $this->getMockBuilder(ParameterParser::class)
            ->setMethods([ 'getParser', 'castType' ])
            ->getMock();
        $parameterParser->method('getParser')
            ->willReturn($mockParser);
        $parameterParser->expects($this->once())
            ->method('castType')
            ->with($mockValue, $mockParameter)
            ->will($this->returnArgument(0));

        $parameterParser->__invoke($mockRequest, $mockParameter, $mockRoute);
    }

    public function testInvokeReturnsCastValue()
    {
        $expectedValue = 'some value';

        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [ 'something here' ];
        $mockRoute = '/some-route';
        $mockValue = 'some other value';

        $mockParser = $this->createMock(ParserInterface::class);
        $mockParser->method('getValue')
            ->willReturn($mockValue);

        $parameterParser = $this->getMockBuilder(ParameterParser::class)
            ->setMethods([ 'getParser', 'castType' ])
            ->getMock();
        $parameterParser->method('getParser')
            ->willReturn($mockParser);
        $parameterParser->method('castType')
            ->willReturn($expectedValue);

        $result = $parameterParser->__invoke($mockRequest, $mockParameter, $mockRoute);

        $this->assertSame($expectedValue, $result);
    }

    public function testGetParserHandlesQueryParameter()
    {
        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [
            'in' => 'query',
        ];
        $mockRoute = '/some-route';

        $reflectedQueryParser = new ReflectionClass(Parser\Query::class);
        $reflectedRequest = $reflectedQueryParser->getProperty('request');
        $reflectedRequest->setAccessible(true);
        $reflectedParameter = $reflectedQueryParser->getProperty('parameter');
        $reflectedParameter->setAccessible(true);

        $reflectedParameterParser = new ReflectionClass(ParameterParser::class);
        $reflectedGetParser = $reflectedParameterParser->getMethod('getParser');
        $reflectedGetParser->setAccessible(true);

        $parameterParser = new ParameterParser;
        $result = $reflectedGetParser->invokeArgs(
            $parameterParser,
            [
                $mockRequest,
                $mockParameter,
                $mockRoute,
            ]
        );

        $this->assertInstanceOf(ParserInterface::class, $result);
        $this->assertInstanceOf(Parser\Query::class, $result);
        $this->assertAttributeSame($mockRequest, 'request', $result);
        $this->assertAttributeSame($mockParameter, 'parameter', $result);
    }

    public function testGetParserHandlesHeaderParameter()
    {
        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [
            'in' => 'header',
        ];
        $mockRoute = '/some-route';

        $reflectedHeaderParser = new ReflectionClass(Parser\Header::class);
        $reflectedRequest = $reflectedHeaderParser->getProperty('request');
        $reflectedRequest->setAccessible(true);
        $reflectedParameter = $reflectedHeaderParser->getProperty('parameter');
        $reflectedParameter->setAccessible(true);

        $reflectedParameterParser = new ReflectionClass(ParameterParser::class);
        $reflectedGetParser = $reflectedParameterParser->getMethod('getParser');
        $reflectedGetParser->setAccessible(true);

        $parameterParser = new ParameterParser;
        $result = $reflectedGetParser->invokeArgs(
            $parameterParser,
            [
                $mockRequest,
                $mockParameter,
                $mockRoute,
            ]
        );

        $this->assertInstanceOf(ParserInterface::class, $result);
        $this->assertInstanceOf(Parser\Header::class, $result);
        $this->assertAttributeSame($mockRequest, 'request', $result);
        $this->assertAttributeSame($mockParameter, 'parameter', $result);
    }

    public function testGetParserHandlesPathParameter()
    {
        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [
            'in' => 'path',
        ];
        $mockRoute = '/some-route';

        $reflectedPathParser = new ReflectionClass(Parser\Path::class);
        $reflectedRequest = $reflectedPathParser->getProperty('request');
        $reflectedRequest->setAccessible(true);
        $reflectedParameter = $reflectedPathParser->getProperty('parameter');
        $reflectedParameter->setAccessible(true);
        $reflectedRoute = $reflectedPathParser->getProperty('route');
        $reflectedRoute->setAccessible(true);

        $reflectedParameterParser = new ReflectionClass(ParameterParser::class);
        $reflectedGetParser = $reflectedParameterParser->getMethod('getParser');
        $reflectedGetParser->setAccessible(true);

        $parameterParser = new ParameterParser;
        $result = $reflectedGetParser->invokeArgs(
            $parameterParser,
            [
                $mockRequest,
                $mockParameter,
                $mockRoute,
            ]
        );

        $this->assertInstanceOf(ParserInterface::class, $result);
        $this->assertInstanceOf(Parser\Path::class, $result);
        $this->assertAttributeSame($mockRequest, 'request', $result);
        $this->assertAttributeSame($mockParameter, 'parameter', $result);
        $this->assertAttributeSame($mockRoute, 'route', $result);
    }

    public function testGetParserHandlesFormParameter()
    {
        $this->markTestIncomplete('not yet implemented');
    }

    public function testGetParserHandlesBodyParameter()
    {
        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [
            'in' => 'body',
        ];
        $mockRoute = '/some-route';

        $reflectedBodyParser = new ReflectionClass(Parser\Body::class);
        $reflectedRequest = $reflectedBodyParser->getProperty('request');
        $reflectedRequest->setAccessible(true);

        $reflectedParameterParser = new ReflectionClass(ParameterParser::class);
        $reflectedGetParser = $reflectedParameterParser->getMethod('getParser');
        $reflectedGetParser->setAccessible(true);

        $parameterParser = new ParameterParser;
        $result = $reflectedGetParser->invokeArgs(
            $parameterParser,
            [
                $mockRequest,
                $mockParameter,
                $mockRoute,
            ]
        );

        $this->assertInstanceOf(ParserInterface::class, $result);
        $this->assertInstanceOf(Parser\Body::class, $result);
        $this->assertAttributeSame($mockRequest, 'request', $result);
    }

    /**
     * @expectedException Exception
     * @expectedExceptionMessage Invalid parameter type defined in swagger
     */
    public function testGetParserBailsOnInvalidParameter()
    {
        $mockRequest = $this->createMock(RequestInterface::class);
        $mockParameter = [
            'in' => 'invalid',
        ];
        $mockRoute = '/some-route';

        $reflectedParameterParser = new ReflectionClass(ParameterParser::class);
        $reflectedGetParser = $reflectedParameterParser->getMethod('getParser');
        $reflectedGetParser->setAccessible(true);

        $parameterParser = new ParameterParser;
        $reflectedGetParser->invokeArgs(
            $parameterParser,
            [
                $mockRequest,
                $mockParameter,
                $mockRoute,
            ]
        );
    }

    public function testCastTypeHandlesArray()
    {
        $parameter = [
            'items' => [
                'type' => 'string',
            ],
        ];
        $value = [
            123,
            456,
{'fraction_non_alphanumeric': 0.13554768592013677, 'fraction_numerical': 0.0012211503236048357, 'mean_word_length': 2.6956227436823106, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 219, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3001783', 'n_tokens_mistral': 4260, 'n_tokens_neox': 4166, 'n_words': 622}