packages/ztd-query-core/tests/Unit/Shadow/Mutation/Row/MultiUpdateMutationTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Shadow\Mutation\Row;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use ZtdQuery\Shadow\Mutation\Row\MultiTableMutationRow;
11use ZtdQuery\Shadow\Mutation\Row\MultiTableMutationTarget;
12use ZtdQuery\Shadow\Mutation\Row\MultiUpdateMutation;
13use ZtdQuery\Shadow\ShadowStore;
14
15#[UsesClass(ShadowStore::class)]
16#[UsesClass(MultiTableMutationRow::class)]
17#[UsesClass(MultiTableMutationTarget::class)]
18#[CoversClass(MultiUpdateMutation::class)]
19#[UsesClass(\ZtdQuery\Shadow\Row\RowMatch::class)]
20#[UsesClass(\ZtdQuery\Schema\RowSet::class)]
21final class MultiUpdateMutationTest extends TestCase
22{
23    public function testApplyUpdatesMultipleTables(): void
24    {
25        $store = new ShadowStore();
26        $store->set('users', [
27            ['id' => 1, 'name' => 'Alice', 'status' => 'active'],
28            ['id' => 2, 'name' => 'Bob', 'status' => 'active'],
29        ]);
30        $store->set('profiles', [
31            ['user_id' => 1, 'verified' => false],
32            ['user_id' => 2, 'verified' => false],
33        ]);
34
35        $mutation = new MultiUpdateMutation([
36            new MultiTableMutationTarget('users', ['id', 'name', 'status'], ['id']),
37            new MultiTableMutationTarget('profiles', ['user_id', 'verified'], ['user_id']),
38        ]);
39
40        $mutation->apply($store, [
41            [
42                '__ztd_multi_0_value_0' => 1,
43                '__ztd_multi_0_value_1' => 'Alice Updated',
44                '__ztd_multi_0_value_2' => 'inactive',
45                '__ztd_multi_0_identity_0' => 1,
46                '__ztd_multi_1_value_0' => 1,
47                '__ztd_multi_1_value_1' => true,
48                '__ztd_multi_1_identity_0' => 1,
49            ],
50        ]);
51
52        self::assertSame('Alice Updated', $store->get('users')[0]['name']);
53        self::assertSame('inactive', $store->get('users')[0]['status']);
54        self::assertTrue($store->get('profiles')[0]['verified']);
55    }
56
57    public function testTableNameReturnsPrimaryTable(): void
58    {
59        $mutation = new MultiUpdateMutation([
60            new MultiTableMutationTarget('users', ['id'], ['id']),
61            new MultiTableMutationTarget('profiles', ['user_id'], ['user_id']),
62        ]);
63
64        self::assertSame('users', $mutation->tableName());
65    }
66
67    public function testTableNamesReturnsAllTableNames(): void
68    {
69        $mutation = new MultiUpdateMutation([
70            new MultiTableMutationTarget('users', ['id'], ['id']),
71            new MultiTableMutationTarget('profiles', ['user_id'], ['user_id']),
72            new MultiTableMutationTarget('settings', ['user_id'], ['user_id']),
73        ]);
74
75        self::assertSame(['users', 'profiles', 'settings'], $mutation->tableNames());
76    }
77
78    public function testApplyWithEmptyTablesReturnsEmptyPrimaryTable(): void
79    {
80        $mutation = new MultiUpdateMutation([]);
81
82        self::assertSame('', $mutation->tableName());
83    }
84
85    public function testApplyUpdatesMultipleRows(): void
86    {
87        $store = new ShadowStore();
88        $store->set('users', [
89            ['id' => 1, 'name' => 'Alice'],
90            ['id' => 2, 'name' => 'Bob'],
91            ['id' => 3, 'name' => 'Carol'],
92        ]);
93
94        $mutation = new MultiUpdateMutation([
95            new MultiTableMutationTarget('users', ['id', 'name'], ['id']),
96        ]);
97
98        $mutation->apply($store, [
99            [
100                '__ztd_multi_0_value_0' => 1,
101                '__ztd_multi_0_value_1' => 'Alice Updated',
102                '__ztd_multi_0_identity_0' => 1,
103            ],
104            [
105                '__ztd_multi_0_value_0' => 3,
106                '__ztd_multi_0_value_1' => 'Carol Updated',
107                '__ztd_multi_0_identity_0' => 3,
108            ],
109        ]);
110
111        self::assertSame('Alice Updated', $store->get('users')[0]['name']);
112        self::assertSame('Bob', $store->get('users')[1]['name']);
113        self::assertSame('Carol Updated', $store->get('users')[2]['name']);
114    }
115
116    public function testApplySkipsRowsWithIncompleteValuesOrIdentity(): void
117    {
118        $store = new ShadowStore();
119        $store->set('users', [['id' => 1, 'name' => 'Alice']]);
120        $mutation = new MultiUpdateMutation([
121            new MultiTableMutationTarget('users', ['id', 'name'], ['id']),
122        ]);
123
124        $mutation->apply($store, [
125            [
126                '__ztd_multi_0_identity_0' => 1,
127            ],
128            [
129                '__ztd_multi_0_value_0' => 1,
130                '__ztd_multi_0_value_1' => 'Incomplete',
131            ],
132        ]);
133
134        self::assertSame([['id' => 1, 'name' => 'Alice']], $store->get('users'));
135    }
136}
137