Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions tests/framework/db/ExpressionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/

declare(strict_types=1);

namespace yiiunit\framework\db;

use yii\db\Expression;
use yii\db\ExpressionInterface;
use yiiunit\TestCase;

/**
* @group db
*/
class ExpressionTest extends TestCase
{
public function testConstructor(): void
{
$expression = new Expression('NOW()');

self::assertSame('NOW()', $expression->expression);
self::assertSame([], $expression->params);
}

public function testConstructorWithConfig(): void
{
$expression = new Expression('DEFAULT', [], ['expression' => 'overridden']);

self::assertSame('overridden', $expression->expression);
}

public function testToString(): void
{
$expression = new Expression('COUNT(*)');

self::assertSame('COUNT(*)', (string) $expression);
self::assertSame('COUNT(*)', $expression->__toString());
}

public function testImplementsExpressionInterface(): void
{
$expression = new Expression('1');

self::assertInstanceOf(ExpressionInterface::class, $expression);
}

public function testEmptyExpression(): void
{
$expression = new Expression('');

self::assertSame('', $expression->expression);
self::assertSame('', (string) $expression);
}

/**
* @dataProvider expressionsProvider
*/
public function testVariousExpressions(string $sql, array $params): void
{
$expression = new Expression($sql, $params);

self::assertSame($sql, (string) $expression);
self::assertSame($params, $expression->params);
}

public static function expressionsProvider(): array
{
return [
'simple function' => ['NOW()', []],
'aggregate' => ['COUNT(*)', []],
'with placeholder' => ['status = :status', [':status' => 1]],
'multiple placeholders' => [
'age BETWEEN :min AND :max',
[':min' => 18, ':max' => 65],
],
'subquery-like' => ['(SELECT MAX(id) FROM users)', []],
'raw literal' => ['1', []],
'complex expression' => [
'CASE WHEN status = :active THEN 1 ELSE 0 END',
[':active' => 'active'],
],
];
}
}
151 changes: 151 additions & 0 deletions tests/framework/db/JsonExpressionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/

declare(strict_types=1);

namespace yiiunit\framework\db;

use yii\base\InvalidConfigException;
use yii\db\ExpressionInterface;
use yii\db\JsonExpression;
use yii\db\Query;
use yiiunit\TestCase;

/**
* @group db
*/
class JsonExpressionTest extends TestCase
{
public function testConstructorWithArray(): void
{
$data = ['a' => 1, 'b' => 2];
$expression = new JsonExpression($data);

self::assertSame($data, $expression->getValue());
self::assertNull($expression->getType());
}

public function testConstructorWithType(): void
{
$expression = new JsonExpression([1, 2, 3], JsonExpression::TYPE_JSON);

self::assertSame(JsonExpression::TYPE_JSON, $expression->getType());
}

public function testConstructorWithJsonbType(): void
{
$expression = new JsonExpression(['key' => 'val'], JsonExpression::TYPE_JSONB);

self::assertSame(JsonExpression::TYPE_JSONB, $expression->getType());
}

public function testUnwrapsNestedJsonExpression(): void
{
$inner = new JsonExpression(['nested' => true]);
$outer = new JsonExpression($inner);

self::assertSame(['nested' => true], $outer->getValue());
}

public function testUnwrapsNestedJsonExpressionPreservesOuterType(): void
{
$inner = new JsonExpression(['data' => 1], JsonExpression::TYPE_JSON);
$outer = new JsonExpression($inner, JsonExpression::TYPE_JSONB);

self::assertSame(['data' => 1], $outer->getValue());
self::assertSame(JsonExpression::TYPE_JSONB, $outer->getType());
}

public function testUnwrapsOnlyOneLevel(): void
{
$innermost = new JsonExpression('deep');
$middle = new JsonExpression($innermost);
$outer = new JsonExpression($middle);

self::assertSame('deep', $outer->getValue());
}

public function testImplementsExpressionInterface(): void
{
$expression = new JsonExpression([]);

self::assertInstanceOf(ExpressionInterface::class, $expression);
}

public function testImplementsJsonSerializable(): void
{
$expression = new JsonExpression([]);

self::assertInstanceOf(\JsonSerializable::class, $expression);
}

public function testJsonSerializeReturnsValue(): void
{
$data = ['x' => 10, 'y' => 20];
$expression = new JsonExpression($data);

self::assertSame($data, $expression->jsonSerialize());
}

public function testJsonSerializeWithScalar(): void
{
$expression = new JsonExpression('string value');

self::assertSame('string value', $expression->jsonSerialize());
}

public function testJsonSerializeWithNull(): void
{
$expression = new JsonExpression(null);

self::assertNull($expression->jsonSerialize());
}

public function testJsonSerializeThrowsOnQueryInterface(): void
{
$query = new Query();
$expression = new JsonExpression($query);

$this->expectException(InvalidConfigException::class);
$expression->jsonSerialize();
}

public function testJsonEncodeUsesJsonSerialize(): void
{
$data = ['name' => 'test', 'count' => 42];
$expression = new JsonExpression($data);

self::assertSame('{"name":"test","count":42}', json_encode($expression));
}

/**
* @dataProvider valueTypesProvider
*/
public function testAcceptsVariousValueTypes($value): void
{
$expression = new JsonExpression($value);

self::assertSame($value, $expression->getValue());
}

public static function valueTypesProvider(): array
{
return [
'array' => [['a', 'b', 'c']],
'associative array' => [['key' => 'value']],
'nested array' => [['a' => ['b' => ['c' => 1]]]],
'string' => ['simple string'],
'integer' => [42],
'float' => [3.14],
'boolean true' => [true],
'boolean false' => [false],
'null' => [null],
'empty array' => [[]],
];
}
}
141 changes: 141 additions & 0 deletions tests/framework/db/TableSchemaTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/

