request = new Request(); } /** * Test getting primary key data. * * @return void */ public function testPrimaryKey() { $row = new Article(); $context = new EntityContext($this->request, [ 'entity' => $row, ]); $this->assertEquals(['id'], $context->primaryKey()); } /** * Test isCreate on a single entity. * * @return void */ public function testIsCreateSingle() { $row = new Entity(); $context = new EntityContext($this->request, [ 'entity' => $row, ]); $this->assertTrue($context->isCreate()); $row->isNew(false); $this->assertFalse($context->isCreate()); $row->isNew(true); $this->assertTrue($context->isCreate()); } /** * Test isCreate on a collection. * * @dataProvider collectionProvider * @return void */ public function testIsCreateCollection($collection) { $context = new EntityContext($this->request, [ 'entity' => $collection, ]); $this->assertTrue($context->isCreate()); } /** * Test an invalid table scope throws an error. * * @expectedException \RuntimeException * @expectedExceptionMessage Unable to find table class for current entity */ public function testInvalidTable() { $row = new \StdClass(); $context = new EntityContext($this->request, [ 'entity' => $row, ]); } /** * Test operations with no entity. * * @return void */ public function testOperationsNoEntity() { $context = new EntityContext($this->request, [ 'table' => 'Articles' ]); $this->assertNull($context->val('title')); $this->assertFalse($context->isRequired('title')); $this->assertFalse($context->hasError('title')); $this->assertEquals('string', $context->type('title')); $this->assertEquals([], $context->error('title')); $this->assertEquals( ['length' => null, 'precision' => null], $context->attributes('title') ); } /** * Test operations that lack a table argument. * * @return void */ public function testOperationsNoTableArg() { $row = new Article([ 'title' => 'Test entity', 'body' => 'Something new' ]); $row->errors('title', ['Title is required.']); $context = new EntityContext($this->request, [ 'entity' => $row, ]); $result = $context->val('title'); $this->assertEquals($row->title, $result); $result = $context->error('title'); $this->assertEquals($row->errors('title'), $result); $this->assertTrue($context->hasError('title')); } /** * Test collection operations that lack a table argument. * * @dataProvider collectionProvider * @return void */ public function testCollectionOperationsNoTableArg($collection) { $context = new EntityContext($this->request, [ 'entity' => $collection, ]); $result = $context->val('0.title'); $this->assertEquals('First post', $result); $result = $context->error('1.body'); $this->assertEquals(['Not long enough'], $result); } /** * Data provider for testing collections. * * @return array */ public static function collectionProvider() { $one = new Entity([ 'title' => 'First post', 'body' => 'Stuff', 'user' => new Entity(['username' => 'mark']) ]); $one->errors('title', 'Required field'); $two = new Entity([ 'title' => 'Second post', 'body' => 'Some text', 'user' => new Entity(['username' => 'jose']) ]); $two->errors('body', 'Not long enough'); return [ 'array' => [[$one, $two]], 'basic iterator' => [new ArrayObject([$one, $two])], 'array iterator' => [new ArrayIterator([$one, $two])], 'collection' => [new Collection([$one, $two])], ]; } /** * Test operations on a collection of entities. * * @dataProvider collectionProvider * @return void */ public function testValOnCollections($collection) { $context = new EntityContext($this->request, [ 'entity' => $collection, 'table' => 'Articles', ]); $result = $context->val('0.title'); $this->assertEquals('First post', $result); $result = $context->val('0.user.username'); $this->assertEquals('mark', $result); $result = $context->val('1.title'); $this->assertEquals('Second post', $result); $result = $context->val('1.user.username'); $this->assertEquals('jose', $result); $this->assertNull($context->val('nope')); $this->assertNull($context->val('99.title')); } /** * Test error operations on a collection of entities. * * @dataProvider collectionProvider * @return void */ public function testErrorsOnCollections($collection) { $context = new EntityContext($this->request, [ 'entity' => $collection, 'table' => 'Articles', ]); $this->assertTrue($context->hasError('0.title')); $this->assertEquals(['Required field'], $context->error('0.title')); $this->assertFalse($context->hasError('0.body')); $this->assertFalse($context->hasError('1.title')); $this->assertEquals(['Not long enough'], $context->error('1.body')); $this->assertTrue($context->hasError('1.body')); $this->assertFalse($context->hasError('nope')); $this->assertFalse($context->hasError('99.title')); } /** * Test schema operations on a collection of entities. * * @dataProvider collectionProvider * @return void */ public function testSchemaOnCollections($collection) { $this->_setupTables(); $context = new EntityContext($this->request, [ 'entity' => $collection, 'table' => 'Articles', ]); $this->assertEquals('string', $context->type('0.title')); $this->assertEquals('text', $context->type('1.body')); $this->assertEquals('string', $context->type('0.user.username')); $this->assertEquals('string', $context->type('1.user.username')); $this->assertEquals('string', $context->type('99.title')); $this->assertNull($context->type('0.nope')); $expected = ['length' => 255, 'precision' => null]; $this->assertEquals($expected, $context->attributes('0.user.username')); } /** * Test validation operations on a collection of entities. * * @dataProvider collectionProvider * @return void */ public function testValidatorsOnCollections($collection) { $this->_setupTables(); $context = new EntityContext($this->request, [ 'entity' => $collection, 'table' => 'Articles', 'validator' => [ 'Articles' => 'create', 'Users' => 'custom', ] ]); $this->assertFalse($context->isRequired('nope')); $this->assertTrue($context->isRequired('0.title')); $this->assertTrue($context->isRequired('0.user.username')); $this->assertFalse($context->isRequired('1.body')); $this->assertTrue($context->isRequired('99.title')); $this->assertFalse($context->isRequired('99.nope')); } /** * Test reading data. * * @return void */ public function testValBasic() { $row = new Entity([ 'title' => 'Test entity', 'body' => 'Something new' ]); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', ]); $result = $context->val('title'); $this->assertEquals($row->title, $result); $result = $context->val('body'); $this->assertEquals($row->body, $result); $result = $context->val('nope'); $this->assertNull($result); } /** * Test reading values from associated entities. * * @return void */ public function testValAssociated() { $row = new Entity([ 'title' => 'Test entity', 'user' => new Entity([ 'username' => 'mark', 'fname' => 'Mark' ]), 'comments' => [ new Entity(['comment' => 'Test comment']), new Entity(['comment' => 'Second comment']), ] ]); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', ]); $result = $context->val('user.fname'); $this->assertEquals($row->user->fname, $result); $result = $context->val('comments.0.comment'); $this->assertEquals($row->comments[0]->comment, $result); $result = $context->val('comments.1.comment'); $this->assertEquals($row->comments[1]->comment, $result); $result = $context->val('comments.0.nope'); $this->assertNull($result); $result = $context->val('comments.0.nope.no_way'); $this->assertNull($result); } /** * Test reading values from associated entities. * * @return void */ public function testValAssociatedHasMany() { $row = new Entity([ 'title' => 'First post', 'user' => new Entity([ 'username' => 'mark', 'fname' => 'Mark', 'articles' => [ new Entity(['title' => 'First post']), new Entity(['title' => 'Second post']), ] ]), ]); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', ]); $result = $context->val('user.articles.0.title'); $this->assertEquals('First post', $result); $result = $context->val('user.articles.1.title'); $this->assertEquals('Second post', $result); } /** * Test validator as a string. * * @return void */ public function testIsRequiredStringValidator() { $this->_setupTables(); $context = new EntityContext($this->request, [ 'entity' => new Entity(), 'table' => 'Articles', 'validator' => 'create', ]); $this->assertTrue($context->isRequired('title')); $this->assertFalse($context->isRequired('body')); $this->assertFalse($context->isRequired('Herp.derp.derp')); $this->assertFalse($context->isRequired('nope')); $this->assertFalse($context->isRequired('')); } /** * Test isRequired on associated entities. * * @return void */ public function testIsRequiredAssociatedHasMany() { $this->_setupTables(); $comments = TableRegistry::get('Comments'); $validator = $comments->validator(); $validator->add('user_id', 'number', [ 'rule' => 'numeric', ]); $row = new Entity([ 'title' => 'My title', 'comments' => [ new Entity(['comment' => 'First comment']), new Entity(['comment' => 'Second comment']), ] ]); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', 'validator' => 'default', ]); $this->assertTrue($context->isRequired('comments.0.user_id')); $this->assertFalse($context->isRequired('comments.0.other')); $this->assertFalse($context->isRequired('user.0.other')); $this->assertFalse($context->isRequired('')); } /** * Test isRequired on associated entities with custom validators. * * @return void */ public function testIsRequiredAssociatedValidator() { $this->_setupTables(); $row = new Entity([ 'title' => 'My title', 'comments' => [ new Entity(['comment' => 'First comment']), new Entity(['comment' => 'Second comment']), ] ]); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', 'validator' => [ 'Articles' => 'create', 'Comments' => 'custom' ] ]); $this->assertTrue($context->isRequired('title')); $this->assertFalse($context->isRequired('body')); $this->assertTrue($context->isRequired('comments.0.comment')); $this->assertTrue($context->isRequired('comments.1.comment')); } /** * Test isRequired on associated entities. * * @return void */ public function testIsRequiredAssociatedBelongsTo() { $this->_setupTables(); $row = new Entity([ 'title' => 'My title', 'user' => new Entity(['username' => 'Mark']), ]); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', 'validator' => [ 'Articles' => 'create', 'Users' => 'custom' ] ]); $this->assertTrue($context->isRequired('user.username')); $this->assertFalse($context->isRequired('user.first_name')); } /** * Test type() basic * * @return void */ public function testType() { $this->_setupTables(); $row = new Entity([ 'title' => 'My title', 'body' => 'Some content', ]); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', ]); $this->assertEquals('string', $context->type('title')); $this->assertEquals('text', $context->type('body')); $this->assertEquals('integer', $context->type('user_id')); $this->assertNull($context->type('nope')); } /** * Test getting types for associated records. * * @return void */ public function testTypeAssociated() { $this->_setupTables(); $row = new Entity([ 'title' => 'My title', 'user' => new Entity(['username' => 'Mark']), ]); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', ]); $this->assertEquals('string', $context->type('user.username')); $this->assertEquals('text', $context->type('user.bio')); $this->assertNull($context->type('user.nope')); } /** * Test attributes for fields. * * @return void */ public function testAttributes() { $this->_setupTables(); $row = new Entity([ 'title' => 'My title', 'user' => new Entity(['username' => 'Mark']), ]); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', ]); $expected = [ 'length' => 255, 'precision' => null ]; $this->assertEquals($expected, $context->attributes('title')); $expected = [ 'length' => null, 'precision' => null ]; $this->assertEquals($expected, $context->attributes('body')); $expected = [ 'length' => 10, 'precision' => 3 ]; $this->assertEquals($expected, $context->attributes('user.rating')); } /** * Test hasError * * @return void */ public function testHasError() { $this->_setupTables(); $row = new Entity([ 'title' => 'My title', 'user' => new Entity(['username' => 'Mark']), ]); $row->errors('title', []); $row->errors('body', 'Gotta have one'); $row->errors('user_id', ['Required field']); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', ]); $this->assertFalse($context->hasError('title')); $this->assertFalse($context->hasError('nope')); $this->assertTrue($context->hasError('body')); $this->assertTrue($context->hasError('user_id')); } /** * Test hasError on associated records * * @return void */ public function testHasErrorAssociated() { $this->_setupTables(); $row = new Entity([ 'title' => 'My title', 'user' => new Entity(['username' => 'Mark']), ]); $row->errors('title', []); $row->errors('body', 'Gotta have one'); $row->user->errors('username', ['Required']); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', ]); $this->assertTrue($context->hasError('user.username')); $this->assertFalse($context->hasError('user.nope')); $this->assertFalse($context->hasError('no.nope')); } /** * Test error * * @return void */ public function testError() { $this->_setupTables(); $row = new Entity([ 'title' => 'My title', 'user' => new Entity(['username' => 'Mark']), ]); $row->errors('title', []); $row->errors('body', 'Gotta have one'); $row->errors('user_id', ['Required field']); $row->user->errors('username', ['Required']); $context = new EntityContext($this->request, [ 'entity' => $row, 'table' => 'Articles', ]); $this->assertEquals([], $context->error('title')); $expected = ['Gotta have one']; $this->assertEquals($expected, $context->error('body')); $expected = ['Required']; $this->assertEquals($expected, $context->error('user.username')); } /** * Setup tables for tests. * * @return void */ protected function _setupTables() { $articles = TableRegistry::get('Articles'); $articles->belongsTo('Users'); $articles->hasMany('Comments'); $comments = TableRegistry::get('Comments'); $users = TableRegistry::get('Users'); $users->hasMany('Articles'); $articles->schema([ 'id' => ['type' => 'integer', 'length' => 11, 'null' => false], 'title' => ['type' => 'string', 'length' => 255], 'user_id' => ['type' => 'integer', 'length' => 11, 'null' => false], 'body' => ['type' => 'text'] ]); $users->schema([ 'id' => ['type' => 'integer', 'length' => 11], 'username' => ['type' => 'string', 'length' => 255], 'bio' => ['type' => 'text'], 'rating' => ['type' => 'decimal', 'length' => 10, 'precision' => 3], ]); $validator = new Validator(); $validator->add('title', 'minlength', [ 'rule' => ['minlength', 10] ]) ->add('body', 'maxlength', [ 'rule' => ['maxlength', 1000] ])->allowEmpty('body'); $articles->validator('create', $validator); $validator = new Validator(); $validator->add('username', 'length', [ 'rule' => ['minlength', 10] ]); $users->validator('custom', $validator); $validator = new Validator(); $validator->add('comment', 'length', [ 'rule' => ['minlength', 10] ]); $comments->validator('custom', $validator); } }