TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
FunctionalTestCase.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Tests;
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 
23 
54 abstract class FunctionalTestCase extends BaseTestCase
55 {
62  protected $identifier;
63 
70  protected $instancePath;
71 
89  protected $coreExtensionsToLoad = [];
90 
111  protected $testExtensionsToLoad = [];
112 
142 
150 
176 
182  protected $backendUserFixture = 'typo3/sysext/core/Tests/Functional/Fixtures/be_users.xml';
183 
191  protected function setUp()
192  {
193  if (!defined('ORIGINAL_ROOT')) {
194  $this->markTestSkipped('Functional tests must be called through phpunit on CLI');
195  }
196 
197  // Use a 7 char long hash of class name as identifier
198  $this->identifier = substr(sha1(get_class($this)), 0, 7);
199  $this->instancePath = ORIGINAL_ROOT . 'typo3temp/var/tests/functional-' . $this->identifier;
200 
201  $testbase = new Testbase();
202  $testbase->defineTypo3ModeBe();
203  $testbase->setTypo3TestingContext();
204  if ($testbase->recentTestInstanceExists($this->instancePath)) {
205  // Reusing an existing instance. This typically happens for the second, third, ... test
206  // in a test case, so environment is set up only once per test case.
207  $testbase->setUpBasicTypo3Bootstrap($this->instancePath);
208  $testbase->initializeTestDatabaseAndTruncateTables();
209  $testbase->loadExtensionTables();
210  } else {
211  $testbase->removeOldInstanceIfExists($this->instancePath);
212  // Basic instance directory structure
213  $testbase->createDirectory($this->instancePath . '/fileadmin');
214  $testbase->createDirectory($this->instancePath . '/typo3temp/var/transient');
215  $testbase->createDirectory($this->instancePath . '/typo3temp/assets');
216  $testbase->createDirectory($this->instancePath . '/typo3conf/ext');
217  $testbase->createDirectory($this->instancePath . '/uploads');
218  // Additionally requested directories
219  foreach ($this->additionalFoldersToCreate as $directory) {
220  $testbase->createDirectory($this->instancePath . '/' . $directory);
221  }
222  $testbase->createLastRunTextfile($this->instancePath);
223  $testbase->setUpInstanceCoreLinks($this->instancePath);
224  $testbase->linkTestExtensionsToInstance($this->instancePath, $this->testExtensionsToLoad);
225  $testbase->linkPathsInTestInstance($this->instancePath, $this->pathsToLinkInTestInstance);
226  $localConfiguration['DB'] = $testbase->getOriginalDatabaseSettingsFromEnvironmentOrLocalConfiguration();
227  $originalDatabaseName = $localConfiguration['DB']['Connections']['Default']['dbname'];
228  // Append the unique identifier to the base database name to end up with a single database per test case
229  $localConfiguration['DB']['Connections']['Default']['dbname'] = $originalDatabaseName . '_ft' . $this->identifier;
230  $testbase->testDatabaseNameIsNotTooLong($originalDatabaseName, $localConfiguration);
231  // Set some hard coded base settings for the instance. Those could be overruled by
232  // $this->configurationToUseInTestInstance if needed again.
233  $localConfiguration['SYS']['isInitialInstallationInProgress'] = false;
234  $localConfiguration['SYS']['isInitialDatabaseImportDone'] = true;
235  $localConfiguration['SYS']['displayErrors'] = '1';
236  $localConfiguration['SYS']['debugExceptionHandler'] = '';
237  $localConfiguration['SYS']['trustedHostsPattern'] = '.*';
238  // @todo: This should be moved over to DB/Connections/Default/initCommands
239  $localConfiguration['SYS']['setDBinit'] = 'SET SESSION sql_mode = \'STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_VALUE_ON_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY\';';
240  $localConfiguration['SYS']['caching']['cacheConfigurations']['extbase_object']['backend'] = NullBackend::class;
241  $testbase->setUpLocalConfiguration($this->instancePath, $localConfiguration, $this->configurationToUseInTestInstance);
242  $defaultCoreExtensionsToLoad = [
243  'core',
244  'backend',
245  'frontend',
246  'lang',
247  'extbase',
248  'install',
249  ];
250  $testbase->setUpPackageStates($this->instancePath, $defaultCoreExtensionsToLoad, $this->coreExtensionsToLoad, $this->testExtensionsToLoad);
251  $testbase->setUpBasicTypo3Bootstrap($this->instancePath);
252  $testbase->setUpTestDatabase($localConfiguration['DB']['Connections']['Default']['dbname'], $originalDatabaseName);
253  $testbase->loadExtensionTables();
254  $testbase->createDatabaseStructure();
255  }
256  }
257 
267  protected function getDatabaseConnection()
268  {
270  return $GLOBALS['TYPO3_DB'];
271  }
272 
276  protected function getConnectionPool()
277  {
278  return GeneralUtility::makeInstance(ConnectionPool::class);
279  }
280 
288  protected function setUpBackendUserFromFixture($userUid)
289  {
290  $this->importDataSet(ORIGINAL_ROOT . $this->backendUserFixture);
291 
292  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
293  $queryBuilder->getRestrictions()->removeAll();
294 
295  $userRow = $queryBuilder->select('*')
296  ->from('be_users')
297  ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($userUid, \PDO::PARAM_INT)))
298  ->execute()
299  ->fetch();
300 
302  $backendUser = GeneralUtility::makeInstance(BackendUserAuthentication::class);
303  $sessionId = $backendUser->createSessionId();
304  $_COOKIE['be_typo_user'] = $sessionId;
305  $backendUser->id = $sessionId;
306  $backendUser->sendNoCacheHeaders = false;
307  $backendUser->dontSetCookie = true;
308  $backendUser->createUserSession($userRow);
309 
310  $GLOBALS['BE_USER'] = $backendUser;
311  $GLOBALS['BE_USER']->start();
312  if (!is_array($GLOBALS['BE_USER']->user) || !$GLOBALS['BE_USER']->user['uid']) {
313  throw new Exception(
314  'Can not initialize backend user',
315  1377095807
316  );
317  }
318  $GLOBALS['BE_USER']->backendCheckLogin();
319 
320  return $backendUser;
321  }
322 
330  protected function importDataSet($path)
331  {
332  $testbase = new Testbase();
333  $testbase->importXmlDatabaseFixture($path);
334  }
335 
340  protected function setUpFrontendRootPage($pageId, array $typoScriptFiles = [])
341  {
342  $pageId = (int)$pageId;
343 
344  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('pages');
345  $page = $connection->select(['*'], 'pages', ['uid' => $pageId])->fetch();
346 
347  if (empty($page)) {
348  $this->fail('Cannot set up frontend root page "' . $pageId . '"');
349  }
350 
351  $connection->update(
352  'pages',
353  ['is_siteroot' => 1],
354  ['uid' => $pageId]
355  );
356 
357  $templateFields = [
358  'pid' => $pageId,
359  'title' => '',
360  'config' => '',
361  'clear' => 3,
362  'root' => 1,
363  ];
364 
365  foreach ($typoScriptFiles as $typoScriptFile) {
366  $templateFields['config'] .= '<INCLUDE_TYPOSCRIPT: source="FILE:' . $typoScriptFile . '">' . LF;
367  }
368 
369  GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('sys_template')->insert(
370  'sys_template',
371  $templateFields
372  );
373  }
374 
384  protected function getFrontendResponse($pageId, $languageId = 0, $backendUserId = 0, $workspaceId = 0, $failOnFailure = true, $frontendUserId = 0)
385  {
386  $pageId = (int)$pageId;
387  $languageId = (int)$languageId;
388 
389  $additionalParameter = '';
390 
391  if (!empty($frontendUserId)) {
392  $additionalParameter .= '&frontendUserId=' . (int)$frontendUserId;
393  }
394  if (!empty($backendUserId)) {
395  $additionalParameter .= '&backendUserId=' . (int)$backendUserId;
396  }
397  if (!empty($workspaceId)) {
398  $additionalParameter .= '&workspaceId=' . (int)$workspaceId;
399  }
400 
401  $arguments = [
402  'documentRoot' => $this->instancePath,
403  'requestUrl' => 'http://localhost/?id=' . $pageId . '&L=' . $languageId . $additionalParameter,
404  ];
405 
406  $template = new \Text_Template(ORIGINAL_ROOT . 'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/request.tpl');
407  $template->setVar(
408  [
409  'arguments' => var_export($arguments, true),
410  'originalRoot' => ORIGINAL_ROOT,
411  ]
412  );
413 
414  $php = \PHPUnit_Util_PHP::factory();
415  $response = $php->runJob($template->render());
416  $result = json_decode($response['stdout'], true);
417 
418  if ($result === null) {
419  $this->fail('Frontend Response is empty');
420  }
421 
422  if ($failOnFailure && $result['status'] === Response::STATUS_Failure) {
423  $this->fail('Frontend Response has failure:' . LF . $result['error']);
424  }
425 
426  $response = new Response($result['status'], $result['content'], $result['error']);
427  return $response;
428  }
429 }
setUpFrontendRootPage($pageId, array $typoScriptFiles=[])
getFrontendResponse($pageId, $languageId=0, $backendUserId=0, $workspaceId=0, $failOnFailure=true, $frontendUserId=0)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)