declare(strict_types=1);

namespace yiiunit\framework\db;

use yii\base\InvalidArgumentException;
use yii\db\ColumnSchema;
use yii\db\TableSchema;
use yiiunit\TestCase;

/**
* @group db
*/
class TableSchemaTest extends TestCase
{
private function createTableSchema(array $columnNames = ['id', 'name', 'email']): TableSchema
{
$table = new TableSchema();
$table->name = 'test_table';
$table->fullName = 'test_table';

foreach ($columnNames as $name) {
$column = new ColumnSchema();
$column->name = $name;
$column->isPrimaryKey = false;
$table->columns[$name] = $column;
}

return $table;
}

public function testGetColumnReturnsColumnSchema(): void
{
$table = $this->createTableSchema();

$column = $table->getColumn('name');

self::assertInstanceOf(ColumnSchema::class, $column);
self::assertSame('name', $column->name);
}

public function testGetColumnReturnsNullForNonExistent(): void
{
$table = $this->createTableSchema();

self::assertNull($table->getColumn('nonexistent'));
}

public function testGetColumnNames(): void
{
$table = $this->createTableSchema(['id', 'name', 'email']);

self::assertSame(['id', 'name', 'email'], $table->getColumnNames());
}

public function testGetColumnNamesEmpty(): void
{
$table = $this->createTableSchema([]);

self::assertSame([], $table->getColumnNames());
}

public function testColumnNamesProperty(): void
{
$table = $this->createTableSchema(['a', 'b']);

self::assertSame(['a', 'b'], $table->columnNames);
}

public function testFixPrimaryKeyWithSingleKey(): void
{
$table = $this->createTableSchema();

$table->fixPrimaryKey('id');

self::assertSame(['id'], $table->primaryKey);
self::assertTrue($table->columns['id']->isPrimaryKey);
self::assertFalse($table->columns['name']->isPrimaryKey);
self::assertFalse($table->columns['email']->isPrimaryKey);
}

public function testFixPrimaryKeyWithCompositeKey(): void
{
$table = $this->createTableSchema(['user_id', 'role_id', 'data']);

$table->fixPrimaryKey(['user_id', 'role_id']);

self::assertSame(['user_id', 'role_id'], $table->primaryKey);
self::assertTrue($table->columns['user_id']->isPrimaryKey);
self::assertTrue($table->columns['role_id']->isPrimaryKey);
self::assertFalse($table->columns['data']->isPrimaryKey);
}

public function testFixPrimaryKeyResetsOldPrimaryKey(): void
{
$table = $this->createTableSchema();
$table->columns['id']->isPrimaryKey = true;
$table->primaryKey = ['id'];

$table->fixPrimaryKey('name');

self::assertSame(['name'], $table->primaryKey);
self::assertFalse($table->columns['id']->isPrimaryKey);
self::assertTrue($table->columns['name']->isPrimaryKey);
}

public function testFixPrimaryKeyThrowsOnNonExistentColumn(): void
{
$table = $this->createTableSchema();

$this->expectException(InvalidArgumentException::class);
$table->fixPrimaryKey('nonexistent');
}

public function testFixPrimaryKeyThrowsOnPartialComposite(): void
{
$table = $this->createTableSchema();

$this->expectException(InvalidArgumentException::class);
$table->fixPrimaryKey(['id', 'missing']);
}

public function testFixPrimaryKeyWithEmptyArray(): void
{
$table = $this->createTableSchema();
$table->columns['id']->isPrimaryKey = true;
$table->primaryKey = ['id'];

$table->fixPrimaryKey([]);

self::assertSame([], $table->primaryKey);
self::assertFalse($table->columns['id']->isPrimaryKey);
}
}
Loading