Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
klimov-paul committed Dec 21, 2023
1 parent 217f2d0 commit 0187008
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 32 deletions.
20 changes: 11 additions & 9 deletions src/AttributeTypecastBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
use CActiveRecord;
use CBehavior;
use CBooleanValidator;
use CEvent;
use CModelEvent;
use CNumberValidator;
use CStringValidator;
use InvalidArgumentException;

/**
* @property \CModel|CActiveRecord $owner The owner component that this behavior is attached to.
* @property \CModel|\CActiveRecord $owner The owner component that this behavior is attached to.
* @property array $attributeTypes
*
* @author Paul Klimov <[email protected]>
* @since 1.0
Expand Down Expand Up @@ -78,10 +80,10 @@ class AttributeTypecastBehavior extends CBehavior
* the database (after find or refresh).
* This option may be disabled in order to achieve better performance.
* For example, in case of [[\yii\db\ActiveRecord]] usage, typecasting after find
* will grant no benefit in most cases an thus can be disabled.
* will grant no benefit in most cases and thus can be disabled.
* Note that changing this option value will have no effect after this behavior has been attached to the model.
*/
public $typecastAfterFind = false;
public $typecastAfterFind = true;

/**
* @var array internal static cache for auto detected [[attributeTypes]] values
Expand Down Expand Up @@ -250,9 +252,9 @@ public function events(): array

/**
* Handles owner 'afterValidate' event, ensuring attribute typecasting.
* @param \CModelEvent $event event instance.
* @param \CEvent $event event instance.
*/
public function afterValidate(CModelEvent $event): void
public function afterValidate(CEvent $event): void
{
if (!$this->owner->hasErrors()) {
$this->typecastAttributes();
Expand All @@ -270,18 +272,18 @@ public function beforeSave(CModelEvent $event): void

/**
* Handles owner 'afterSave' event, ensuring attribute typecasting.
* @param \CModelEvent $event event instance.
* @param \CEvent $event event instance.
*/
public function afterSave(CModelEvent $event): void
public function afterSave(CEvent $event): void
{
$this->typecastAttributes();
}

/**
* Handles owner 'afterFind' event, ensuring attribute typecasting.
* @param \CModelEvent $event event instance.
* @param \CEvent $event event instance.
*/
public function afterFind(CModelEvent $event): void
public function afterFind(CEvent $event): void
{
$this->typecastAttributes();
}
Expand Down
147 changes: 145 additions & 2 deletions tests/AttributeTypecastBehaviorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,153 @@

namespace yii1tech\model\typecast\test;

use yii1tech\model\typecast\AttributeTypecastBehavior;
use yii1tech\model\typecast\test\data\Item;
use yii1tech\model\typecast\test\data\ItemWithTypecast;

class AttributeTypecastBehaviorTest extends TestCase
{
public function testTypecastAttributes(): void
public function testTypecast(): void
{
$this->assertTrue(true);
$model = new ItemWithTypecast();

$model->name = 123;
$model->category_id = '58';
$model->price = '100.8';
$model->is_active = 1;
$model->callback = 'foo';

$model->typecastAttributes();

$this->assertSame('123', $model->name);
$this->assertSame(58, $model->category_id);
$this->assertSame(100.8, $model->price);
$this->assertTrue($model->is_active);
$this->assertSame('callback: foo', $model->callback);
}

/**
* @depends testTypecast
*/
public function testSkipNull()
{
$model = new ItemWithTypecast();
$model->skipOnNull = true;

$model->name = null;
$model->category_id = null;
$model->price = null;
$model->is_active = null;
$model->callback = null;

$model->typecastAttributes();

$this->assertNull($model->name);
$this->assertNull($model->category_id);
$this->assertNull($model->price);
$this->assertNull($model->is_active);
$this->assertNull($model->callback);

$model->skipOnNull = false;
$model->typecastAttributes();

$this->assertSame('', $model->name);
$this->assertSame(0, $model->category_id);
$this->assertSame(0.0, $model->price);
$this->assertFalse($model->is_active);
$this->assertSame('callback: ', $model->callback);
}

/**
* @depends testTypecast
*/
public function testAfterFindEvent(): void
{
$model = new ItemWithTypecast();

$model->validate();
$model->save(false);

$model->updateAll(['callback' => 'find']);
$model->refresh();
$this->assertSame('callback: find', $model->callback);
}

/**
* @depends testTypecast
*/
public function testAfterValidateEvent(): void
{
$model = new ItemWithTypecast();

$model->callback = 'validate';
$model->validate();
$this->assertSame('callback: validate', $model->callback);
}

/**
* @depends testTypecast
*/
public function testSaveEvents()
{
$baseBehavior = new AttributeTypecastBehavior();
$baseBehavior->attributeTypes = [
'callback' => function ($value) {
return 'callback: ' . $value;
},
];

$model = new Item();
$behavior = clone $baseBehavior;
$behavior->typecastBeforeSave = true;
$behavior->typecastAfterSave = false;
$model->attachBehavior('typecast', $behavior);
$model->callback = 'before save';
$model->save(false);
$this->assertSame('callback: before save', $model->callback);

$model = new Item();
$behavior = clone $baseBehavior;
$behavior->typecastBeforeSave = false;
$behavior->typecastAfterSave = true;
$model->attachBehavior('typecast', $behavior);
$model->callback = 'after save';
$model->save(false);
$this->assertSame('callback: after save', $model->callback);

$model = new Item();
$behavior = clone $baseBehavior;
$behavior->typecastBeforeSave = false;
$behavior->typecastAfterSave = false;
$model->attachBehavior('typecast', $behavior);
$model->callback = 'no typecast';
$model->save(false);
$this->assertSame('no typecast', $model->callback);
}

/**
* @depends testSkipNull
*/
public function testSkipNotSelectedAttribute()
{
$model = new ItemWithTypecast();
$model->name = 'skip-not-selected';
$model->category_id = '58';
$model->price = '100.8';
$model->is_active = 1;
$model->callback = 'foo';
$model->save(false);

/* @var $model ItemWithTypecast */
$model = ItemWithTypecast::model()->find([
'select' => ['id', 'name'],
'condition' => "id = {$model->id}",
]);

$model->typecastAttributes();
$model->save(false);

$model->refresh();
$this->assertSame(58, $model->category_id);
}
}
11 changes: 8 additions & 3 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use CConsoleApplication;
use CMap;
use Yii;
use yii1tech\model\typecast\AttributeTypecastBehavior;

class TestCase extends \PHPUnit\Framework\TestCase
{
Expand All @@ -25,6 +26,8 @@ protected function setUp(): void
*/
protected function tearDown(): void
{
AttributeTypecastBehavior::clearAutoDetectedAttributeTypes();

$this->destroyApplication();

parent::tearDown();
Expand Down Expand Up @@ -76,9 +79,11 @@ protected function setupTestDbData()
'id' => 'pk',
'category_id' => 'integer',
'name' => 'string',
'is_deleted' => 'boolean DEFAULT 0',
'price' => 'float',
'is_active' => 'boolean DEFAULT 0',
'created_at' => 'integer',
'created_date' => 'datetime',
'callback' => 'string',
]);

// Data :
Expand All @@ -88,14 +93,14 @@ protected function setupTestDbData()
[
'category_id' => 1,
'name' => 'item1',
'is_deleted' => 0,
'is_active' => 0,
'created_at' => time(),
'created_date' => date('Y-m-d H:i:s'),
],
[
'category_id' => 2,
'name' => 'item2',
'is_deleted' => 1,
'is_active' => 1,
'created_at' => time(),
'created_date' => date('Y-m-d H:i:s'),
],
Expand Down
24 changes: 6 additions & 18 deletions tests/data/Item.php
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<?php

namespace yii1tech\ar\softdelete\test\data;
namespace yii1tech\model\typecast\test\data;

use CActiveRecord;
use CDbException;
use yii1tech\model\typecast\AttributeTypecastBehavior;

/**
* @property int $id
* @property int $category_id
* @property string $name
* @property bool $is_deleted
* @property float $price
* @property bool $is_active
* @property int $created_at
* @property int $created_date
* @property string $created_date
* @property string $callback
*/
class Item extends CActiveRecord
{
Expand All @@ -27,20 +27,8 @@ public static function model($className = __CLASS__)
/**
* {@inheritdoc}
*/
public function tableName()
public function tableName(): string
{
return 'item';
}

/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'softDeleteBehavior' => [
'class' => AttributeTypecastBehavior::class,
],
];
}
}
44 changes: 44 additions & 0 deletions tests/data/ItemWithTypecast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace yii1tech\model\typecast\test\data;

use yii1tech\model\typecast\AttributeTypecastBehavior;

/**
* @mixin \yii1tech\model\typecast\AttributeTypecastBehavior
*
* @property-read \yii1tech\model\typecast\AttributeTypecastBehavior $typecastBehavior
*/
class ItemWithTypecast extends Item
{
/**
* {@inheritdoc}
*/
public static function model($className = __CLASS__)
{
return parent::model($className);
}

/**
* {@inheritdoc}
*/
public function behaviors(): array
{
return [
'typecastBehavior' => [
'class' => AttributeTypecastBehavior::class,
'typecastBeforeSave' => true,
'typecastAfterFind' => true,
'attributeTypes' => [
'name' => AttributeTypecastBehavior::TYPE_STRING,
'category_id' => AttributeTypecastBehavior::TYPE_INTEGER,
'price' => AttributeTypecastBehavior::TYPE_FLOAT,
'is_active' => AttributeTypecastBehavior::TYPE_BOOLEAN,
'callback' => function ($value) {
return 'callback: ' . $value;
},
],
],
];
}
}

0 comments on commit 0187008

Please sign in to comment.