1<?php 2/** 3 * webtrees: online genealogy 4 * Copyright (C) 2019 webtrees development team 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16declare(strict_types=1); 17 18namespace Fisharebest\Webtrees; 19 20use Fisharebest\Webtrees\Contracts\UserInterface; 21use Fisharebest\Webtrees\Http\Controllers\GedcomFileController; 22use Fisharebest\Webtrees\Module\ModuleThemeInterface; 23use Fisharebest\Webtrees\Module\WebtreesTheme; 24use Fisharebest\Webtrees\Schema\SeedDatabase; 25use Fisharebest\Webtrees\Services\TimeoutService; 26use Fisharebest\Webtrees\Services\UserService; 27use Illuminate\Cache\ArrayStore; 28use Illuminate\Cache\Repository; 29use Illuminate\Database\Capsule\Manager as DB; 30use function basename; 31use Symfony\Component\HttpFoundation\Request; 32 33/** 34 * Base class for unit tests 35 */ 36class TestCase extends \PHPUnit\Framework\TestCase 37{ 38 protected static $uses_database = false; 39 40 /** 41 * Things to run once, before all the tests. 42 */ 43 public static function setUpBeforeClass() 44 { 45 parent::setUpBeforeClass(); 46 47 if (static::$uses_database) { 48 defined('WT_ROOT') || define('WT_ROOT', dirname(__DIR__) . '/'); 49 50 static::createTestDatabase(); 51 } 52 } 53 54 /** 55 * Things to run once, AFTER all the tests. 56 */ 57 public static function tearDownAfterClass() 58 { 59 if (static::$uses_database) { 60 $pdo = DB::connection()->getPdo(); 61 unset($pdo); 62 } 63 64 parent::tearDownAfterClass(); 65 } 66 67 /** 68 * Things to run before every test. 69 */ 70 protected function setUp() 71 { 72 parent::setUp(); 73 74 // Use an array cache for database calls, etc. 75 app()->instance('cache.array', new Repository(new ArrayStore())); 76 77 app()->bind(Tree::class, function () { 78 return null; 79 }); 80 81 app()->instance(UserService::class, new UserService()); 82 app()->instance(UserInterface::class, new GuestUser()); 83 84 app()->instance(Request::class, Request::createFromGlobals()); 85 86 app()->bind(ModuleThemeInterface::class, WebtreesTheme::class); 87 88 defined('WT_ROOT') || define('WT_ROOT', dirname(__DIR__) . '/'); 89 defined('WT_BASE_URL') || define('WT_BASE_URL', 'http://localhost/'); 90 defined('WT_DATA_DIR') || define('WT_DATA_DIR', WT_ROOT . 'data/'); 91 defined('WT_LOCALE') || define('WT_LOCALE', I18N::init('en-US')); 92 93 if (static::$uses_database) { 94 DB::connection()->beginTransaction(); 95 } 96 } 97 98 /** 99 * Things to run after every test 100 */ 101 protected function tearDown() 102 { 103 if (static::$uses_database) { 104 DB::connection()->rollBack(); 105 } 106 107 app('cache.array')->flush(); 108 109 Site::$preferences = []; 110 Tree::$trees = []; 111 GedcomRecord::$gedcom_record_cache = null; 112 GedcomRecord::$pending_record_cache = null; 113 114 Auth::logout(); 115 } 116 117 /** 118 * Create an SQLite in-memory database for testing 119 */ 120 protected static function createTestDatabase(): void 121 { 122 $capsule = new DB(); 123 $capsule->addConnection([ 124 'driver' => 'sqlite', 125 'database' => ':memory:', 126 ]); 127 $capsule->setAsGlobal(); 128 Database::registerMacros(); 129 130 // Create tables 131 Database::updateSchema('\Fisharebest\Webtrees\Schema', 'WT_SCHEMA_VERSION', Webtrees::SCHEMA_VERSION); 132 133 // Create config data 134 (new SeedDatabase())->run(); 135 } 136 137 /** 138 * Import a GEDCOM file into the test database. 139 * 140 * @param string $gedcom_file 141 * 142 * @return Tree 143 */ 144 protected function importTree(string $gedcom_file): Tree 145 { 146 $tree = Tree::create(basename($gedcom_file), basename($gedcom_file)); 147 $tree->importGedcomFile(__DIR__ . '/data/' . $gedcom_file, $gedcom_file); 148 149 View::share('tree', $tree); 150 $gedcom_file_controller = new GedcomFileController(); 151 152 do { 153 $gedcom_file_controller->import(new TimeoutService(microtime(true)), $tree); 154 155 $imported = $tree->getPreference('imported'); 156 } while (!$imported); 157 158 return $tree; 159 } 160} 161