Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/friendsofcake/crud-json-api/tests/TestCase/Error/JsonApiExceptionRendererTest.php
<?php
namespace CrudJsonApi\Test\TestCase\Error;

use
Cake\Core\Configure;
use
Cake\Core\Exception\Exception;
use
Cake\Core\Plugin;
use
Cake\Filesystem\File;
use
Cake\Http\Response;
use
Cake\Http\ServerRequest;
use
Cake\ORM\TableRegistry;
use
Crud\Error\Exception\ValidationException;
use
Crud\TestSuite\TestCase;
use
Neomerx\JsonApi\Schema\ErrorCollection;

class
JsonApiExceptionRendererTest extends TestCase
{
   
/**
     * Path to directory holding the JSON API response fixtures
     *
     * @var
     */
   
protected $_JsonApiResponseBodyFixtures;

   
/**
     * fixtures property
     *
     * @var array
     */
   
public $fixtures = [
       
'plugin.CrudJsonApi.Countries',
    ];

   
/**
     * setUp
     */
   
public function setUp()
    {
       
parent::setUp();
       
Configure::write('debug', true);

       
$this->deprecated(function () {
            \
Cake\Core\Plugin::load('Crud', ['path' => ROOT . DS, 'autoload' => true]);
            \
Cake\Core\Plugin::load('CrudJsonApi', ['path' => ROOT . DS, 'autoload' => true]);
        });

       
// set path to the JSON API response fixtures
       
$this->_JsonApiResponseBodyFixtures = Plugin::path('Crud') . 'tests' . DS . 'Fixture' . DS . 'JsonApiResponseBodies';
    }

   
/**
     * Make sure non-validation errors are rendered.
     *
     * @return void
     */
   
public function testRenderWithNonValidationError()
    {
       
$exception = new Exception('Hello World');

       
$controller = $this->getMockBuilder('Cake\Controller\Controller')
            ->
setMethods(['render'])
            ->
getMock();
       
$controller->request = new ServerRequest([
           
'environment' => [
               
'HTTP_ACCEPT' => 'application/vnd.api+json'
           
]
        ]);
       
$controller->response = new Response();

       
$renderer = $this->getMockBuilder('CrudJsonApi\Error\JsonApiExceptionRenderer')
            ->
setMethods(['_getController'])
            ->
disableOriginalConstructor()
            ->
getMock();
       
$renderer
           
->expects($this->once())
            ->
method('_getController')
            ->
with()
            ->
will($this->returnValue($controller));

       
$renderer->__construct($exception);
       
$renderer->render();

       
$viewVars = $controller->viewVars;

       
// assert viewVars required to generate JSON API error are present
       
$this->assertTrue(!empty($viewVars['_serialize']));

       
$expected = ['message', 'url', 'code'];
       
$actual = $viewVars['_serialize'];
       
$actual = array_flip($actual);
        unset(
$actual['file'], $actual['line']);
       
$actual = array_flip($actual);
       
$this->assertEquals($expected, $actual);

       
$this->assertEquals($viewVars['message'], 'Hello World');
       
$this->assertEquals($viewVars['code'], 500);
       
$this->assertEquals($viewVars['url'], '/');
    }

   
/**
     * Make sure validation errors are rendered.
     *
     * @return void
     */
   
public function testRenderWithValidationError()
    {
       
$countries = TableRegistry::get('Countries');

       
$invalidCountry = $countries->newEntity([
           
'code' => 'not-all-uppercase'
       
]);

       
$exception = new ValidationException($invalidCountry);

       
$controller = $this->getMockBuilder('Cake\Controller\Controller')
            ->
setMethods(['render'])
            ->
getMock();
       
$controller->request = new ServerRequest([
           
'environment' => [
               
'HTTP_ACCEPT' => 'application/vnd.api+json'
           
]
        ]);
       
$controller->response = new Response();

       
$renderer = $this->getMockBuilder('CrudJsonApi\Error\JsonApiExceptionRenderer')
            ->
setMethods(['_getController'])
            ->
disableOriginalConstructor()
            ->
getMock();
       
$renderer
           
->expects($this->once())
            ->
method('_getController')
            ->
with()
            ->
will($this->returnValue($controller));

       
$renderer->__construct($exception);
       
$result = $renderer->render();

       
// assert expected exception is generated
       
$jsonApiFixture = new File($this->_JsonApiResponseBodyFixtures . DS . 'Errors' . DS . 'validation-error-multiple-reasons.json');
       
$jsonApiArray = json_decode($jsonApiFixture->read(), true);

       
$result = json_decode($result->getBody(), true);
        unset(
$result['query']);

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

   
/**
     * Make sure validation status code is set to 422 if fetching status
     * code from the controller causes an exception.
     *
     * @return void
     */
   
public function testValidationExceptionsFallBackToStatusCode422()
    {
       
$countries = TableRegistry::get('Countries');

       
$invalidCountry = $countries->newEntity([]);

       
$exception = new ValidationException($invalidCountry);

       
$controller = $this->getMockBuilder('Cake\Controller\Controller')
            ->
setMethods(['render'])
            ->
getMock();

       
$controller->request = new ServerRequest([
           
'environment' => [
               
'HTTP_ACCEPT' => 'application/vnd.api+json'
           
]
        ]);

       
$res = new Response();

       
$response = $this->getMockBuilder('Cake\Http\Response')
            ->
setMethods(['withStatus'])
            ->
getMock();
       
$response
           
->expects($this->at(0))
            ->
method('withStatus')
            ->
will($this->throwException(new Exception('woot')));
       
$response
           
->expects($this->at(1))
            ->
method('withStatus')
            ->
will($this->returnCallback(function ($input) use ($res) {
                return
$res->withStatus($input);
            }));

       
$controller->response = $response;

       
$renderer = $this->getMockBuilder('CrudJsonApi\Error\JsonApiExceptionRenderer')
            ->
setMethods(['_getController'])
            ->
disableOriginalConstructor()
            ->
getMock();
       
$renderer
           
->expects($this->once())
            ->
method('_getController')
            ->
with()
            ->
will($this->returnValue($controller));

       
$renderer->__construct($exception);
       
$result = $renderer->render();
       
$this->assertEquals(422, $result->getStatusCode());
    }

   
/**
     * Make sure both built-in and user-defined validation errors get
     * converted to similar array format used to generate JSON API errors.
     *
     * @return void
     */
   
public function testStandardizeValidationErrors()
    {
       
$errors = [
           
'name' => [
               
'_empty' => 'This is a single word built-in rule'
           
],
           
'dummy_counter' => [
               
'integer' => 'This is a two word built-in rule'
           
],
           
'code' => [
               
0 => [
                   
'fields' => [
                       
0 => 'code'
                   
],
                   
'name' => 'EXACT_LENGTH',
                   
'message' => 'This is a user-defined rule'
               
]
            ],
        ];

       
$renderer = $this->getMockBuilder('CrudJsonApi\Error\JsonApiExceptionRenderer')
            ->
setMethods(null)
            ->
disableOriginalConstructor()
            ->
getMock();

       
$this->setReflectionClassInstance($renderer);

       
$expected = [
           
0 => [
               
'fields' => [
                   
'name'
               
],
               
'name' => '_empty',
               
'message' => 'This is a single word built-in rule'
           
],
           
1 => [
               
'fields' => [
                   
'dummy-counter'
               
],
               
'name' => 'integer',
               
'message' => 'This is a two word built-in rule'
           
],
           
2 => [
               
'fields' => [
                   
'code'
               
],
               
'name' => 'EXACT_LENGTH',
               
'message' => 'This is a user-defined rule'
           
],
        ];

       
$result = $this->callProtectedMethod('_standardizeValidationErrors', [$errors], $renderer);
       
$this->assertEquals($expected, $result);
    }

   
/**
     * Make sure a NeoMerx ErrorCollection is either created from validation
     * errors OR a cloaked existing collection is retrieved as-is from the
     * JsonApiListener property.
     *
     * @return void
     */
   
public function testGetNeoMerxErrorCollection()
    {
       
$renderer = $this->getMockBuilder('CrudJsonApi\Error\JsonApiExceptionRenderer')
            ->
setMethods(null)
            ->
disableOriginalConstructor()
            ->
getMock();

       
$this->setReflectionClassInstance($renderer);

       
// assert that cloaked error collection passed to the exception as
        // a CrudJsonApiListener validation error returned as-is
       
$collection = new ErrorCollection();
       
$collection->addDataError('My manual test error');
       
$validationErrors = [
           
'CrudJsonApiListener' => [
               
'NeoMerxErrorCollection' => $collection
           
]
        ];

       
$result = $this->callProtectedMethod('_getNeoMerxErrorCollection', [$validationErrors], $renderer);
       
$this->assertSame($collection, $result);

       
// assert that the cloaking key is not returned as-is if it does not
        // contain an error collection and thus a new collection is created.
       
$validationErrors = [
           
'CrudJsonApiListener' => [
               
'NeoMerxErrorCollection' => 'not-a-neomerx-error-collection'
           
]
        ];

       
$result = $this->callProtectedMethod('_getNeoMerxErrorCollection', [$validationErrors], $renderer);
       
$errors = $result->getArrayCopy();
       
$error = $errors[0];
       
$this->setReflectionClassInstance($error);

       
$this->assertSame('not-a-neomerx-error-collection', $this->getProtectedProperty('detail', $error));

       
// assert basic collections are created as well
       
$nonStandardizedValidationErrors = [
           
'name' => [
               
'_required' => 'This is a built-in rule'
           
],
           
'code' => [
               
'_required' => 'This is a built-in rule'
           
],
        ];

       
$result = $this->callProtectedMethod('_getNeoMerxErrorCollection', [$nonStandardizedValidationErrors], $renderer);

       
$this->assertInstanceOf(ErrorCollection::class, $result);
       
$this->assertSame(2, $result->count());
    }

   
/**
     * Make sure top-level `query` node is only added to the json if
     * ApiQueryLogListener is loaded.
     *
     * @return void
     */
   
public function testAddQueryLogs()
    {
       
$apiQueryLogListener = $this->getMockBuilder('Crud\Listener\ApiQueryLogListener')
            ->
setMethods(['getQueryLogs'])
            ->
disableOriginalConstructor()
            ->
getMock();
       
$apiQueryLogListener
           
->expects($this->at(0))
            ->
method('getQueryLogs')
            ->
with()
            ->
will($this->returnValue(null));
       
$apiQueryLogListener
           
->expects($this->at(1))
            ->
method('getQueryLogs')
            ->
with()
            ->
will($this->returnValue([
               
'dummy' => 'log-entry'
           
]));

       
$renderer = $this->getMockBuilder('CrudJsonApi\Error\JsonApiExceptionRenderer')
            ->
setMethods(['_getApiQueryLogListenerObject'])
            ->
disableOriginalConstructor()
            ->
getMock();
       
$renderer
           
->expects($this->exactly(2))
            ->
method('_getApiQueryLogListenerObject')
            ->
with()
            ->
will($this->returnValue($apiQueryLogListener));

       
$this->setReflectionClassInstance($renderer);

       
$json = '{"data": {"dummy": "data"}}';

       
// assert query node is not added when listener is not loaded/does not provide logs
       
$result = $this->callProtectedMethod('_addQueryLogsNode', [$json], $renderer);
       
$this->assertJsonStringEqualsJsonString($json, $result);

       
// assert query node is added when listener is loaded
       
$result = $this->callProtectedMethod('_addQueryLogsNode', [$json], $renderer);
       
$resultArray = json_decode($result, true);
       
$this->assertArrayHasKey('query', $resultArray);
    }
}