packages/sql-fixture/tests/Unit/DatabaseFixtureProviderTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit;
6
7use Faker\Factory;
8use PDO;
9use PHPUnit\Framework\Attributes\CoversClass;
10use PHPUnit\Framework\Attributes\Test;
11use PHPUnit\Framework\Attributes\UsesClass;
12use PHPUnit\Framework\TestCase;
13use SqlFixture\DatabaseFixtureProvider;
14use SqlFixture\FixtureGenerator;
15use SqlFixture\Platform\PlatformFactory;
16use SqlFixture\Platform\Sqlite\SqliteSchemaFetcher;
17use SqlFixture\Platform\Sqlite\SqliteSchemaParser;
18use SqlFixture\Platform\Sqlite\SqliteTypeMapper;
19use SqlFixture\Schema\ColumnDefinition;
20use SqlFixture\Schema\TableSchema;
21
22#[CoversClass(DatabaseFixtureProvider::class)]
23#[UsesClass(FixtureGenerator::class)]
24#[UsesClass(PlatformFactory::class)]
25#[UsesClass(SqliteSchemaFetcher::class)]
26#[UsesClass(SqliteSchemaParser::class)]
27#[UsesClass(SqliteTypeMapper::class)]
28#[UsesClass(ColumnDefinition::class)]
29#[UsesClass(TableSchema::class)]
30#[CoversClass(\SqlFixture\Provider\DatabaseSchemaCache::class)]
31#[UsesClass(\SqlFixture\Hydrator\HydrationException::class)]
32#[UsesClass(\SqlFixture\Hydrator\HydratorInterface::class)]
33#[UsesClass(\SqlFixture\Hydrator\ReflectionHydrator::class)]
34#[UsesClass(\SqlFixture\Platform\MySql\MySqlSchemaFetcher::class)]
35#[UsesClass(\SqlFixture\Platform\MySql\MySqlSchemaParser::class)]
36#[UsesClass(\SqlFixture\Platform\MySql\MySqlTypeMapper::class)]
37#[UsesClass(\SqlFixture\Platform\PostgreSql\PostgreSqlSchemaFetcher::class)]
38#[UsesClass(\SqlFixture\Platform\PostgreSql\PostgreSqlSchemaParser::class)]
39#[UsesClass(\SqlFixture\Platform\PostgreSql\PostgreSqlTypeMapper::class)]
40#[UsesClass(\SqlFixture\Schema\SchemaFetcherInterface::class)]
41#[UsesClass(\SqlFixture\Schema\SchemaParseException::class)]
42#[UsesClass(\SqlFixture\Schema\SchemaParserInterface::class)]
43#[UsesClass(\SqlFixture\TypeMapper\TypeMapperInterface::class)]
44#[UsesClass(\SqlFixture\Fixture\RowGeneration::class)]
45#[UsesClass(\SqlFixture\Fixture\Validation\OverrideValidator::class)]
46#[UsesClass(\SqlFixture\Hydrator\Reflection\ConstructorHydration::class)]
47#[UsesClass(\SqlFixture\Hydrator\Reflection\PropertyHydration::class)]
48#[UsesClass(\SqlFixture\Hydrator\Reflection\PropertyNames::class)]
49#[UsesClass(\SqlFixture\Hydrator\Reflection\ValueConversion::class)]
50#[UsesClass(\SqlFixture\InvalidOverrideException::class)]
51#[UsesClass(\SqlFixture\Platform\MySql\Schema\ColumnParser::class)]
52#[UsesClass(\SqlFixture\Platform\MySql\Schema\CreateTableQuery::class)]
53#[UsesClass(\SqlFixture\Platform\MySql\Schema\DefaultExpression::class)]
54#[UsesClass(\SqlFixture\Platform\MySql\Schema\DefinitionIntegrity::class)]
55#[UsesClass(\SqlFixture\Platform\MySql\Schema\IdentifierQuoter::class)]
56#[UsesClass(\SqlFixture\Platform\MySql\Schema\TableDefinition::class)]
57#[UsesClass(\SqlFixture\Platform\MySql\Schema\TypeParameters::class)]
58#[UsesClass(\SqlFixture\Platform\MySql\Value\ColumnGenerator::class)]
59#[UsesClass(\SqlFixture\Platform\MySql\Value\DecimalGenerator::class)]
60#[UsesClass(\SqlFixture\Platform\MySql\Value\GeometryGenerator::class)]
61#[UsesClass(\SqlFixture\Platform\MySql\Value\IntegerGenerator::class)]
62#[UsesClass(\SqlFixture\Platform\MySql\Value\NumericGenerator::class)]
63#[UsesClass(\SqlFixture\Platform\MySql\Value\SpatialGenerator::class)]
64#[UsesClass(\SqlFixture\Platform\MySql\Value\StringGenerator::class)]
65#[UsesClass(\SqlFixture\Platform\MySql\Value\TextGenerator::class)]
66#[UsesClass(\SqlFixture\Platform\PostgreSql\Schema\CatalogColumn::class)]
67#[UsesClass(\SqlFixture\Platform\PostgreSql\Schema\CatalogDdl::class)]
68#[UsesClass(\SqlFixture\Platform\PostgreSql\Schema\CatalogQuery::class)]
69#[UsesClass(\SqlFixture\Platform\PostgreSql\Schema\CatalogSchema::class)]
70#[UsesClass(\SqlFixture\Platform\PostgreSql\Schema\ColumnParser::class)]
71#[UsesClass(\SqlFixture\Platform\PostgreSql\Schema\DefaultExpression::class)]
72#[UsesClass(\SqlFixture\Platform\PostgreSql\Schema\DefinitionList::class)]
73#[UsesClass(\SqlFixture\Platform\PostgreSql\Schema\TableSyntax::class)]
74#[UsesClass(\SqlFixture\Platform\PostgreSql\Schema\TypeDeclaration::class)]
75#[UsesClass(\SqlFixture\Platform\PostgreSql\Value\ColumnGenerator::class)]
76#[UsesClass(\SqlFixture\Platform\PostgreSql\Value\DecimalGenerator::class)]
77#[UsesClass(\SqlFixture\Platform\PostgreSql\Value\NumericGenerator::class)]
78#[UsesClass(\SqlFixture\Platform\PostgreSql\Value\StringGenerator::class)]
79#[UsesClass(\SqlFixture\Platform\PostgreSql\Value\StructuredGenerator::class)]
80#[UsesClass(\SqlFixture\Platform\PostgreSql\Value\TemporalGenerator::class)]
81#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\ColumnParser::class)]
82#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\CreateTableQuery::class)]
83#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\DefaultExpression::class)]
84#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\DefinitionList::class)]
85#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\PragmaColumn::class)]
86#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\PragmaSchema::class)]
87#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\TableSyntax::class)]
88#[UsesClass(\SqlFixture\Platform\Sqlite\Schema\TypeDeclaration::class)]
89#[UsesClass(\SqlFixture\Platform\Sqlite\Value\ColumnGenerator::class)]
90#[UsesClass(\SqlFixture\Platform\Sqlite\Value\TypeAffinity::class)]
91#[UsesClass(\SqlFixture\Schema\DefinitionSegments::class)]
92#[UsesClass(\SqlFixture\Schema\TypeShape::class)]
93#[UsesClass(\SqlFixture\TypeMapper\ParagraphGenerator::class)]
94#[UsesClass(\SqlFixture\Platform\MySql\Schema\TableDefinitionInput::class)]
95#[UsesClass(\SqlFixture\Hydrator\Exception\ClassNotFoundException::class)]
96#[UsesClass(\SqlFixture\Hydrator\Exception\MissingConstructorArgumentException::class)]
97#[UsesClass(\SqlFixture\Fixture\Exception\UnknownOverrideColumnException::class)]
98#[UsesClass(\SqlFixture\Fixture\Exception\NullOverrideException::class)]
99#[UsesClass(\SqlFixture\Fixture\Exception\GeneratedColumnOverrideException::class)]
100#[UsesClass(\SqlFixture\Schema\Exception\InvalidSqlException::class)]
101#[UsesClass(\SqlFixture\Schema\Exception\ExpectedCreateTableException::class)]
102#[UsesClass(\SqlFixture\Schema\Exception\MissingColumnDefinitionsException::class)]
103#[UsesClass(\SqlFixture\TypeMapper\IntegerRange::class)]
104#[UsesClass(\SqlFixture\TypeMapper\IntegerWidth::class)]
105#[UsesClass(\SqlFixture\TypeMapper\DecimalRange::class)]
106#[UsesClass(\SqlFixture\Hydrator\Reflection\ConversionTarget::class)]
107final class DatabaseFixtureProviderTest extends TestCase
108{
109 #[Test]
110 public function testFixtureGeneratesArrayFromSqliteTable(): void
111 {
112 $pdo = new PDO('sqlite::memory:');
113 $pdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT)');
114
115 $faker = Factory::create();
116 $provider = new DatabaseFixtureProvider($faker, $pdo);
117
118 $result = $provider->fixture('users');
119 self::assertArrayHasKey('name', $result);
120 }
121
122 #[Test]
123 public function testClearCacheAllowsRefetch(): void
124 {
125 $pdo = new PDO('sqlite::memory:');
126 $pdo->exec('CREATE TABLE items (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT)');
127
128 $faker = Factory::create();
129 $provider = new DatabaseFixtureProvider($faker, $pdo);
130
131 $provider->fixture('items');
132 $provider->clearCache();
133 $result = $provider->fixture('items');
134 self::assertArrayHasKey('title', $result);
135 }
136
137 #[Test]
138 public function testGetDriverReturnsSqlite(): void
139 {
140 $pdo = new PDO('sqlite::memory:');
141 $faker = Factory::create();
142 $provider = new DatabaseFixtureProvider($faker, $pdo);
143
144 self::assertSame('sqlite', $provider->getDriver());
145 }
146
147 #[Test]
148 public function testGetFixtureGeneratorReturnsInstance(): void
149 {
150 $pdo = new PDO('sqlite::memory:');
151 $faker = Factory::create();
152 $provider = new DatabaseFixtureProvider($faker, $pdo);
153
154 self::assertSame(['id' => 7], $provider->getFixtureGenerator()->generate(new TableSchema('sample', ['id' => new ColumnDefinition('id', 'INT')]), ['id' => 7]));
155 }
156
157 #[Test]
158 public function testFixtureWithCustomTypeMapper(): void
159 {
160 $pdo = new PDO('sqlite::memory:');
161 $pdo->exec('CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT NOT NULL)');
162
163 $faker = Factory::create();
164 $typeMapper = new SqliteTypeMapper();
165 $provider = new DatabaseFixtureProvider($faker, $pdo, typeMapper: $typeMapper);
166
167 $data = $provider->fixture('test');
168 self::assertArrayHasKey('name', $data);
169 }
170
171 #[Test]
172 public function testFixtureWithCustomSchemaFetcher(): void
173 {
174 $pdo = new PDO('sqlite::memory:');
175 $pdo->exec('CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT NOT NULL)');
176
177 $faker = Factory::create();
178 $fetcher = new SqliteSchemaFetcher();
179 $provider = new DatabaseFixtureProvider($faker, $pdo, schemaFetcher: $fetcher);
180
181 $data = $provider->fixture('test');
182 self::assertArrayHasKey('name', $data);
183 }
184
185 #[Test]
186 public function testSchemaCacheWorksOnSecondCall(): void
187 {
188 $pdo = new PDO('sqlite::memory:');
189 $pdo->exec('CREATE TABLE items (id INTEGER PRIMARY KEY AUTOINCREMENT, val TEXT NOT NULL)');
190
191 $faker = Factory::create();
192 $provider = new DatabaseFixtureProvider($faker, $pdo);
193
194 $data1 = $provider->fixture('items');
195 $data2 = $provider->fixture('items');
196
197 self::assertArrayHasKey('val', $data1);
198 self::assertArrayHasKey('val', $data2);
199 }
200
201 #[Test]
202 public function testFixtureNormalizesQuotedTableNames(): void
203 {
204 $pdo = new PDO('sqlite::memory:');
205 $pdo->exec('CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT NOT NULL)');
206
207 $faker = Factory::create();
208 $provider = new DatabaseFixtureProvider($faker, $pdo);
209
210 $data = $provider->fixture('products');
211 self::assertArrayHasKey('name', $data);
212 }
213
214 #[Test]
215 public function testFixtureWithOverrides(): void
216 {
217 $pdo = new PDO('sqlite::memory:');
218 $pdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)');
219
220 $faker = Factory::create();
221 $provider = new DatabaseFixtureProvider($faker, $pdo);
222
223 $data = $provider->fixture('users', ['name' => 'Override']);
224 self::assertSame('Override', $data['name']);
225 }
226
227}
228