Commit f7a6cb9f by Qiang Xue

Refactored AR tests.

parent 338b6aa7
......@@ -20,26 +20,6 @@ class ActiveRecordTest extends ElasticSearchTestCase
{
use ActiveRecordTestTrait;
public function callCustomerFind($q = null)
{
return Customer::find($q);
}
public function callOrderFind($q = null)
{
return Order::find($q);
}
public function callOrderItemFind($q = null)
{
return OrderItem::find($q);
}
public function callItemFind($q = null)
{
return Item::find($q);
}
public function getCustomerClass()
{
return Customer::className();
......@@ -164,7 +144,7 @@ class ActiveRecordTest extends ElasticSearchTestCase
public function testFindAsArray()
{
// asArray
$customer = $this->callCustomerFind()->where(['id' => 2])->asArray()->one();
$customer = Customer::find()->where(['id' => 2])->asArray()->one();
$this->assertEquals([
'id' => 2,
'email' => 'user2@example.com',
......@@ -177,7 +157,7 @@ class ActiveRecordTest extends ElasticSearchTestCase
public function testSearch()
{
$customers = $this->callCustomerFind()->search()['hits'];
$customers = Customer::find()->search()['hits'];
$this->assertEquals(3, $customers['total']);
$this->assertEquals(3, count($customers['hits']));
$this->assertTrue($customers['hits'][0] instanceof Customer);
......@@ -185,12 +165,12 @@ class ActiveRecordTest extends ElasticSearchTestCase
$this->assertTrue($customers['hits'][2] instanceof Customer);
// limit vs. totalcount
$customers = $this->callCustomerFind()->limit(2)->search()['hits'];
$customers = Customer::find()->limit(2)->search()['hits'];
$this->assertEquals(3, $customers['total']);
$this->assertEquals(2, count($customers['hits']));
// asArray
$result = $this->callCustomerFind()->asArray()->search()['hits'];
$result = Customer::find()->asArray()->search()['hits'];
$this->assertEquals(3, $result['total']);
$customers = $result['hits'];
$this->assertEquals(3, count($customers));
......@@ -213,7 +193,7 @@ class ActiveRecordTest extends ElasticSearchTestCase
// TODO test asArray() + fields() + indexBy()
// find by attributes
$result = $this->callCustomerFind()->where(['name' => 'user2'])->search()['hits'];
$result = Customer::find()->where(['name' => 'user2'])->search()['hits'];
$customer = reset($result['hits']);
$this->assertTrue($customer instanceof Customer);
$this->assertEquals(2, $customer->id);
......@@ -223,7 +203,7 @@ class ActiveRecordTest extends ElasticSearchTestCase
public function testSearchFacets()
{
$result = $this->callCustomerFind()->addStatisticalFacet('status_stats', ['field' => 'status'])->search();
$result = Customer::find()->addStatisticalFacet('status_stats', ['field' => 'status'])->search();
$this->assertArrayHasKey('facets', $result);
$this->assertEquals(3, $result['facets']['status_stats']['count']);
$this->assertEquals(4, $result['facets']['status_stats']['total']); // sum of values
......@@ -400,10 +380,10 @@ class ActiveRecordTest extends ElasticSearchTestCase
$customer->save(false);
$this->afterSave();
$customers = $this->callCustomerFind()->where(['status' => true])->all();
$customers = Customer::find()->where(['status' => true])->all();
$this->assertEquals(1, count($customers));
$customers = $this->callCustomerFind()->where(['status' => false])->all();
$customers = Customer::find()->where(['status' => false])->all();
$this->assertEquals(2, count($customers));
}
......@@ -411,7 +391,7 @@ class ActiveRecordTest extends ElasticSearchTestCase
{
/** @var TestCase|ActiveRecordTestTrait $this */
// indexBy + asArray
$customers = $this->callCustomerFind()->asArray()->fields(['id', 'name'])->all();
$customers = Customer::find()->asArray()->fields(['id', 'name'])->all();
$this->assertEquals(3, count($customers));
$this->assertArrayHasKey('id', $customers[0]);
$this->assertArrayHasKey('name', $customers[0]);
......@@ -435,7 +415,7 @@ class ActiveRecordTest extends ElasticSearchTestCase
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// indexBy + asArray
$customers = $this->callCustomerFind()->indexBy('name')->fields('id', 'name')->all();
$customers = Customer::find()->indexBy('name')->fields('id', 'name')->all();
$this->assertEquals(3, count($customers));
$this->assertTrue($customers['user1'] instanceof $customerClass);
$this->assertTrue($customers['user2'] instanceof $customerClass);
......@@ -457,7 +437,7 @@ class ActiveRecordTest extends ElasticSearchTestCase
$this->assertNull($customers['user3']->status);
// indexBy callable + asArray
$customers = $this->callCustomerFind()->indexBy(function ($customer) {
$customers = Customer::find()->indexBy(function ($customer) {
return $customer->id . '-' . $customer->name;
})->fields('id', 'name')->all();
$this->assertEquals(3, count($customers));
......@@ -485,7 +465,7 @@ class ActiveRecordTest extends ElasticSearchTestCase
{
/** @var TestCase|ActiveRecordTestTrait $this */
// indexBy + asArray
$customers = $this->callCustomerFind()->indexBy('name')->asArray()->fields('id', 'name')->all();
$customers = Customer::find()->indexBy('name')->asArray()->fields('id', 'name')->all();
$this->assertEquals(3, count($customers));
$this->assertArrayHasKey('id', $customers['user1']);
$this->assertArrayHasKey('name', $customers['user1']);
......@@ -504,7 +484,7 @@ class ActiveRecordTest extends ElasticSearchTestCase
$this->assertArrayNotHasKey('status', $customers['user3']);
// indexBy callable + asArray
$customers = $this->callCustomerFind()->indexBy(function ($customer) {
$customers = Customer::find()->indexBy(function ($customer) {
return $customer['id'] . '-' . $customer['name'];
})->asArray()->fields('id', 'name')->all();
$this->assertEquals(3, count($customers));
......
......@@ -16,26 +16,6 @@ class ActiveRecordTest extends RedisTestCase
{
use ActiveRecordTestTrait;
public function callCustomerFind($q = null)
{
return Customer::find($q);
}
public function callOrderFind($q = null)
{
return Order::find($q);
}
public function callOrderItemFind($q = null)
{
return OrderItem::find($q);
}
public function callItemFind($q = null)
{
return Item::find($q);
}
public function getCustomerClass()
{
return Customer::className();
......@@ -142,7 +122,7 @@ class ActiveRecordTest extends RedisTestCase
$this->markTestSkipped('Redis does not support orderBy.');
}
public function testSatisticalFind()
public function testStatisticalFind()
{
// find count, sum, average, min, max, scalar
$this->assertEquals(3, Customer::find()->count());
......@@ -155,19 +135,19 @@ class ActiveRecordTest extends RedisTestCase
$this->assertEquals(7, OrderItem::find()->sum('quantity'));
}
public function testfindIndexBy()
public function testFindIndexBy()
{
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// indexBy
$customers = $this->callCustomerFind()->indexBy('name')/*->orderBy('id')*/->all();
$customers = Customer::find()->indexBy('name')/*->orderBy('id')*/->all();
$this->assertEquals(3, count($customers));
$this->assertTrue($customers['user1'] instanceof $customerClass);
$this->assertTrue($customers['user2'] instanceof $customerClass);
$this->assertTrue($customers['user3'] instanceof $customerClass);
// indexBy callable
$customers = $this->callCustomerFind()->indexBy(function ($customer) {
$customers = Customer::find()->indexBy(function ($customer) {
return $customer->id . '-' . $customer->name;
})/*->orderBy('id')*/->all(); // TODO this test is duplicated because of missing orderBy support in redis
$this->assertEquals(3, count($customers));
......@@ -181,50 +161,53 @@ class ActiveRecordTest extends RedisTestCase
// TODO this test is duplicated because of missing orderBy support in redis
/** @var TestCase|ActiveRecordTestTrait $this */
// all()
$customers = $this->callCustomerFind()->all();
$customers = Customer::find()->all();
$this->assertEquals(3, count($customers));
$customers = $this->callCustomerFind()/*->orderBy('id')*/->limit(1)->all();
$customers = Customer::find()/*->orderBy('id')*/->limit(1)->all();
$this->assertEquals(1, count($customers));
$this->assertEquals('user1', $customers[0]->name);
$customers = $this->callCustomerFind()/*->orderBy('id')*/->limit(1)->offset(1)->all();
$customers = Customer::find()/*->orderBy('id')*/->limit(1)->offset(1)->all();
$this->assertEquals(1, count($customers));
$this->assertEquals('user2', $customers[0]->name);
$customers = $this->callCustomerFind()/*->orderBy('id')*/->limit(1)->offset(2)->all();
$customers = Customer::find()/*->orderBy('id')*/->limit(1)->offset(2)->all();
$this->assertEquals(1, count($customers));
$this->assertEquals('user3', $customers[0]->name);
$customers = $this->callCustomerFind()/*->orderBy('id')*/->limit(2)->offset(1)->all();
$customers = Customer::find()/*->orderBy('id')*/->limit(2)->offset(1)->all();
$this->assertEquals(2, count($customers));
$this->assertEquals('user2', $customers[0]->name);
$this->assertEquals('user3', $customers[1]->name);
$customers = $this->callCustomerFind()->limit(2)->offset(3)->all();
$customers = Customer::find()->limit(2)->offset(3)->all();
$this->assertEquals(0, count($customers));
// one()
$customer = $this->callCustomerFind()/*->orderBy('id')*/->one();
$customer = Customer::find()/*->orderBy('id')*/->one();
$this->assertEquals('user1', $customer->name);
$customer = $this->callCustomerFind()/*->orderBy('id')*/->offset(0)->one();
$customer = Customer::find()/*->orderBy('id')*/->offset(0)->one();
$this->assertEquals('user1', $customer->name);
$customer = $this->callCustomerFind()/*->orderBy('id')*/->offset(1)->one();
$customer = Customer::find()/*->orderBy('id')*/->offset(1)->one();
$this->assertEquals('user2', $customer->name);
$customer = $this->callCustomerFind()/*->orderBy('id')*/->offset(2)->one();
$customer = Customer::find()/*->orderBy('id')*/->offset(2)->one();
$this->assertEquals('user3', $customer->name);
$customer = $this->callCustomerFind()->offset(3)->one();
$customer = Customer::find()->offset(3)->one();
$this->assertNull($customer);
}
public function testFindEagerViaRelation()
{
/** @var \yii\db\ActiveRecordInterface $orderClass */
$orderClass = $this->getOrderClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$orders = $this->callOrderFind()->with('items')/*->orderBy('id')*/->all(); // TODO this test is duplicated because of missing orderBy support in redis
$orders = $orderClass::find()->with('items')/*->orderBy('id')*/->all(); // TODO this test is duplicated because of missing orderBy support in redis
$this->assertEquals(3, count($orders));
$order = $orders[0];
$this->assertEquals(1, $order->id);
......
......@@ -15,41 +15,13 @@ use yiiunit\data\ar\Customer;
use yiiunit\data\ar\Order;
/**
* This trait provides unit tests shared by the differen AR implementations
* This trait provides unit tests shared by the different AR implementations
*
* @var TestCase $this
*/
trait ActiveRecordTestTrait
{
/**
* This method should call Customer::find($q)
* @param $q
* @return mixed
*/
abstract public function callCustomerFind($q = null);
/**
* This method should call Order::find($q)
* @param $q
* @return mixed
*/
abstract public function callOrderFind($q = null);
/**
* This method should call OrderItem::find($q)
* @param $q
* @return mixed
*/
abstract public function callOrderItemFind($q = null);
/**
* This method should call Item::find($q)
* @param $q
* @return mixed
*/
abstract public function callItemFind($q = null);
/**
* This method should return the classname of Customer class
* @return string
*/
......@@ -82,23 +54,24 @@ trait ActiveRecordTestTrait
public function testFind()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// find one
$result = $this->callCustomerFind();
$result = $customerClass::find();
$this->assertTrue($result instanceof ActiveQueryInterface);
$customer = $result->one();
$this->assertTrue($customer instanceof $customerClass);
// find all
$customers = $this->callCustomerFind()->all();
$customers = $customerClass::find()->all();
$this->assertEquals(3, count($customers));
$this->assertTrue($customers[0] instanceof $customerClass);
$this->assertTrue($customers[1] instanceof $customerClass);
$this->assertTrue($customers[2] instanceof $customerClass);
// find all asArray
$customers = $this->callCustomerFind()->asArray()->all();
$customers = $customerClass::find()->asArray()->all();
$this->assertEquals(3, count($customers));
$this->assertArrayHasKey('id', $customers[0]);
$this->assertArrayHasKey('name', $customers[0]);
......@@ -117,41 +90,44 @@ trait ActiveRecordTestTrait
$this->assertArrayHasKey('status', $customers[2]);
// find by a single primary key
$customer = $this->callCustomerFind(2);
$customer = $customerClass::find(2);
$this->assertTrue($customer instanceof $customerClass);
$this->assertEquals('user2', $customer->name);
$customer = $this->callCustomerFind(5);
$customer = $customerClass::find(5);
$this->assertNull($customer);
$customer = $this->callCustomerFind(['id' => [5, 6, 1]]);
$customer = $customerClass::find(['id' => [5, 6, 1]]);
$this->assertEquals(1, count($customer));
$customer = $this->callCustomerFind()->where(['id' => [5, 6, 1]])->one();
$customer = $customerClass::find()->where(['id' => [5, 6, 1]])->one();
$this->assertNotNull($customer);
// find by column values
$customer = $this->callCustomerFind(['id' => 2, 'name' => 'user2']);
$customer = $customerClass::find(['id' => 2, 'name' => 'user2']);
$this->assertTrue($customer instanceof $customerClass);
$this->assertEquals('user2', $customer->name);
$customer = $this->callCustomerFind(['id' => 2, 'name' => 'user1']);
$customer = $customerClass::find(['id' => 2, 'name' => 'user1']);
$this->assertNull($customer);
$customer = $this->callCustomerFind(['id' => 5]);
$customer = $customerClass::find(['id' => 5]);
$this->assertNull($customer);
$customer = $this->callCustomerFind(['name' => 'user5']);
$customer = $customerClass::find(['name' => 'user5']);
$this->assertNull($customer);
// find by attributes
$customer = $this->callCustomerFind()->where(['name' => 'user2'])->one();
$customer = $customerClass::find()->where(['name' => 'user2'])->one();
$this->assertTrue($customer instanceof $customerClass);
$this->assertEquals(2, $customer->id);
// scope
$this->assertEquals(2, count($this->callCustomerFind()->active()->all()));
$this->assertEquals(2, $this->callCustomerFind()->active()->count());
$this->assertEquals(2, count($customerClass::find()->active()->all()));
$this->assertEquals(2, $customerClass::find()->active()->count());
}
public function testFindAsArray()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
// asArray
$customer = $this->callCustomerFind()->where(['id' => 2])->asArray()->one();
$customer = $customerClass::find()->where(['id' => 2])->asArray()->one();
$this->assertEquals([
'id' => 2,
'email' => 'user2@example.com',
......@@ -164,38 +140,45 @@ trait ActiveRecordTestTrait
public function testFindScalar()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// query scalar
$customerName = $this->callCustomerFind()->where(['id' => 2])->scalar('name');
$customerName = $customerClass::find()->where(['id' => 2])->scalar('name');
$this->assertEquals('user2', $customerName);
$customerName = $this->callCustomerFind()->where(['status' => 2])->scalar('name');
$customerName = $customerClass::find()->where(['status' => 2])->scalar('name');
$this->assertEquals('user3', $customerName);
$customerName = $this->callCustomerFind()->where(['status' => 2])->scalar('noname');
$customerName = $customerClass::find()->where(['status' => 2])->scalar('noname');
$this->assertNull($customerName);
$customerId = $this->callCustomerFind()->where(['status' => 2])->scalar('id');
$customerId = $customerClass::find()->where(['status' => 2])->scalar('id');
$this->assertEquals(3, $customerId);
}
public function testFindColumn()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$this->assertEquals(['user1', 'user2', 'user3'], $this->callCustomerFind()->orderBy(['name' => SORT_ASC])->column('name'));
$this->assertEquals(['user3', 'user2', 'user1'], $this->callCustomerFind()->orderBy(['name' => SORT_DESC])->column('name'));
$this->assertEquals(['user1', 'user2', 'user3'], $customerClass::find()->orderBy(['name' => SORT_ASC])->column('name'));
$this->assertEquals(['user3', 'user2', 'user1'], $customerClass::find()->orderBy(['name' => SORT_DESC])->column('name'));
}
public function testFindIndexBy()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// indexBy
$customers = $this->callCustomerFind()->indexBy('name')->orderBy('id')->all();
$customers = $customerClass::find()->indexBy('name')->orderBy('id')->all();
$this->assertEquals(3, count($customers));
$this->assertTrue($customers['user1'] instanceof $customerClass);
$this->assertTrue($customers['user2'] instanceof $customerClass);
$this->assertTrue($customers['user3'] instanceof $customerClass);
// indexBy callable
$customers = $this->callCustomerFind()->indexBy(function ($customer) {
$customers = $customerClass::find()->indexBy(function ($customer) {
return $customer->id . '-' . $customer->name;
})->orderBy('id')->all();
$this->assertEquals(3, count($customers));
......@@ -206,9 +189,12 @@ trait ActiveRecordTestTrait
public function testFindIndexByAsArray()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// indexBy + asArray
$customers = $this->callCustomerFind()->asArray()->indexBy('name')->all();
$customers = $customerClass::find()->asArray()->indexBy('name')->all();
$this->assertEquals(3, count($customers));
$this->assertArrayHasKey('id', $customers['user1']);
$this->assertArrayHasKey('name', $customers['user1']);
......@@ -227,7 +213,7 @@ trait ActiveRecordTestTrait
$this->assertArrayHasKey('status', $customers['user3']);
// indexBy callable + asArray
$customers = $this->callCustomerFind()->indexBy(function ($customer) {
$customers = $customerClass::find()->indexBy(function ($customer) {
return $customer['id'] . '-' . $customer['name'];
})->asArray()->all();
$this->assertEquals(3, count($customers));
......@@ -250,12 +236,13 @@ trait ActiveRecordTestTrait
public function testRefresh()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$customer = new $customerClass();
$this->assertFalse($customer->refresh());
$customer = $this->callCustomerFind(1);
$customer = $customerClass::find(1);
$customer->name = 'to be refreshed';
$this->assertTrue($customer->refresh());
$this->assertEquals('user1', $customer->name);
......@@ -263,7 +250,9 @@ trait ActiveRecordTestTrait
public function testEquals()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var \yii\db\ActiveRecordInterface $itemClass */
$itemClass = $this->getItemClass();
/** @var TestCase|ActiveRecordTestTrait $this */
......@@ -275,123 +264,141 @@ trait ActiveRecordTestTrait
$customerB = new $itemClass();
$this->assertFalse($customerA->equals($customerB));
$customerA = $this->callCustomerFind(1);
$customerB = $this->callCustomerFind(2);
$customerA = $customerClass::find(1);
$customerB = $customerClass::find(2);
$this->assertFalse($customerA->equals($customerB));
$customerB = $this->callCustomerFind(1);
$customerB = $customerClass::find(1);
$this->assertTrue($customerA->equals($customerB));
$customerA = $this->callCustomerFind(1);
$customerB = $this->callItemFind(1);
$customerA = $customerClass::find(1);
$customerB = $itemClass::find(1);
$this->assertFalse($customerA->equals($customerB));
}
public function testFindCount()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$this->assertEquals(3, $this->callCustomerFind()->count());
$this->assertEquals(3, $customerClass::find()->count());
$this->assertEquals(1, $this->callCustomerFind()->where(['id' => 1])->count());
$this->assertEquals(2, $this->callCustomerFind()->where(['id' => [1, 2]])->count());
$this->assertEquals(2, $this->callCustomerFind()->where(['id' => [1, 2]])->offset(1)->count());
$this->assertEquals(2, $this->callCustomerFind()->where(['id' => [1, 2]])->offset(2)->count());
$this->assertEquals(1, $customerClass::find()->where(['id' => 1])->count());
$this->assertEquals(2, $customerClass::find()->where(['id' => [1, 2]])->count());
$this->assertEquals(2, $customerClass::find()->where(['id' => [1, 2]])->offset(1)->count());
$this->assertEquals(2, $customerClass::find()->where(['id' => [1, 2]])->offset(2)->count());
// limit should have no effect on count()
$this->assertEquals(3, $this->callCustomerFind()->limit(1)->count());
$this->assertEquals(3, $this->callCustomerFind()->limit(2)->count());
$this->assertEquals(3, $this->callCustomerFind()->limit(10)->count());
$this->assertEquals(3, $this->callCustomerFind()->offset(2)->limit(2)->count());
$this->assertEquals(3, $customerClass::find()->limit(1)->count());
$this->assertEquals(3, $customerClass::find()->limit(2)->count());
$this->assertEquals(3, $customerClass::find()->limit(10)->count());
$this->assertEquals(3, $customerClass::find()->offset(2)->limit(2)->count());
}
public function testFindLimit()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// all()
$customers = $this->callCustomerFind()->all();
$customers = $customerClass::find()->all();
$this->assertEquals(3, count($customers));
$customers = $this->callCustomerFind()->orderBy('id')->limit(1)->all();
$customers = $customerClass::find()->orderBy('id')->limit(1)->all();
$this->assertEquals(1, count($customers));
$this->assertEquals('user1', $customers[0]->name);
$customers = $this->callCustomerFind()->orderBy('id')->limit(1)->offset(1)->all();
$customers = $customerClass::find()->orderBy('id')->limit(1)->offset(1)->all();
$this->assertEquals(1, count($customers));
$this->assertEquals('user2', $customers[0]->name);
$customers = $this->callCustomerFind()->orderBy('id')->limit(1)->offset(2)->all();
$customers = $customerClass::find()->orderBy('id')->limit(1)->offset(2)->all();
$this->assertEquals(1, count($customers));
$this->assertEquals('user3', $customers[0]->name);
$customers = $this->callCustomerFind()->orderBy('id')->limit(2)->offset(1)->all();
$customers = $customerClass::find()->orderBy('id')->limit(2)->offset(1)->all();
$this->assertEquals(2, count($customers));
$this->assertEquals('user2', $customers[0]->name);
$this->assertEquals('user3', $customers[1]->name);
$customers = $this->callCustomerFind()->limit(2)->offset(3)->all();
$customers = $customerClass::find()->limit(2)->offset(3)->all();
$this->assertEquals(0, count($customers));
// one()
$customer = $this->callCustomerFind()->orderBy('id')->one();
$customer = $customerClass::find()->orderBy('id')->one();
$this->assertEquals('user1', $customer->name);
$customer = $this->callCustomerFind()->orderBy('id')->offset(0)->one();
$customer = $customerClass::find()->orderBy('id')->offset(0)->one();
$this->assertEquals('user1', $customer->name);
$customer = $this->callCustomerFind()->orderBy('id')->offset(1)->one();
$customer = $customerClass::find()->orderBy('id')->offset(1)->one();
$this->assertEquals('user2', $customer->name);
$customer = $this->callCustomerFind()->orderBy('id')->offset(2)->one();
$customer = $customerClass::find()->orderBy('id')->offset(2)->one();
$this->assertEquals('user3', $customer->name);
$customer = $this->callCustomerFind()->offset(3)->one();
$customer = $customerClass::find()->offset(3)->one();
$this->assertNull($customer);
}
public function testFindComplexCondition()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$this->assertEquals(2, $this->callCustomerFind()->where(['OR', ['name' => 'user1'], ['name' => 'user2']])->count());
$this->assertEquals(2, count($this->callCustomerFind()->where(['OR', ['name' => 'user1'], ['name' => 'user2']])->all()));
$this->assertEquals(2, $customerClass::find()->where(['OR', ['name' => 'user1'], ['name' => 'user2']])->count());
$this->assertEquals(2, count($customerClass::find()->where(['OR', ['name' => 'user1'], ['name' => 'user2']])->all()));
$this->assertEquals(2, $this->callCustomerFind()->where(['name' => ['user1', 'user2']])->count());
$this->assertEquals(2, count($this->callCustomerFind()->where(['name' => ['user1', 'user2']])->all()));
$this->assertEquals(2, $customerClass::find()->where(['name' => ['user1', 'user2']])->count());
$this->assertEquals(2, count($customerClass::find()->where(['name' => ['user1', 'user2']])->all()));
$this->assertEquals(1, $this->callCustomerFind()->where(['AND', ['name' => ['user2', 'user3']], ['BETWEEN', 'status', 2, 4]])->count());
$this->assertEquals(1, count($this->callCustomerFind()->where(['AND', ['name' => ['user2', 'user3']], ['BETWEEN', 'status', 2, 4]])->all()));
$this->assertEquals(1, $customerClass::find()->where(['AND', ['name' => ['user2', 'user3']], ['BETWEEN', 'status', 2, 4]])->count());
$this->assertEquals(1, count($customerClass::find()->where(['AND', ['name' => ['user2', 'user3']], ['BETWEEN', 'status', 2, 4]])->all()));
}
public function testFindNullValues()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$customer = $this->callCustomerFind(2);
$customer = $customerClass::find(2);
$customer->name = null;
$customer->save(false);
$this->afterSave();
$result = $this->callCustomerFind()->where(['name' => null])->all();
$result = $customerClass::find()->where(['name' => null])->all();
$this->assertEquals(1, count($result));
$this->assertEquals(2, reset($result)->primaryKey);
}
public function testExists()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$this->assertTrue($this->callCustomerFind()->where(['id' => 2])->exists());
$this->assertFalse($this->callCustomerFind()->where(['id' => 5])->exists());
$this->assertTrue($this->callCustomerFind()->where(['name' => 'user1'])->exists());
$this->assertFalse($this->callCustomerFind()->where(['name' => 'user5'])->exists());
$this->assertTrue($this->callCustomerFind()->where(['id' => [2, 3]])->exists());
$this->assertTrue($this->callCustomerFind()->where(['id' => [2, 3]])->offset(1)->exists());
$this->assertFalse($this->callCustomerFind()->where(['id' => [2, 3]])->offset(2)->exists());
$this->assertTrue($customerClass::find()->where(['id' => 2])->exists());
$this->assertFalse($customerClass::find()->where(['id' => 5])->exists());
$this->assertTrue($customerClass::find()->where(['name' => 'user1'])->exists());
$this->assertFalse($customerClass::find()->where(['name' => 'user5'])->exists());
$this->assertTrue($customerClass::find()->where(['id' => [2, 3]])->exists());
$this->assertTrue($customerClass::find()->where(['id' => [2, 3]])->offset(1)->exists());
$this->assertFalse($customerClass::find()->where(['id' => [2, 3]])->offset(2)->exists());
}
public function testFindLazy()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$customer = $this->callCustomerFind(2);
$customer = $customerClass::find(2);
$this->assertFalse($customer->isRelationPopulated('orders'));
$orders = $customer->orders;
$this->assertTrue($customer->isRelationPopulated('orders'));
......@@ -403,7 +410,7 @@ trait ActiveRecordTestTrait
$this->assertFalse($customer->isRelationPopulated('orders'));
/** @var Customer $customer */
$customer = $this->callCustomerFind(2);
$customer = $customerClass::find(2);
$this->assertFalse($customer->isRelationPopulated('orders'));
$orders = $customer->getOrders()->where(['id' => 3])->all();
$this->assertFalse($customer->isRelationPopulated('orders'));
......@@ -415,8 +422,13 @@ trait ActiveRecordTestTrait
public function testFindEager()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var \yii\db\ActiveRecordInterface $orderClass */
$orderClass = $this->getOrderClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$customers = $this->callCustomerFind()->with('orders')->indexBy('id')->all();
$customers = $customerClass::find()->with('orders')->indexBy('id')->all();
ksort($customers);
$this->assertEquals(3, count($customers));
$this->assertTrue($customers[1]->isRelationPopulated('orders'));
......@@ -429,17 +441,17 @@ trait ActiveRecordTestTrait
unset($customers[1]->orders);
$this->assertFalse($customers[1]->isRelationPopulated('orders'));
$customer = $this->callCustomerFind()->where(['id' => 1])->with('orders')->one();
$customer = $customerClass::find()->where(['id' => 1])->with('orders')->one();
$this->assertTrue($customer->isRelationPopulated('orders'));
$this->assertEquals(1, count($customer->orders));
$this->assertEquals(1, count($customer->relatedRecords));
// multiple with() calls
$orders = $this->callOrderFind()->with('customer', 'items')->all();
$orders = $orderClass::find()->with('customer', 'items')->all();
$this->assertEquals(3, count($orders));
$this->assertTrue($orders[0]->isRelationPopulated('customer'));
$this->assertTrue($orders[0]->isRelationPopulated('items'));
$orders = $this->callOrderFind()->with('customer')->with('items')->all();
$orders = $orderClass::find()->with('customer')->with('items')->all();
$this->assertEquals(3, count($orders));
$this->assertTrue($orders[0]->isRelationPopulated('customer'));
$this->assertTrue($orders[0]->isRelationPopulated('items'));
......@@ -447,9 +459,12 @@ trait ActiveRecordTestTrait
public function testFindLazyVia()
{
/** @var \yii\db\ActiveRecordInterface $orderClass */
$orderClass = $this->getOrderClass();
/** @var TestCase|ActiveRecordTestTrait $this */
/** @var Order $order */
$order = $this->callOrderFind(1);
$order = $orderClass::find(1);
$this->assertEquals(1, $order->id);
$this->assertEquals(2, count($order->items));
$this->assertEquals(1, $order->items[0]->id);
......@@ -458,17 +473,23 @@ trait ActiveRecordTestTrait
public function testFindLazyVia2()
{
/** @var \yii\db\ActiveRecordInterface $orderClass */
$orderClass = $this->getOrderClass();
/** @var TestCase|ActiveRecordTestTrait $this */
/** @var Order $order */
$order = $this->callOrderFind(1);
$order = $orderClass::find(1);
$order->id = 100;
$this->assertEquals([], $order->items);
}
public function testFindEagerViaRelation()
{
/** @var \yii\db\ActiveRecordInterface $orderClass */
$orderClass = $this->getOrderClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$orders = $this->callOrderFind()->with('items')->orderBy('id')->all();
$orders = $orderClass::find()->with('items')->orderBy('id')->all();
$this->assertEquals(3, count($orders));
$order = $orders[0];
$this->assertEquals(1, $order->id);
......@@ -480,8 +501,11 @@ trait ActiveRecordTestTrait
public function testFindNestedRelation()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$customers = $this->callCustomerFind()->with('orders', 'orders.items')->indexBy('id')->all();
$customers = $customerClass::find()->with('orders', 'orders.items')->indexBy('id')->all();
ksort($customers);
$this->assertEquals(3, count($customers));
$this->assertTrue($customers[1]->isRelationPopulated('orders'));
......@@ -504,6 +528,9 @@ trait ActiveRecordTestTrait
*/
public function testFindEagerViaRelationPreserveOrder()
{
/** @var \yii\db\ActiveRecordInterface $orderClass */
$orderClass = $this->getOrderClass();
/** @var TestCase|ActiveRecordTestTrait $this */
/*
......@@ -536,7 +563,7 @@ trait ActiveRecordTestTrait
- itemsInOrder:
Item 3: 'Ice Age', 2
*/
$orders = $this->callOrderFind()->with('itemsInOrder1')->orderBy('created_at')->all();
$orders = $orderClass::find()->with('itemsInOrder1')->orderBy('created_at')->all();
$this->assertEquals(3, count($orders));
$order = $orders[0];
......@@ -564,7 +591,10 @@ trait ActiveRecordTestTrait
// different order in via table
public function testFindEagerViaRelationPreserveOrderB()
{
$orders = $this->callOrderFind()->with('itemsInOrder2')->orderBy('created_at')->all();
/** @var \yii\db\ActiveRecordInterface $orderClass */
$orderClass = $this->getOrderClass();
$orders = $orderClass::find()->with('itemsInOrder2')->orderBy('created_at')->all();
$this->assertEquals(3, count($orders));
$order = $orders[0];
......@@ -591,10 +621,16 @@ trait ActiveRecordTestTrait
public function testLink()
{
/** @var \yii\db\ActiveRecordInterface $orderClass */
/** @var \yii\db\ActiveRecordInterface $itemClass */
/** @var \yii\db\ActiveRecordInterface $orderItemClass */
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
$orderClass = $this->getOrderClass();
$orderItemClass = $this->getOrderItemClass();
$itemClass = $this->getItemClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$customer = $this->callCustomerFind(2);
$customer = $customerClass::find(2);
$this->assertEquals(2, count($customer->orders));
// has many
......@@ -612,7 +648,7 @@ trait ActiveRecordTestTrait
$order = new $orderClass;
$order->total = 100;
$this->assertTrue($order->isNewRecord);
$customer = $this->callCustomerFind(1);
$customer = $customerClass::find(1);
$this->assertNull($order->customer);
$order->link('customer', $customer);
$this->assertFalse($order->isNewRecord);
......@@ -620,17 +656,17 @@ trait ActiveRecordTestTrait
$this->assertEquals(1, $order->customer->primaryKey);
// via model
$order = $this->callOrderFind(1);
$order = $orderClass::find(1);
$this->assertEquals(2, count($order->items));
$this->assertEquals(2, count($order->orderItems));
$orderItem = $this->callOrderItemFind(['order_id' => 1, 'item_id' => 3]);
$orderItem = $orderItemClass::find(['order_id' => 1, 'item_id' => 3]);
$this->assertNull($orderItem);
$item = $this->callItemFind(3);
$item = $itemClass::find(3);
$order->link('items', $item, ['quantity' => 10, 'subtotal' => 100]);
$this->afterSave();
$this->assertEquals(3, count($order->items));
$this->assertEquals(3, count($order->orderItems));
$orderItem = $this->callOrderItemFind(['order_id' => 1, 'item_id' => 3]);
$orderItem = $orderItemClass::find(['order_id' => 1, 'item_id' => 3]);
$this->assertTrue($orderItem instanceof $orderItemClass);
$this->assertEquals(10, $orderItem->quantity);
$this->assertEquals(100, $orderItem->subtotal);
......@@ -638,17 +674,22 @@ trait ActiveRecordTestTrait
public function testUnlink()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var \yii\db\ActiveRecordInterface $orderClass */
$orderClass = $this->getOrderClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// has many
$customer = $this->callCustomerFind(2);
$customer = $customerClass::find(2);
$this->assertEquals(2, count($customer->orders));
$customer->unlink('orders', $customer->orders[1], true);
$this->afterSave();
$this->assertEquals(1, count($customer->orders));
$this->assertNull($this->callOrderFind(3));
$this->assertNull($orderClass::find(3));
// via model
$order = $this->callOrderFind(2);
$order = $orderClass::find(2);
$this->assertEquals(3, count($order->items));
$this->assertEquals(3, count($order->orderItems));
$order->unlink('items', $order->items[2], true);
......@@ -662,6 +703,7 @@ trait ActiveRecordTestTrait
public function testInsert()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$customer = new $customerClass;
......@@ -685,10 +727,11 @@ trait ActiveRecordTestTrait
public function testUpdate()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// save
$customer = $this->callCustomerFind(2);
$customer = $customerClass::find(2);
$this->assertTrue($customer instanceof $customerClass);
$this->assertEquals('user2', $customer->name);
$this->assertFalse($customer->isNewRecord);
......@@ -702,16 +745,16 @@ trait ActiveRecordTestTrait
$this->assertFalse($customer->isNewRecord);
$this->assertFalse(static::$afterSaveNewRecord);
$this->assertFalse(static::$afterSaveInsert);
$customer2 = $this->callCustomerFind(2);
$customer2 = $customerClass::find(2);
$this->assertEquals('user2x', $customer2->name);
// updateAll
$customer = $this->callCustomerFind(3);
$customer = $customerClass::find(3);
$this->assertEquals('user3', $customer->name);
$ret = $customerClass::updateAll(['name' => 'temp'], ['id' => 3]);
$this->afterSave();
$this->assertEquals(1, $ret);
$customer = $this->callCustomerFind(3);
$customer = $customerClass::find(3);
$this->assertEquals('temp', $customer->name);
$ret = $customerClass::updateAll(['name' => 'tempX']);
......@@ -725,10 +768,11 @@ trait ActiveRecordTestTrait
public function testUpdateAttributes()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// save
$customer = $this->callCustomerFind(2);
$customer = $customerClass::find(2);
$this->assertTrue($customer instanceof $customerClass);
$this->assertEquals('user2', $customer->name);
$this->assertFalse($customer->isNewRecord);
......@@ -741,10 +785,10 @@ trait ActiveRecordTestTrait
$this->assertFalse($customer->isNewRecord);
$this->assertFalse(static::$afterSaveNewRecord);
$this->assertFalse(static::$afterSaveInsert);
$customer2 = $this->callCustomerFind(2);
$customer2 = $customerClass::find(2);
$this->assertEquals('user2x', $customer2->name);
$customer = $this->callCustomerFind(1);
$customer = $customerClass::find(1);
$this->assertEquals('user1', $customer->name);
$this->assertEquals(1, $customer->status);
$customer->name = 'user1x';
......@@ -752,29 +796,30 @@ trait ActiveRecordTestTrait
$customer->updateAttributes(['name']);
$this->assertEquals('user1x', $customer->name);
$this->assertEquals(2, $customer->status);
$customer = $this->callCustomerFind(1);
$customer = $customerClass::find(1);
$this->assertEquals('user1x', $customer->name);
$this->assertEquals(1, $customer->status);
}
public function testUpdateCounters()
{
/** @var \yii\db\ActiveRecordInterface $orderItemClass */
$orderItemClass = $this->getOrderItemClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// updateCounters
$pk = ['order_id' => 2, 'item_id' => 4];
$orderItem = $this->callOrderItemFind($pk);
$orderItem = $orderItemClass::find($pk);
$this->assertEquals(1, $orderItem->quantity);
$ret = $orderItem->updateCounters(['quantity' => -1]);
$this->afterSave();
$this->assertEquals(1, $ret);
$this->assertEquals(0, $orderItem->quantity);
$orderItem = $this->callOrderItemFind($pk);
$orderItem = $orderItemClass::find($pk);
$this->assertEquals(0, $orderItem->quantity);
// updateAllCounters
$pk = ['order_id' => 1, 'item_id' => 2];
$orderItem = $this->callOrderItemFind($pk);
$orderItem = $orderItemClass::find($pk);
$this->assertEquals(2, $orderItem->quantity);
$ret = $orderItemClass::updateAllCounters([
'quantity' => 3,
......@@ -782,31 +827,32 @@ trait ActiveRecordTestTrait
], $pk);
$this->afterSave();
$this->assertEquals(1, $ret);
$orderItem = $this->callOrderItemFind($pk);
$orderItem = $orderItemClass::find($pk);
$this->assertEquals(5, $orderItem->quantity);
$this->assertEquals(30, $orderItem->subtotal);
}
public function testDelete()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
// delete
$customer = $this->callCustomerFind(2);
$customer = $customerClass::find(2);
$this->assertTrue($customer instanceof $customerClass);
$this->assertEquals('user2', $customer->name);
$customer->delete();
$this->afterSave();
$customer = $this->callCustomerFind(2);
$customer = $customerClass::find(2);
$this->assertNull($customer);
// deleteAll
$customers = $this->callCustomerFind()->all();
$customers = $customerClass::find()->all();
$this->assertEquals(2, count($customers));
$ret = $customerClass::deleteAll();
$this->afterSave();
$this->assertEquals(2, $ret);
$customers = $this->callCustomerFind()->all();
$customers = $customerClass::find()->all();
$this->assertEquals(0, count($customers));
$ret = $customerClass::deleteAll();
......@@ -820,6 +866,7 @@ trait ActiveRecordTestTrait
*/
public function testBooleanAttribute()
{
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var TestCase|ActiveRecordTestTrait $this */
$customer = new $customerClass();
......@@ -837,16 +884,16 @@ trait ActiveRecordTestTrait
$customer->refresh();
$this->assertEquals(0, $customer->status);
$customers = $this->callCustomerFind()->where(['status' => true])->all();
$customers = $customerClass::find()->where(['status' => true])->all();
$this->assertEquals(2, count($customers));
$customers = $this->callCustomerFind()->where(['status' => false])->all();
$customers = $customerClass::find()->where(['status' => false])->all();
$this->assertEquals(1, count($customers));
}
public function testAfterFind()
{
/** @var BaseActiveRecord $customerClass */
/** @var \yii\db\ActiveRecordInterface $customerClass */
$customerClass = $this->getCustomerClass();
/** @var BaseActiveRecord $orderClass */
$orderClass = $this->getOrderClass();
......@@ -859,22 +906,22 @@ trait ActiveRecordTestTrait
$afterFindCalls[] = [get_class($ar), $ar->getIsNewRecord(), $ar->getPrimaryKey(), $ar->isRelationPopulated('orders')];
});
$customer = $this->callCustomerFind(1);
$customer = $customerClass::find(1);
$this->assertNotNull($customer);
$this->assertEquals([[$customerClass, false, 1, false]], $afterFindCalls);
$afterFindCalls = [];
$customer = $this->callCustomerFind()->where(['id' => 1])->one();
$customer = $customerClass::find()->where(['id' => 1])->one();
$this->assertNotNull($customer);
$this->assertEquals([[$customerClass, false, 1, false]], $afterFindCalls);
$afterFindCalls = [];
$customer = $this->callCustomerFind()->where(['id' => 1])->all();
$customer = $customerClass::find()->where(['id' => 1])->all();
$this->assertNotNull($customer);
$this->assertEquals([[$customerClass, false, 1, false]], $afterFindCalls);
$afterFindCalls = [];
$customer = $this->callCustomerFind()->where(['id' => 1])->with('orders')->all();
$customer = $customerClass::find()->where(['id' => 1])->with('orders')->all();
$this->assertNotNull($customer);
$this->assertEquals([
[$this->getOrderClass(), false, 1, false],
......@@ -883,10 +930,10 @@ trait ActiveRecordTestTrait
$afterFindCalls = [];
if ($this instanceof \yiiunit\extensions\redis\ActiveRecordTest) { // TODO redis does not support orderBy() yet
$customer = $this->callCustomerFind()->where(['id' => [1, 2]])->with('orders')->all();
$customer = $customerClass::find()->where(['id' => [1, 2]])->with('orders')->all();
} else {
// orderBy is needed to avoid random test failure
$customer = $this->callCustomerFind()->where(['id' => [1, 2]])->with('orders')->orderBy('name')->all();
$customer = $customerClass::find()->where(['id' => [1, 2]])->with('orders')->orderBy('name')->all();
}
$this->assertNotNull($customer);
$this->assertEquals([
......
......@@ -26,26 +26,6 @@ class ActiveRecordTest extends DatabaseTestCase
ActiveRecord::$db = $this->getConnection();
}
public function callCustomerFind($q = null)
{
return Customer::find($q);
}
public function callOrderFind($q = null)
{
return Order::find($q);
}
public function callOrderItemFind($q = null)
{
return OrderItem::find($q);
}
public function callItemFind($q = null)
{
return Item::find($q);
}
public function getCustomerClass()
{
return Customer::className();
......@@ -69,7 +49,7 @@ class ActiveRecordTest extends DatabaseTestCase
public function testCustomColumns()
{
// find custom column
$customer = $this->callCustomerFind()->select(['*', '(status*2) AS status2'])
$customer = Customer::find()->select(['*', '(status*2) AS status2'])
->where(['name' => 'user3'])->one();
$this->assertEquals(3, $customer->id);
$this->assertEquals(4, $customer->status2);
......@@ -78,19 +58,19 @@ class ActiveRecordTest extends DatabaseTestCase
public function testStatisticalFind()
{
// find count, sum, average, min, max, scalar
$this->assertEquals(3, $this->callCustomerFind()->count());
$this->assertEquals(2, $this->callCustomerFind()->where('id=1 OR id=2')->count());
$this->assertEquals(6, $this->callCustomerFind()->sum('id'));
$this->assertEquals(2, $this->callCustomerFind()->average('id'));
$this->assertEquals(1, $this->callCustomerFind()->min('id'));
$this->assertEquals(3, $this->callCustomerFind()->max('id'));
$this->assertEquals(3, $this->callCustomerFind()->select('COUNT(*)')->scalar());
$this->assertEquals(3, Customer::find()->count());
$this->assertEquals(2, Customer::find()->where('id=1 OR id=2')->count());
$this->assertEquals(6, Customer::find()->sum('id'));
$this->assertEquals(2, Customer::find()->average('id'));
$this->assertEquals(1, Customer::find()->min('id'));
$this->assertEquals(3, Customer::find()->max('id'));
$this->assertEquals(3, Customer::find()->select('COUNT(*)')->scalar());
}
public function testFindScalar()
{
// query scalar
$customerName = $this->callCustomerFind()->where(['id' => 2])->select('name')->scalar();
$customerName = Customer::find()->where(['id' => 2])->select('name')->scalar();
$this->assertEquals('user2', $customerName);
}
......@@ -168,7 +148,7 @@ class ActiveRecordTest extends DatabaseTestCase
public function testDeeplyNestedTableRelation()
{
/** @var Customer $customer */
$customer = $this->callCustomerFind(1);
$customer = Customer::find(1);
$this->assertNotNull($customer);
$items = $customer->orderItems;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment