Skip to content
Open
Show file tree
Hide file tree
Changes from 78 commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
c95a1ab
fix: Checking the state of a database with a binary field.
AZabolotnikov Jan 18, 2026
03606be
fix: Checking the state of a database with a binary field.
AZabolotnikov Jan 18, 2026
b68918a
fix: Checking the state of a database with a binary field.
AZabolotnikov Jan 18, 2026
4b349e7
Update tests/ModelTestStateTest.php
AZabolotnikov Jan 18, 2026
ba961a8
fix: Checking the state of a database with a binary field.
AZabolotnikov Jan 28, 2026
bd8ca19
Merge remote-tracking branch 'origin/azabolotnikov/fix-db-check-binar…
AZabolotnikov Jan 28, 2026
32f7886
fix: Checking the state of a database with a binary field.
AZabolotnikov Jan 28, 2026
f5ade29
fix: Checking the state of a database with a binary field.
AZabolotnikov Jan 28, 2026
1b6250a
Update src/Testing/TableTestState.php
AZabolotnikov Jan 28, 2026
9848df9
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
AZabolotnikov Jan 28, 2026
4b80523
fix: Checking the state of a database with a binary field.
AZabolotnikov Feb 2, 2026
8d9bcfa
Merge remote-tracking branch 'origin/azabolotnikov/fix-db-check-binar…
AZabolotnikov Feb 2, 2026
ff2e175
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
DenTray Feb 5, 2026
a0b2c76
fix: Checking the state of a database with a binary field.
AZabolotnikov Feb 5, 2026
f6ff34f
Merge remote-tracking branch 'origin/azabolotnikov/fix-db-check-binar…
AZabolotnikov Feb 5, 2026
9484e68
fix: Checking the state of a database with a binary field.
AZabolotnikov Feb 5, 2026
7473a6b
fix: Checking the state of a database with a binary field.
AZabolotnikov Feb 5, 2026
4258cbc
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
DenTray Mar 23, 2026
c74065b
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 6, 2026
8951b4b
Merge remote-tracking branch 'origin/azabolotnikov/fix-db-check-binar…
AZabolotnikov Apr 6, 2026
a60b08e
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 6, 2026
33993e9
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 6, 2026
aca1a87
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 6, 2026
b4aeffc
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
AZabolotnikov Apr 6, 2026
e7fa346
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 6, 2026
f4a501a
Merge remote-tracking branch 'origin/azabolotnikov/fix-db-check-binar…
AZabolotnikov Apr 6, 2026
e72c12a
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 7, 2026
edad585
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 7, 2026
bb73fab
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 7, 2026
2a976ad
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 7, 2026
6fab5c9
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
AZabolotnikov Apr 8, 2026
c597064
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 8, 2026
5e38ced
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 8, 2026
ab7f5d6
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 8, 2026
fc7f201
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 8, 2026
c87c21c
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 14, 2026
9e161a5
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 14, 2026
91ddd77
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 14, 2026
348b4c7
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 14, 2026
f2422f4
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 15, 2026
57465f5
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 15, 2026
a9263dc
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 15, 2026
cfd2a6d
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 15, 2026
7aabc7f
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 15, 2026
b2bd039
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 15, 2026
a7dd48c
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 15, 2026
647182d
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 15, 2026
5b5297d
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 20, 2026
57bcc04
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
f035b19
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
10c4a84
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
f9a907e
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
cf3f874
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
fa5b926
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
9652fce
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
f3ee829
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
ee3ce45
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
b3d0fba
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
d73d64d
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
2383392
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
6ad4db8
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
bc48582
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
f323581
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
742b67e
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
AZabolotnikov Apr 21, 2026
da0e89d
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
ddc5ae8
Merge remote-tracking branch 'origin/azabolotnikov/fix-db-check-binar…
AZabolotnikov Apr 21, 2026
ab59651
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
10110ef
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 21, 2026
3cb3676
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
AZabolotnikov Apr 28, 2026
fe3863e
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 28, 2026
8c3d27c
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 29, 2026
e59c1dd
fix: Checking the state of a database with a binary field.
AZabolotnikov Apr 29, 2026
6ae0715
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
AZabolotnikov May 4, 2026
4540130
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
AZabolotnikov May 18, 2026
2428ea9
Merge remote-tracking branch 'origin/azabolotnikov/fix-db-check-binar…
AZabolotnikov May 18, 2026
a049bdf
fix: Checking the state of a database with a binary field.
AZabolotnikov May 18, 2026
e3171a4
fix: Checking the state of a database with a binary field.
AZabolotnikov May 18, 2026
289f186
fix: Checking the state of a database with a binary field.
AZabolotnikov May 18, 2026
d5756ec
fix: Checking the state of a database with a binary field.
AZabolotnikov May 18, 2026
619a525
chore: correct variables order
yburlakov May 20, 2026
fbcbd6a
chore: fix tests
May 20, 2026
9f9bb8f
chore: fix tests with aggregates wrap
May 20, 2026
43c8c71
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
yburlakov May 20, 2026
2a757fa
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
DenTray Jun 3, 2026
e5da600
Update src/Testing/TableTestState.php
AZabolotnikov Jun 3, 2026
854f968
Update tests/support/Mock/Casts/BinaryCast.php
AZabolotnikov Jun 3, 2026
3a8b5fc
Update tests/support/Mock/Casts/BinaryCast.php
AZabolotnikov Jun 3, 2026
285125d
Update src/Testing/TableTestState.php
AZabolotnikov Jun 3, 2026
2216458
fix: strict change detection in TableTestState
AZabolotnikov Jun 4, 2026
b4c8b90
Merge remote-tracking branch 'origin/azabolotnikov/fix-db-check-binar…
AZabolotnikov Jun 4, 2026
4510af2
fix: strict change detection in TableTestState
AZabolotnikov Jun 5, 2026
c2e40b0
fix: strict change detection in TableTestState
AZabolotnikov Jun 5, 2026
505487f
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
AZabolotnikov Jun 24, 2026
01fa046
Merge branch 'master' into azabolotnikov/fix-db-check-binary-field
AZabolotnikov Jul 31, 2026
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
73 changes: 71 additions & 2 deletions src/Testing/TableTestState.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ class TableTestState extends Assert
protected ?string $connectionName;
protected Collection $state;
protected string $uniqueKey;
protected ?array $binaryColumns = null;

