[TASK] mssql: A series of functional test fixes
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Functional / Category / Collection / CategoryCollectionTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Functional\Category\Collection;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Doctrine\DBAL\Schema\Column;
18 use Doctrine\DBAL\Schema\TableDiff;
19 use Doctrine\DBAL\Types\Type;
20 use TYPO3\CMS\Core\Category\Collection\CategoryCollection;
21 use TYPO3\CMS\Core\Database\Connection;
22 use TYPO3\CMS\Core\Database\ConnectionPool;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24
25 /**
26 * Test case for \TYPO3\CMS\Core\Category\Collection\CategoryCollection
27 */
28 class CategoryCollectionTest extends \TYPO3\TestingFramework\Core\Functional\FunctionalTestCase
29 {
30 /**
31 * @var CategoryCollection
32 */
33 private $subject;
34
35 /**
36 * @var string
37 */
38 private $tableName = 'tx_foo_5001615c50bed';
39
40 /**
41 * @var array
42 */
43 private $tables = ['sys_category', 'sys_category_record_mm'];
44
45 /**
46 * @var int
47 */
48 private $categoryUid = 0;
49
50 /**
51 * @var array
52 */
53 private $collectionRecord = [];
54
55 /**
56 * @var int
57 */
58 private $numberOfRecords = 5;
59
60 /**
61 * Sets up this test suite.
62 */
63 protected function setUp()
64 {
65 parent::setUp();
66 $this->subject = GeneralUtility::makeInstance(CategoryCollection::class, $this->tableName);
67 $this->collectionRecord = [
68 'uid' => 0,
69 'title' => $this->getUniqueId('title'),
70 'description' => $this->getUniqueId('description'),
71 'table_name' => $this->tableName,
72 ];
73 $GLOBALS['TCA'][$this->tableName] = ['ctrl' => []];
74 // prepare environment
75 $this->createDummyTable();
76 $this->populateDummyTable();
77 $this->prepareTables();
78 $this->makeRelationBetweenCategoryAndDummyTable();
79 }
80
81 /**
82 * Tears down this test suite.
83 */
84 protected function tearDown()
85 {
86 $this->purgePreparedTables();
87 $this->dropDummyTable();
88 parent::tearDown();
89 }
90
91 /**
92 * @test
93 * @covers \TYPO3\CMS\Core\Category\Collection\CategoryCollection::fromArray
94 */
95 public function checkIfFromArrayMethodSetCorrectProperties()
96 {
97 $this->subject->fromArray($this->collectionRecord);
98 $this->assertEquals($this->collectionRecord['uid'], $this->subject->getIdentifier());
99 $this->assertEquals($this->collectionRecord['uid'], $this->subject->getUid());
100 $this->assertEquals($this->collectionRecord['title'], $this->subject->getTitle());
101 $this->assertEquals($this->collectionRecord['description'], $this->subject->getDescription());
102 $this->assertEquals($this->collectionRecord['table_name'], $this->subject->getItemTableName());
103 }
104
105 /**
106 * @test
107 * @covers \TYPO3\CMS\Core\Category\Collection\CategoryCollection::create
108 */
109 public function canCreateDummyCollection()
110 {
111 $collection = CategoryCollection::create($this->collectionRecord);
112 $this->assertInstanceOf(CategoryCollection::class, $collection);
113 }
114
115 /**
116 * @test
117 * @covers \TYPO3\CMS\Core\Category\Collection\CategoryCollection::create
118 */
119 public function canCreateDummyCollectionAndFillItems()
120 {
121 $collection = CategoryCollection::create($this->collectionRecord, true);
122 $this->assertInstanceOf(CategoryCollection::class, $collection);
123 }
124
125 /**
126 * @test
127 * @covers \TYPO3\CMS\Core\Category\Collection\CategoryCollection::getCollectedRecords
128 */
129 public function getCollectedRecordsReturnsEmptyRecordSet()
130 {
131 $method = new \ReflectionMethod(CategoryCollection::class, 'getCollectedRecords');
132 $method->setAccessible(true);
133 $records = $method->invoke($this->subject);
134 $this->assertInternalType('array', $records);
135 $this->assertEmpty($records);
136 }
137
138 /**
139 * @test
140 * @covers \TYPO3\CMS\Core\Category\Collection\CategoryCollection::getStorageTableName
141 */
142 public function isStorageTableNameEqualsToSysCategory()
143 {
144 $this->assertEquals('sys_category', CategoryCollection::getStorageTableName());
145 }
146
147 /**
148 * @test
149 * @covers \TYPO3\CMS\Core\Category\Collection\CategoryCollection::getStorageItemsField
150 */
151 public function isStorageItemsFieldEqualsToItems()
152 {
153 $this->assertEquals('items', CategoryCollection::getStorageItemsField());
154 }
155
156 /**
157 * @test
158 */
159 public function canLoadADummyCollectionFromDatabase()
160 {
161 /** @var $collection CategoryCollection */
162 $collection = CategoryCollection::load($this->categoryUid, true, $this->tableName);
163 // Check the number of record
164 $this->assertEquals($this->numberOfRecords, $collection->count());
165 // Check that the first record is the one expected
166 $queryBuilder = $this->getConnectionPool()
167 ->getQueryBuilderForTable($this->tableName);
168 $queryBuilder->getRestrictions()->removeAll();
169 $statement = $queryBuilder
170 ->select('*')
171 ->from($this->tableName)
172 ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)))
173 ->execute();
174 $record = $statement->fetch();
175 $collection->rewind();
176 $this->assertEquals($record, $collection->current());
177 // Add a new record
178 $fakeRecord = [
179 'uid' => $this->numberOfRecords + 1,
180 'pid' => 0,
181 'title' => $this->getUniqueId('title'),
182 'categories' => 0
183 ];
184 // Check the number of records
185 $collection->add($fakeRecord);
186 $this->assertEquals($this->numberOfRecords + 1, $collection->count());
187 }
188
189 /**
190 * @test
191 */
192 public function canLoadADummyCollectionFromDatabaseAndAddRecord()
193 {
194 $collection = CategoryCollection::load($this->categoryUid, true, $this->tableName);
195 // Add a new record
196 $fakeRecord = [
197 'uid' => $this->numberOfRecords + 1,
198 'pid' => 0,
199 'title' => $this->getUniqueId('title'),
200 'categories' => 0
201 ];
202 // Check the number of records
203 $collection->add($fakeRecord);
204 $this->assertEquals($this->numberOfRecords + 1, $collection->count());
205 }
206
207 /**
208 * @test
209 */
210 public function canLoadADummyCollectionWithoutContentFromDatabase()
211 {
212 /** @var $collection CategoryCollection */
213 $collection = CategoryCollection::load($this->categoryUid, false, $this->tableName);
214 // Check the number of record
215 $this->assertEquals(0, $collection->count());
216 }
217
218 /**
219 * @test
220 */
221 public function canLoadADummyCollectionFromDatabaseAfterRemoveOneRelation()
222 {
223 // Remove one relation
224 $fakeName = [
225 'tablenames' => $this->getUniqueId('name')
226 ];
227 $this->getConnectionPool()
228 ->getConnectionForTable('sys_category_record_mm')
229 ->update('sys_category_record_mm', $fakeName, ['uid_foreign' => 1]);
230 // Check the number of records
231 $collection = CategoryCollection::load($this->categoryUid, true, $this->tableName);
232 $this->assertEquals($this->numberOfRecords - 1, $collection->count());
233 }
234
235 /********************/
236 /* INTERNAL METHODS */
237 /********************/
238 /**
239 * Create dummy table for testing purpose
240 */
241 private function populateDummyTable()
242 {
243 for ($index = 1; $index <= $this->numberOfRecords; $index++) {
244 $values = [
245 'title' => $this->getUniqueId('title')
246 ];
247 $this->getConnectionPool()
248 ->getConnectionForTable($this->tableName)
249 ->insert($this->tableName, $values);
250 }
251 }
252
253 /**
254 * Make relation between tables
255 */
256 private function makeRelationBetweenCategoryAndDummyTable()
257 {
258 for ($index = 1; $index <= $this->numberOfRecords; $index++) {
259 $values = [
260 'uid_local' => $this->categoryUid,
261 'uid_foreign' => $index,
262 'tablenames' => $this->tableName,
263 'fieldname' => 'categories'
264 ];
265 $this->getConnectionPool()
266 ->getConnectionForTable('sys_category_record_mm')
267 ->insert('sys_category_record_mm', $values);
268 }
269 }
270
271 /**
272 * Create dummy table for testing purpose
273 */
274 private function createDummyTable()
275 {
276 $connection = $this->getConnectionPool()
277 ->getConnectionForTable($this->tableName);
278 $currentSchema = $connection->getSchemaManager()->createSchema();
279 $targetSchema = clone $currentSchema;
280
281 $table = $targetSchema->createTable($this->tableName);
282 $table->addColumn('uid', Type::INTEGER, ['length' => 11, 'unsigned' => true, 'autoincrement' => true]);
283 $table->addColumn('pid', Type::INTEGER, ['length' => 11, 'notnull' => true, 'default' => 0]);
284 $table->addColumn('title', Type::STRING);
285 $table->addColumn('tcategories', Type::INTEGER, ['length' => 11, 'unsigned' => true, 'notnull' => true, 'default' => 0]);
286 $table->addColumn('sys_category_is_dummy_record', Type::INTEGER, ['length' => 11, 'unsigned' => true, 'notnull' => true, 'default' => 0]);
287 $table->setPrimaryKey(['uid']);
288
289 $queries = $currentSchema->getMigrateToSql($targetSchema, $connection->getDatabasePlatform());
290 foreach ($queries as $query) {
291 $connection->query($query);
292 }
293 }
294
295 /**
296 * Drop dummy table
297 */
298 private function dropDummyTable()
299 {
300 $connection = $this->getConnectionPool()
301 ->getConnectionForTable($this->tableName);
302 $currentSchema = $connection->getSchemaManager()->createSchema();
303 $targetSchema = clone $currentSchema;
304
305 $targetSchema->dropTable($this->tableName);
306
307 $queries = $currentSchema->getMigrateToSql($targetSchema, $connection->getDatabasePlatform());
308 foreach ($queries as $query) {
309 $connection->query($query);
310 }
311 }
312
313 /**
314 * Add is_dummy_record record and create dummy record
315 */
316 private function prepareTables()
317 {
318 $connection = $this->getConnectionPool()
319 ->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME);
320 $currentSchema = $connection->getSchemaManager()->createSchema();
321 $targetSchema = clone $currentSchema;
322
323 $columnOptions = ['length' => 1, 'unsigned' => true, 'notnull' => true, 'default' => 0];
324 foreach ($this->tables as $table) {
325 $targetSchema
326 ->getTable($table)
327 ->addColumn('is_dummy_record', Type::SMALLINT, $columnOptions);
328 }
329
330 $queries = $currentSchema->getMigrateToSql($targetSchema, $connection->getDatabasePlatform());
331 foreach ($queries as $query) {
332 $connection->query($query);
333 }
334
335 $values = [
336 'title' => $this->getUniqueId('title'),
337 'l10n_diffsource' => '',
338 'description' => '',
339 'is_dummy_record' => 1
340 ];
341
342 $connection->insert('sys_category', $values, [ 'l10n_diffsource' => Connection::PARAM_LOB ]);
343 $this->categoryUid = $connection->lastInsertId('sys_category');
344 }
345
346 /**
347 * Drops previously added dummy columns from core tables.
348 *
349 * @throws \Doctrine\DBAL\DBALException
350 * @throws \Doctrine\DBAL\Schema\SchemaException
351 * @see prepareTables()
352 */
353 private function purgePreparedTables()
354 {
355 $connection = $this->getConnectionPool()
356 ->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME);
357
358 foreach ($this->tables as $table) {
359 $diff = new TableDiff(
360 $table,
361 [],
362 [],
363 [
364 'is_dummy_record' => new Column('is_dummy_record', Type::getType(Type::SMALLINT))
365 ]
366 );
367 $connection->getSchemaManager()->alterTable($diff);
368 }
369 }
370 }