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

use
CrudJsonApi\Listener\JsonApi\DocumentValidator;
use
Crud\TestSuite\TestCase;
use
Neomerx\JsonApi\Contracts\Schema\LinkInterface;
use
Neomerx\JsonApi\Schema\ErrorCollection;
use
stdClass;

/**
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 */
class DocumentValidatorTest extends TestCase
{
   
/**
     * @var DocumentValidator
     */
   
protected $_validator;

   
/**
     * Create a DocumentValidator instance for every test with disabled
     * aboutLinks config option.
     */
   
public function setUp()
    {
       
parent::setUp();
       
$this->_validator = new DocumentValidator([], []);
       
$this->setReflectionClassInstance($this->_validator);

       
$listenerConfig = [
           
'docValidatorAboutLinks' => false
       
];
       
$this->setProtectedProperty('_config', $listenerConfig, $this->_validator);
    }

   
/**
     * tearDown.
     */
   
public function tearDown()
    {
       
parent::tearDown();
        unset(
$this->_validator);
    }

   
/**
     * _validateCreateDocument()
     *
     * @expectedException \Crud\Error\Exception\ValidationException
     * @expectedExceptionMessage A validation error occurred
     */
   
public function testValidateCreateDocument()
    {
       
// assert success
       
$document = [
           
'data' => [
               
'type' => 'must-be-string',
               
'id' => 'd0b31ee1-4637-48c9-b9ef-fcefbb83d86f'
           
]
        ];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertNull($this->_validator->validateCreateDocument());

       
// assert exception
       
$document['data']['id'] = 'not-a-valid-uuid';
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->_validator->validateCreateDocument();
    }

   
/**
     * _validateUpdateDocument()
     *
     * @expectedException \Crud\Error\Exception\ValidationException
     * @expectedExceptionMessage A validation error occurred
     */
   
public function testValidateUpdateDocument()
    {
       
// assert success
       
$document = [
           
'data' => [
               
'type' => 'must-be-string',
               
'id' => 'must-be-string',
            ]
        ];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertNull($this->_validator->validateUpdateDocument());

       
// assert exception
       
$document['data']['id'] = null;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->_validator->validateUpdateDocument();
    }

   
/**
     * _documentMustHavePrimaryData()
     *
     * @expectedException \Crud\Error\Exception\ValidationException
     * @expectedExceptionMessage A validation error occurred
     */
   
public function testDocumentMustHavePrimaryData()
    {
       
// assert success
       
$document = [
           
'data' => []
        ];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_documentMustHavePrimaryData', [], $this->_validator));

       
// assert exception
       
$document = [];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->callProtectedMethod('_documentMustHavePrimaryData', [], $this->_validator);
    }

   
/**
     * _primaryDataMustHaveType()
     *
     * @return void
     */
   
public function testPrimaryDataMustHaveType()
    {
       
// assert success
       
$document = [
           
'data' => [
               
'type' => 'must-be-string'
           
]
        ];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_primaryDataMustHaveType', [], $this->_validator));

       
// assert false for non-string
       
$document['data']['type'] = 123;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_primaryDataMustHaveType', [], $this->_validator));

       
// assert exception
       
$document = [];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->callProtectedMethod('_primaryDataMustHaveType', [], $this->_validator);
    }

   
/**
     * _primaryDataMayHaveUiId()
     *
     * @return void
     */
   
public function testPrimaryDataMayHaveUuid()
    {
       
// assert success
       
$document = [
           
'data' => [
               
'id' => 'edd28c99-216b-4ef7-a806-d865aca14f17'
           
]
        ];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_primaryDataMayHaveUuid', [], $this->_validator));

       
// assert false for non-string
       
$document['data']['id'] = 123;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_primaryDataMayHaveUuid', [], $this->_validator));

       
// assert exception
       
$document = [];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->callProtectedMethod('_primaryDataMayHaveUuid', [], $this->_validator);
    }

   
/**
     * _primaryDataMustHaveId()
     *
     * @return void
     */
   
public function testPrimaryDataMustHaveId()
    {
       
// assert success
       
$document = [
           
'data' => [
               
'type' => 'must-be-string',
               
'id' => 'must-be-string',
            ]
        ];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_primaryDataMustHaveId', [], $this->_validator));

       
// assert false for non-string
       
$document['data']['id'] = 123;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_primaryDataMustHaveId', [], $this->_validator));

       
// assert exception
       
$document = [];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->callProtectedMethod('_primaryDataMustHaveId', [], $this->_validator);
    }

   
/**
     * _primaryDataMayHaveRelationShips()
     *
     * @return void
     */
   
public function testPrimaryDataMayHaveRelationships()
    {
       
// assert pass if relationships node with valid members exists
       
$document = [
           
'data' => [
               
'type' => 'countries',
               
'relationships' => [
                   
'cultures' => [
                       
'data' => [
                            [
                               
'type' => 'cultures',
                               
'id' => '1'
                           
]
                        ]
                    ],
                   
'currency' => [
                       
'data' => [
                           
'type' => 'currencies',
                           
'id' => '2'
                       
]
                    ]
                ]
            ]
        ];

       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_primaryDataMayHaveRelationships', [], $this->_validator));

       
// assert foreach loop continues if belongsTo relation has empty/null data node
       
$document['data']['relationships']['currency']['data'] = null;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_primaryDataMayHaveRelationships', [], $this->_validator));

       
// assert foreach loop continues if belongsTo relation does not have data node
       
unset($document['data']['relationships']['currency']['data']);
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_primaryDataMayHaveRelationships', [], $this->_validator));

       
// assert foreach loop continues if hasMany relation has empty/null data node
       
$document['data']['relationships']['cultures']['data'] = null;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_primaryDataMayHaveRelationships', [], $this->_validator));

       
// assert foreach loop continues if hasMany relation does not have data node
       
unset($document['data']['relationships']['cultures']['data']);
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_primaryDataMayHaveRelationships', [], $this->_validator));

       
// assert non-pass if `relationships` exists but has no members
       
$document['data']['relationships'] = [];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_primaryDataMayHaveRelationships', [], $this->_validator));

       
// assert pass if `relationships` does not exist at all
       
unset($document['data']['relationships']);
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_primaryDataMayHaveRelationships', [], $this->_validator));
    }

   
/**
     * _relationshipMustHaveData()
     *
     * @return void
     */
   
public function testRelationshipMustHaveData()
    {
       
$document = [
           
'data' => [
               
'type' => 'countries',
               
'relationships' => [
                   
'cultures' => [
                       
'data' => [
                            [
                               
'type' => 'cultures',
                               
'id' => '1'
                           
]
                        ]
                    ],
                   
'currency' => [
                       
'data' => [
                           
'type' => 'currencies',
                           
'id' => '2'
                       
]
                    ]
                ]
            ]
        ];

       
// assert success when belongsTo relation has data node
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_relationshipMustHaveData', ['data.relationships.currency'], $this->_validator));

       
// assert fail when belongsTo relation is missing data node
       
unset($document['data']['relationships']['currency']['data']);
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_relationshipMustHaveData', ['data.relationships.currency'], $this->_validator));

       
// assert success when hasMany relation has data node
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_relationshipMustHaveData', ['data.relationships.cultures'], $this->_validator));

       
// assert fail when hasMany relation is missing data node
       
unset($document['data']['relationships']['cultures']['data']);
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_relationshipMustHaveData', ['data.relationships.cultures'], $this->_validator));
    }

   
/**
     * _relationshipDataMustHaveType()
     *
     * @return void
     */
   
public function testRelationshipDataMustHaveType()
    {
       
$document = [
           
'data' => [
               
'type' => 'countries',
               
'relationships' => [
                   
'cultures' => [
                       
'data' => [
                            [
                               
'type' => 'cultures',
                               
'id' => '1'
                           
]
                        ]
                    ],
                   
'currency' => [
                       
'data' => [
                           
'type' => 'currencies',
                           
'id' => '2'
                       
]
                    ]
                ]
            ]
        ];

       
// assert success when belongsTo relationship data has valid type node
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_relationshipDataMustHaveType', ['currency', 'data.relationships.currency'], $this->_validator));

       
// assert fail when belongsTo relationship data has type node but it's value is not a string
       
$document['data']['relationships']['currency']['data']['type'] = 123;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_relationshipDataMustHaveType', ['currency', 'data.relationships.currency'], $this->_validator));

       
// assert fail when belongsTo relationship data does not have type node
       
unset($document['data']['relationships']['currency']['data']['type']);
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_relationshipDataMustHaveType', ['currency', 'data.relationships.currency'], $this->_validator));

       
// assert success when all hasMany relationships have data with valid type node
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_relationshipDataMustHaveType', ['cultures', 'data.relationships.cultures.data.0'], $this->_validator));

       
// assert fail when one of the hasMany relationships has data with type node but it's value is not a string
       
$document['data']['relationships']['cultures']['data'][0]['type'] = 123;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_relationshipDataMustHaveType', ['cultures', 'data.relationships.cultures.data.0'], $this->_validator));

       
// assert fail when one of the hasMany relationships has data without type node
       
unset($document['data']['relationships']['cultures']['data'][0]['type']);
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_relationshipDataMustHaveType', ['cultures', 'data.relationships.cultures.data.0'], $this->_validator));
    }

   
/**
     * _relationshipDataMustHaveId()
     *
     * @return void
     */
   
public function testRelationshipDataMustHaveId()
    {
       
$document = [
           
'data' => [
               
'type' => 'countries',
               
'relationships' => [
                   
'cultures' => [
                       
'data' => [
                            [
                               
'type' => 'cultures',
                               
'id' => '1'
                           
]
                        ]
                    ],
                   
'currency' => [
                       
'data' => [
                           
'type' => 'currencies',
                           
'id' => '2'
                       
]
                    ]
                ]
            ]
        ];

       
// assert success when belongsTo relationship data has valid id node
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_relationshipDataMustHaveId', ['currency', 'data.relationships.currency'], $this->_validator));

       
// assert fail when belongsTo relationship data has id node but it's value is not a string
       
$document['data']['relationships']['currency']['data']['id'] = 123;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_relationshipDataMustHaveId', ['currency', 'data.relationships.currency'], $this->_validator));

       
// assert fail when belongsTo relationship data does not have id node
       
unset($document['data']['relationships']['currency']['data']['id']);
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_relationshipDataMustHaveId', ['currency', 'data.relationships.currency'], $this->_validator));

       
// assert success when all hasMany relationships have data with valid id node
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_relationshipDataMustHaveId', ['cultures', 'data.relationships.cultures.data.0'], $this->_validator));

       
// assert fail when one of the hasMany relationships has data with id node but it's value is not a string
       
$document['data']['relationships']['cultures']['data'][0]['id'] = 123;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_relationshipDataMustHaveId', ['cultures', 'data.relationships.cultures.data.0'], $this->_validator));

       
// assert fail when one of the hasMany relationships has data without id node
       
unset($document['data']['relationships']['cultures']['data'][0]['id']);
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_relationshipDataMustHaveId', ['cultures', 'data.relationships.cultures.data.0'], $this->_validator));
    }

   
/**
     * _isString()
     *
     * @expectedException \Crud\Error\Exception\CrudException
     * @expectedExceptionMessage Document member 'dummy.path' does not exist
     * @return void
     */
   
public function testIsString()
    {
       
// assert success
       
$document = [
           
'data' => 'some-string'
       
];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_isString', ['data'], $this->_validator));

       
// assert false for non-string
       
$document['data'] = 123;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_isString', ['data'], $this->_validator));

       
// assert exception
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_isString', ['dummy.path'], $this->_validator));
    }

   
/**
     * _isString()
     *
     * @expectedException \Crud\Error\Exception\CrudException
     * @expectedExceptionMessage Document member 'dummy.path' does not exist
     * @return void
     */
   
public function testIsUuid()
    {
       
// assert success
       
$document = [
           
'data' => 'edd28c99-216b-4ef7-a806-d865aca14f17'
       
];
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertTrue($this->callProtectedMethod('_isUuid', ['data'], $this->_validator));

       
// assert false for non-string
       
$document['data'] = 123;
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_isUuid', ['data'], $this->_validator));

       
// assert exception
       
$this->setProtectedProperty('_document', $document, $this->_validator);
       
$this->assertFalse($this->callProtectedMethod('_isUuid', ['dummy.path'], $this->_validator));
    }

   
/**
     * _hasProperty()
     *
     * @return void
     */
   
public function testHasProperty()
    {
       
$this->_validator = new DocumentValidator([], []);
       
$this->setReflectionClassInstance($this->_validator);
       
$document = [
           
'data' => [
               
'attributes' => [
                   
'name' => 'bravo-kernel',
                   
'test-null' => null,
                   
'test-true' => true,
                   
'test-false' => false
               
],
               
'sub-array' => [
                    [
                       
'name' => 'bravo-kernel',
                       
'test-null' => null,
                       
'test-true' => true,
                       
'test-false' => false
                   
]
                ]
            ]
        ];
       
$this->setProtectedProperty('_document', $document, $this->_validator);

       
$this->assertTrue($this->callProtectedMethod('_hasProperty', ['data'], $this->_validator));
       
$this->assertTrue($this->callProtectedMethod('_hasProperty', ['data.attributes'], $this->_validator));
       
$this->assertTrue($this->callProtectedMethod('_hasProperty', ['data.attributes.name'], $this->_validator));
       
$this->assertTrue($this->callProtectedMethod('_hasProperty', ['data.attributes.test-null'], $this->_validator));
       
$this->assertTrue($this->callProtectedMethod('_hasProperty', ['data.attributes.test-true'], $this->_validator));
       
$this->assertTrue($this->callProtectedMethod('_hasProperty', ['data.attributes.test-false'], $this->_validator));

       
$this->assertTrue($this->callProtectedMethod('_hasProperty', ['data.sub-array.0'], $this->_validator));
       
$this->assertTrue($this->callProtectedMethod('_hasProperty', ['data.sub-array.0.name'], $this->_validator));
       
$this->assertTrue($this->callProtectedMethod('_hasProperty', ['data.sub-array.0.test-null'], $this->_validator));
       
$this->assertTrue($this->callProtectedMethod('_hasProperty', ['data.sub-array.0.test-true'], $this->_validator));
       
$this->assertTrue($this->callProtectedMethod('_hasProperty', ['data.sub-array.0.test-false'], $this->_validator));

       
$this->assertFalse($this->callProtectedMethod('_hasProperty', ['fake-root'], $this->_validator));
       
$this->assertFalse($this->callProtectedMethod('_hasProperty', ['data.fake-sub'], $this->_validator));
       
$this->assertFalse($this->callProtectedMethod('_hasProperty', ['data.attributes.fake-sub'], $this->_validator));
    }

   
/**
     * _getProperty()
     *
     * @expectedException \Crud\Error\Exception\CrudException
     * @expectedExceptionMessage Error retrieving a value for non-existing JSON API document property 'path.does.not.exist'
     */
   
public function testGetProperty()
    {
       
$this->_validator = new DocumentValidator([], []);
       
$this->setReflectionClassInstance($this->_validator);
       
$document = [
           
'data' => [
               
'attributes' => [
                   
'name' => 'bravo-kernel'
               
]
            ]
        ];
       
$this->setProtectedProperty('_document', $document, $this->_validator);

       
//assert test single and multi-level lookups
       
$expected = [
           
'name' => 'bravo-kernel'
       
];
       
$this->assertEquals($expected, $this->callProtectedMethod('_getProperty', ['data.attributes'], $this->_validator));
       
$this->assertEquals('bravo-kernel', $this->callProtectedMethod('_getProperty', ['data.attributes.name'], $this->_validator));

       
// assert using a path object works as well
       
$obj = new stdClass();
       
$obj->dotted = 'data.attributes.name';
       
$obj->toKey = 'data.attributes';
       
$obj->key = 'name';
       
$this->assertEquals('bravo-kernel', $this->callProtectedMethod('_getProperty', [$obj], $this->_validator));

       
// assert exception
       
$this->callProtectedMethod('_getProperty', ['path.does.not.exist'], $this->_validator);
    }

   
/**
     * _getPathObject()
     *
     * @return void
     */
   
public function testGetPathObject()
    {
       
$this->_validator = new DocumentValidator([], []);
       
$this->setReflectionClassInstance($this->_validator);

       
// assert existing object is returned as-if if passed as argument
       
$obj = new stdClass();
       
$obj->dotted = 'my.path';
       
$obj->toKey = 'my';
       
$obj->key = 'path';

       
$this->assertEquals($obj, $this->callProtectedMethod('_getPathObject', [$obj], $this->_validator));

       
// assert object is created with expected properties
       
$obj = $this->callProtectedMethod('_getPathObject', ['data'], $this->_validator);

       
$this->assertTrue(is_a($obj, 'stdClass'));
       
$this->assertObjectHasAttribute('dotted', $obj);
       
$this->assertObjectHasAttribute('toKey', $obj);
       
$this->assertObjectHasAttribute('key', $obj);

       
// assert single-level path
       
$this->assertEquals('data', $obj->dotted);
       
$this->assertEquals('', $obj->toKey);
       
$this->assertEquals('data', $obj->key);

       
// assert two-level path
       
$obj = $this->callProtectedMethod('_getPathObject', ['data.attributes'], $this->_validator);

       
$this->assertEquals('data.attributes', $obj->dotted);
       
$this->assertEquals('data', $obj->toKey);
       
$this->assertEquals('attributes', $obj->key);

       
// assert three-level path
       
$obj = $this->callProtectedMethod('_getPathObject', ['data.attributes.name'], $this->_validator);

       
$this->assertEquals('data.attributes.name', $obj->dotted);
       
$this->assertEquals('data.attributes', $obj->toKey);
       
$this->assertEquals('name', $obj->key);
    }

   
/**
     * _getAboutLink()
     *
     * @return void
     */
   
public function testGetAboutLink()
    {
       
$this->_validator = new DocumentValidator([], []);
       
$this->setReflectionClassInstance($this->_validator);

       
// assert no link is created if disabled in listener config
       
$listenerConfig = [
           
'docValidatorAboutLinks' => false
       
];

       
$this->setProtectedProperty('_config', $listenerConfig, $this->_validator);
       
$this->assertNull($this->callProtectedMethod('_getAboutLink', ['http://www.friendsofcake.com'], $this->_validator));

       
// assert link is created when enabled in listener config
       
$listenerConfig = [
           
'docValidatorAboutLinks' => true
       
];

       
$this->setProtectedProperty('_config', $listenerConfig, $this->_validator);
       
$result = $this->callProtectedMethod('_getAboutLink', ['http://www.friendsofcake.com'], $this->_validator);

       
$this->assertInstanceOf(LinkInterface::class, $result);
    }

   
/**
     * Make sure _getErrorCollectionEntity() generates the expected entity
     * with NeoMerx ErrorCollection.
     *
     * @return void
     */
   
public function testGetErrorCollectionEntity()
    {
       
$this->_validator = new DocumentValidator([], []);
       
$this->setReflectionClassInstance($this->_validator);

       
$result = $this->callProtectedMethod('_getErrorCollectionEntity', [], $this->_validator);
       
$this->assertInstanceOf('\Cake\ORM\Entity', $result);

       
$errors = $result->getErrors();
       
$this->assertArrayHasKey('CrudJsonApiListener', $errors);
       
$this->assertArrayHasKey('NeoMerxErrorCollection', $errors['CrudJsonApiListener']);
       
$this->assertInstanceOf(ErrorCollection::class, $errors['CrudJsonApiListener']['NeoMerxErrorCollection']);
    }
}