packages/ztd-query-core/tests/Unit/Shadow/Mutation/Table/CreateTableLikeMutationTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Shadow\Mutation\Table;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use RuntimeException;
11use ZtdQuery\Schema\TableDefinition;
12use ZtdQuery\Schema\TableDefinitionRegistry;
13use ZtdQuery\Shadow\Mutation\Table\CreateTableLikeMutation;
14use ZtdQuery\Shadow\ShadowStore;
15
16#[UsesClass(TableDefinition::class)]
17#[UsesClass(TableDefinitionRegistry::class)]
18#[UsesClass(ShadowStore::class)]
19#[CoversClass(CreateTableLikeMutation::class)]
20#[UsesClass(\ZtdQuery\Schema\RowSet::class)]
21final class CreateTableLikeMutationTest extends TestCase
22{
23    public function testApplyCopiesSchemaFromSourceTable(): void
24    {
25        $registry = new TableDefinitionRegistry();
26        $sourceDefinition = new TableDefinition(
27            ['id', 'name'],
28            ['id' => 'INT', 'name' => 'VARCHAR(255)'],
29            ['id'],
30            ['id'],
31            [],
32        );
33        $registry->register('users', $sourceDefinition);
34        $store = new ShadowStore();
35
36        $mutation = new CreateTableLikeMutation('users_backup', 'users', $registry);
37        $mutation->apply($store, []);
38
39        $newDefinition = $registry->get('users_backup');
40        self::assertNotNull($newDefinition);
41        self::assertSame(['id', 'name'], $newDefinition->columns);
42    }
43
44    public function testApplyEnsuresNewTableInShadowStore(): void
45    {
46        $registry = new TableDefinitionRegistry();
47        $sourceDefinition = new TableDefinition(
48            ['id'],
49            ['id' => 'INT'],
50            ['id'],
51            ['id'],
52            [],
53        );
54        $registry->register('users', $sourceDefinition);
55        $store = new ShadowStore();
56
57        $mutation = new CreateTableLikeMutation('users_backup', 'users', $registry);
58        $mutation->apply($store, []);
59
60        self::assertSame([], $store->get('users_backup'));
61    }
62
63    public function testTableNameReturnsNewTableName(): void
64    {
65        $registry = new TableDefinitionRegistry();
66        $mutation = new CreateTableLikeMutation('users_backup', 'users', $registry);
67
68        self::assertSame('users_backup', $mutation->tableName());
69    }
70
71    public function testApplyThrowsExceptionWhenTargetTableExists(): void
72    {
73        $registry = new TableDefinitionRegistry();
74        $sourceDefinition = new TableDefinition(
75            ['id'],
76            ['id' => 'INT'],
77            ['id'],
78            ['id'],
79            [],
80        );
81        $registry->register('users', $sourceDefinition);
82
83        $backupDefinition = new TableDefinition(
84            ['id'],
85            ['id' => 'INT'],
86            ['id'],
87            ['id'],
88            [],
89        );
90        $registry->register('users_backup', $backupDefinition);
91        $store = new ShadowStore();
92
93        $mutation = new CreateTableLikeMutation('users_backup', 'users', $registry);
94
95        $this->expectException(RuntimeException::class);
96        $this->expectExceptionMessage("Table 'users_backup' already exists.");
97
98        $mutation->apply($store, []);
99    }
100
101    public function testApplyWithIfNotExistsSkipsWhenTableExists(): void
102    {
103        $registry = new TableDefinitionRegistry();
104        $sourceDefinition = new TableDefinition(
105            ['id', 'name'],
106            ['id' => 'INT', 'name' => 'VARCHAR(255)'],
107            ['id'],
108            ['id'],
109            [],
110        );
111        $registry->register('users', $sourceDefinition);
112
113        $originalDefinition = new TableDefinition(
114            ['id'],
115            ['id' => 'INT'],
116            ['id'],
117            ['id'],
118            [],
119        );
120        $registry->register('users_backup', $originalDefinition);
121        $store = new ShadowStore();
122
123        $mutation = new CreateTableLikeMutation('users_backup', 'users', $registry, true);
124        $mutation->apply($store, []);
125
126        $def = $registry->get('users_backup');
127        self::assertNotNull($def);
128        self::assertSame(['id'], $def->columns);
129    }
130
131    public function testApplyThrowsExceptionWhenSourceTableDoesNotExist(): void
132    {
133        $registry = new TableDefinitionRegistry();
134        $store = new ShadowStore();
135
136        $mutation = new CreateTableLikeMutation('users_backup', 'users', $registry);
137
138        $this->expectException(RuntimeException::class);
139        $this->expectExceptionMessage("Source table 'users' does not exist.");
140
141        $mutation->apply($store, []);
142    }
143}
144