protected const array BINARY_COLUMNS = [
'bytea',
'blob',
'tinyblob',
'mediumblob',
'longblob',
'binary',
'varbinary',
];

public function __construct(
string $tableName,
Expand Down Expand Up @@ -91,7 +102,11 @@ protected function prepareChanges(array $changes): array

return array_map(function ($item) use ($jsonFields) {
foreach ($jsonFields as $jsonField) {
if (Arr::has($item, $jsonField)) {
$shouldDecode = Arr::has($item, $jsonField)
&& is_string($item[$jsonField])
&& json_validate($item[$jsonField]);

if ($shouldDecode) {
$item[$jsonField] = json_decode($item[$jsonField], true);
}
}
Expand All @@ -111,10 +126,64 @@ protected function getFixturePath(string $fixtureName): string

protected function getDataSet(string $table, string $orderField = 'id'): Collection
{
return DB::connection($this->connectionName)
$dataSet = DB::connection($this->connectionName)
->table($table)
->orderBy($orderField)
->get()
->map(fn ($record) => (array) $record);

$this->prepareBinaryFields($dataSet);

return $dataSet;
}

protected function prepareBinaryFields(Collection $dataSet): void
{
$this->binaryColumns ??= $this->getBinaryColumns();

$dataSet->transform(function (array $record) {
array_walk($record, function (mixed &$value, string $field) {
if (!is_null($value) && in_array($field, $this->binaryColumns)) {
$value = is_resource($value) ? bin2hex(stream_get_contents($value)) : bin2hex($value);
Comment thread
AZabolotnikov marked this conversation as resolved.
Outdated
}
});

return $record;
});
}

protected function getBinaryColumns(): array
{
$connection = DB::connection($this->connectionName);

$tableSchema = $this->getTableSchema($connection->getDriverName(), $connection->getDatabaseName());

return (empty($tableSchema))
? []
: $connection
->table('information_schema.columns')
->select('column_name')
->where('table_name', $this->tableName)
->whereIn('table_schema', $tableSchema)
->whereIn('data_type', self::BINARY_COLUMNS)
->get()
->pluck('column_name')
->toArray();
}

protected function getTableSchema(string $driverName, string $databaseName): array
{
$tableSchema = match ($driverName) {
'pgsql' => config("database.connections.{$this->connectionName}.schema")
?? config("database.connections.{$this->connectionName}.search_path", 'public'),
'mysql' => $databaseName,
default => '',
};
Comment thread
AZabolotnikov marked this conversation as resolved.

$tableSchema = array_map('trim', explode(',', $tableSchema));

Comment thread
AZabolotnikov marked this conversation as resolved.
$tableSchema = array_filter($tableSchema, fn ($schema) => !empty($schema));
Comment thread
AZabolotnikov marked this conversation as resolved.
Outdated

return Arr::wrap($tableSchema);
}
}
4 changes: 2 additions & 2 deletions tests/BaseRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function testGetOrderableFields()
{
$result = $this->callEncapsulatedMethod(new BaseRequest(), 'getOrderableFields', TestModel::class);

$expectedResult = 'id,name,json_field,castable_field,*,created_at,updated_at';
$expectedResult = 'id,name,json_field,castable_field,cast_binary_field,binary_field,*,created_at,updated_at';

$this->assertEquals($expectedResult, $result);
}
Expand All @@ -30,7 +30,7 @@ public function testGetOrderableFieldsWithAdditionalFields()

$result = $this->callEncapsulatedMethod(new BaseRequest(), 'getOrderableFields', ...$args);

$expectedResult = 'id,name,json_field,castable_field,*,created_at,updated_at,additional_field_1,additional_field_2';
$expectedResult = 'id,name,json_field,castable_field,cast_binary_field,binary_field,*,created_at,updated_at,additional_field_1,additional_field_2';

$this->assertEquals($expectedResult, $result);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ModelTestStateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function testInitialization()
$jsonFields = $this->getProtectedProperty($reflectionClass, 'jsonFields', $modelTestState);
$state = $this->getProtectedProperty($reflectionClass, 'state', $modelTestState);

$this->assertEquals(['json_field', 'castable_field'], $jsonFields);
$this->assertEquals(['json_field', 'castable_field', 'cast_binary_field'], $jsonFields);
$this->assertEquals($originRecords, $state);
}

Expand Down
99 changes: 99 additions & 0 deletions tests/TableTestStateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

use PHPUnit\Framework\Attributes\DataProvider;
use ReflectionClass;
use RonasIT\Support\Testing\ModelTestState;
use RonasIT\Support\Testing\TableTestState;
use RonasIT\Support\Tests\Support\Mock\Models\TestModel;
use RonasIT\Support\Tests\Support\Traits\TableTestStateMockTrait;

class TableTestStateTest extends TestCase
Expand Down Expand Up @@ -102,4 +104,101 @@ public function testAssertChangesWithCustomPrimaryKey()

$modelTestState->assertChangesEqualsFixture('assertion_fixture_primary_key_set');
}

public function testAssertChangesCastedBinaryStringMysqlDriver()
{
$initialDatasetMock = collect([[
'id' => 1,
'cast_binary_field' => null,
]]);

$changedDatasetMock = collect([[
'id' => 1,
'cast_binary_field' => md5('some_string', true),
]]);

$this->mockGettingDatasetForChanges(
responseMock: $changedDatasetMock,
initialState: $initialDatasetMock,
tableName: 'test_models',
binaryColumn: 'cast_binary_field',
dbDriver: 'mysql',
);

$modelTestState = new ModelTestState(TestModel::class);
$modelTestState->assertChangesEqualsFixture('null_to_binary_string_changes');
}
Comment thread
AZabolotnikov marked this conversation as resolved.

public function testAssertChangesCastedBinaryToNull()
{
$initialDatasetMock = collect([[
'id' => 1,
'cast_binary_field' => md5('some_string', true),
]]);

$changedDatasetMock = collect([[
'id' => 1,
'cast_binary_field' => null,
]]);

$this->mockGettingDatasetForChanges(
responseMock: $changedDatasetMock,
initialState: $initialDatasetMock,
tableName: 'test_models',
binaryColumn: 'cast_binary_field',
);

$modelTestState = new ModelTestState(TestModel::class);
$modelTestState->assertChangesEqualsFixture('binary_string_to_null_changes');
}

public function testAssertChangesWithPgsqlBinaryFieldAsResource()
{
$initialDatasetMock = collect([[
'id' => 1,
'binary_field' => null,
]]);

$resource = $this->getTestResource();

$changedDatasetMock = collect([[
'id' => 1,
'binary_field' => $resource,
]]);

$this->mockGettingDatasetForChanges(
responseMock: $changedDatasetMock,
initialState: $initialDatasetMock,
tableName: 'test_models',
binaryColumn: 'binary_field',
);

$modelTestState = new ModelTestState(TestModel::class);

$modelTestState->assertChangesEqualsFixture('null_to_binary_resource_changes');

fclose($resource);
}

public function testAssertChangesWithUnsupportedMysqlDriver()
{
$initialDatasetMock = collect([[
'id' => 1,
'name' => 'name',
]]);

$changedDatasetMock = collect([[
'id' => 1,
'name' => 'name_changed',
]]);

$this->mockGettingDatasetForChangesUnsupportedDriver(
responseMock: $changedDatasetMock,
initialState: $initialDatasetMock,
tableName: 'test_models',
);

$modelTestState = new ModelTestState(TestModel::class);
$modelTestState->assertChangesEqualsFixture('unsupported_db_driver');
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[
"Test"
]
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"updated": [
{
"id": 1,
"cast_binary_field": null
}
],
"created": [],
"deleted": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"updated": [
{
"id": 1,
"binary_field": "31ee76261d87fed8cb9d4c465c48158c"
}
],
"created": [],
"deleted": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"updated": [
{
"id": 1,
"cast_binary_field": "31ee76261d87fed8cb9d4c465c48158c"
}
],
"created": [],
"deleted": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"updated": [],
"created": [],
"deleted": [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks strange, it should contains only updated

{
"id": 1,
"name": "name"
}
]
}
18 changes: 18 additions & 0 deletions tests/support/Mock/Casts/BinaryCast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace RonasIT\Support\Tests\Support\Mock\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class BinaryCast implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
return is_null($value) ? $value : bin2hex($value);
Comment thread
AZabolotnikov marked this conversation as resolved.
Outdated
}

public function set($model, $key, $value, $attributes)
{
return is_null($value) ? $value : md5($value, true);
Comment thread
AZabolotnikov marked this conversation as resolved.
Outdated
}
}
Comment thread
AZabolotnikov marked this conversation as resolved.
4 changes: 4 additions & 0 deletions tests/support/Mock/Models/TestModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use RonasIT\Support\Tests\Support\Mock\Casts\BinaryCast;
use RonasIT\Support\Tests\Support\Mock\Casts\JSONCustomCast;
use RonasIT\Support\Traits\ModelTrait;

Expand All @@ -17,11 +18,14 @@ class TestModel extends Model
'name',
'json_field',
'castable_field',
'cast_binary_field',
'binary_field',
];

protected $casts = [
'json_field' => 'array',
'castable_field' => JSONCustomCast::class,
'cast_binary_field' => BinaryCast::class,
];

public function relation(): HasMany
Expand Down
Loading
Loading