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\Services\UserService; 21use function stream_get_contents; 22 23/** 24 * Test harness for the class Tree 25 */ 26class TreeTest extends TestCase 27{ 28 protected static $uses_database = true; 29 30 /** 31 * @covers \Fisharebest\Webtrees\Tree::__construct 32 * @covers \Fisharebest\Webtrees\Tree::create 33 * @covers \Fisharebest\Webtrees\Tree::id 34 * @covers \Fisharebest\Webtrees\Tree::name 35 * @covers \Fisharebest\Webtrees\Tree::title 36 * 37 * @return void 38 */ 39 public function testConstructor(): void 40 { 41 $tree = Tree::create('tree-name', 'Tree title'); 42 43 $this->assertSame(1, $tree->id()); 44 $this->assertSame('tree-name', $tree->name()); 45 $this->assertSame('Tree title', $tree->title()); 46 } 47 48 /** 49 * @covers \Fisharebest\Webtrees\Tree::getPreference 50 * @covers \Fisharebest\Webtrees\Tree::setPreference 51 * 52 * @return void 53 */ 54 public function testTreePreferences(): void 55 { 56 $tree = Tree::create('tree-name', 'Tree title'); 57 58 $pref = $tree->getPreference('foo', 'default'); 59 $this->assertSame('default', $pref); 60 61 $tree->setPreference('foo', 'bar'); 62 $pref = $tree->getPreference('foo', 'default'); 63 $this->assertSame('bar', $pref); 64 } 65 66 /** 67 * @covers \Fisharebest\Webtrees\Tree::getUserPreference 68 * @covers \Fisharebest\Webtrees\Tree::setUserPreference 69 * 70 * @return void 71 */ 72 public function testUserTreePreferences(): void 73 { 74 $user_service = new UserService(); 75 $tree = Tree::create('tree-name', 'Tree title'); 76 $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 77 78 $pref = $tree->getUserPreference($user, 'foo', 'default'); 79 $this->assertSame('default', $pref); 80 81 $tree->setUserPreference($user, 'foo', 'bar'); 82 $pref = $tree->getUserPreference($user, 'foo', 'default'); 83 $this->assertSame('bar', $pref); 84 } 85 86 /** 87 * @covers \Fisharebest\Webtrees\Tree::getNewXref 88 * 89 * @return void 90 */ 91 public function testGetNewXref(): void 92 { 93 $tree = Tree::create('tree-name', 'Tree title'); 94 95 $this->assertSame('X1', $tree->getNewXref()); 96 $this->assertSame('X2', $tree->getNewXref()); 97 $this->assertSame('X3', $tree->getNewXref()); 98 $this->assertSame('X4', $tree->getNewXref()); 99 $this->assertSame('X5', $tree->getNewXref()); 100 } 101 102 /** 103 * @covers \Fisharebest\Webtrees\Tree::createIndividual 104 * @expectedException \InvalidArgumentException 105 * 106 * @return void 107 */ 108 public function testCreateInvalidIndividual(): void 109 { 110 $user_service = new UserService(); 111 $tree = Tree::create('tree-name', 'Tree title'); 112 $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 113 $user->setPreference('canadmin', '1'); 114 Auth::login($user); 115 116 $tree->createIndividual("0 @@ FOO\n1 SEX U"); 117 } 118 119 /** 120 * @covers \Fisharebest\Webtrees\Tree::createIndividual 121 * 122 * @return void 123 */ 124 public function testCreateIndividual(): void 125 { 126 $user_service = new UserService(); 127 $tree = Tree::create('tree-name', 'Tree title'); 128 $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 129 $user->setPreference('canadmin', '1'); 130 Auth::login($user); 131 132 $record = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 133 $this->assertTrue($record->isPendingAddition()); 134 135 $user->setPreference('auto_accept', '1'); 136 $record = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 137 $this->assertFalse($record->isPendingAddition()); 138 } 139 140 /** 141 * @covers \Fisharebest\Webtrees\Tree::createFamily 142 * @expectedException \InvalidArgumentException 143 * 144 * @return void 145 */ 146 public function testCreateInvalidFamily(): void 147 { 148 $user_service = new UserService(); 149 $tree = Tree::create('tree-name', 'Tree title'); 150 $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 151 $user->setPreference('canadmin', '1'); 152 Auth::login($user); 153 154 $tree->createFamily("0 @@ FOO\n1 MARR Y"); 155 } 156 157 /** 158 * @covers \Fisharebest\Webtrees\Tree::createFamily 159 * 160 * @return void 161 */ 162 public function testCreateFamily(): void 163 { 164 $user_service = new UserService(); 165 $tree = Tree::create('tree-name', 'Tree title'); 166 $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 167 $user->setPreference('canadmin', '1'); 168 Auth::login($user); 169 170 $record = $tree->createFamily("0 @@ FAM\n1 MARR Y"); 171 $this->assertTrue($record->isPendingAddition()); 172 173 $user->setPreference('auto_accept', '1'); 174 $record = $tree->createFamily("0 @@ FAM\n1 MARR Y"); 175 $this->assertFalse($record->isPendingAddition()); 176 } 177 178 /** 179 * @covers \Fisharebest\Webtrees\Tree::createMediaObject 180 * @expectedException \InvalidArgumentException 181 * 182 * @return void 183 */ 184 public function testCreateInvalidMediaObject(): void 185 { 186 $user_service = new UserService(); 187 $tree = Tree::create('tree-name', 'Tree title'); 188 $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 189 $user->setPreference('canadmin', '1'); 190 Auth::login($user); 191 192 $tree->createMediaObject("0 @@ FOO\n1 MARR Y"); 193 } 194 195 /** 196 * @covers \Fisharebest\Webtrees\Tree::createMediaObject 197 * 198 * @return void 199 */ 200 public function testCreateMediaObject(): void 201 { 202 $user_service = new UserService(); 203 $tree = Tree::create('tree-name', 'Tree title'); 204 $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 205 $user->setPreference('canadmin', '1'); 206 Auth::login($user); 207 208 $record = $tree->createMediaObject("0 @@ OBJE\n1 FILE foo.jpeg"); 209 $this->assertTrue($record->isPendingAddition()); 210 211 $user->setPreference('auto_accept', '1'); 212 $record = $tree->createMediaObject("0 @@ OBJE\n1 FILE foo.jpeg"); 213 $this->assertFalse($record->isPendingAddition()); 214 } 215 216 /** 217 * @covers \Fisharebest\Webtrees\Tree::createRecord 218 * @expectedException \InvalidArgumentException 219 * 220 * @return void 221 */ 222 public function testCreateInvalidRecord(): void 223 { 224 $user_service = new UserService(); 225 $tree = Tree::create('tree-name', 'Tree title'); 226 $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 227 $user->setPreference('canadmin', '1'); 228 Auth::login($user); 229 230 $tree->createRecord("0 @@FOO\n1 NOTE noted"); 231 } 232 233 /** 234 * @covers \Fisharebest\Webtrees\Tree::createRecord 235 * 236 * @return void 237 */ 238 public function testCreateRecord(): void 239 { 240 $user_service = new UserService(); 241 $tree = Tree::create('tree-name', 'Tree title'); 242 $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 243 $user->setPreference('canadmin', '1'); 244 Auth::login($user); 245 246 $record = $tree->createRecord("0 @@ FOO\n1 NOTE noted"); 247 $this->assertTrue($record->isPendingAddition()); 248 249 $user->setPreference('auto_accept', '1'); 250 $record = $tree->createRecord("0 @@ FOO\n1 NOTE noted"); 251 $this->assertFalse($record->isPendingAddition()); 252 } 253 254 /** 255 * @covers \Fisharebest\Webtrees\Tree::significantIndividual 256 * 257 * @return void 258 */ 259 public function testSignificantIndividual(): void 260 { 261 $user_service = new UserService(); 262 $tree = Tree::create('tree-name', 'Tree title'); 263 $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 264 $user->setPreference('auto_accept', '1'); 265 Auth::login($user); 266 267 // No individuals in tree? Dummy individual 268 $this->assertSame('I', $tree->significantIndividual($user)->xref()); 269 270 $record1 = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 271 $record2 = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 272 $record3 = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 273 $record4 = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 274 275 // Individuals exist? First one (lowest XREF). 276 $this->assertSame($record1->xref(), $tree->significantIndividual($user)->xref()); 277 278 // Preference for tree? 279 $tree->setPreference('PEDIGREE_ROOT_ID', $record2->xref()); 280 $this->assertSame($record2->xref(), $tree->significantIndividual($user)->xref()); 281 282 // User preference 283 $tree->setUserPreference($user, 'gedcomid', $record3->xref()); 284 $this->assertSame($record3->xref(), $tree->significantIndividual($user)->xref()); 285 286 // User record 287 $tree->setUserPreference($user, 'rootid', $record4->xref()); 288 $this->assertSame($record4->xref(), $tree->significantIndividual($user)->xref()); 289 } 290 291 /** 292 * @covers \Fisharebest\Webtrees\Tree::importGedcomFile 293 * @covers \Fisharebest\Webtrees\Tree::deleteGenealogyData 294 * @covers \Fisharebest\Webtrees\Tree::delete 295 * 296 * @return void 297 */ 298 public function testImportAndDeleteGedcomFile(): void 299 { 300 $tree = $this->importTree('demo.ged'); 301 $this->assertNotNull(Tree::findByName('demo.ged')); 302 Site::setPreference('DEFAULT_GEDCOM', $tree->name()); 303 304 $tree->delete(); 305 306 $this->assertNull(Tree::findByName('demo.ged')); 307 $this->assertSame('', Site::getPreference('DEFAULT_GEDCOM')); 308 } 309 310 /** 311 * @covers \Fisharebest\Webtrees\Tree::hasPendingEdit 312 * 313 * @return void 314 */ 315 public function testHasPendingEdits(): void 316 { 317 $user_service = new UserService(); 318 $tree = $this->importTree('demo.ged'); 319 $user = $user_service->create('admin', 'Administrator', 'admin@example.com', 'secret'); 320 $user->setPreference('canadmin', '1'); 321 Auth::login($user); 322 323 $user->setPreference('auto_accept', '1'); 324 $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 325 $this->assertFalse($tree->hasPendingEdit()); 326 327 $user->setPreference('auto_accept', '0'); 328 $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 329 $this->assertTrue($tree->hasPendingEdit()); 330 } 331 332 /** 333 * @covers \Fisharebest\Webtrees\Tree::exportGedcom 334 * 335 * @return void 336 */ 337 public function testExportGedcom(): void 338 { 339 $tree = $this->importTree('demo.ged'); 340 341 $fp = fopen('php://memory', 'wb'); 342 343 $tree->exportGedcom($fp); 344 345 rewind($fp); 346 347 $original = file_get_contents(__DIR__ . '/../data/demo.ged'); 348 $export = stream_get_contents($fp); 349 350 // The date and time in the HEAD record will be different. 351 $original = preg_replace('/\n1 DATE .. ... ..../', '', $original, 1); 352 $export = preg_replace('/\n1 DATE .. ... ..../', '', $export, 1); 353 $original = preg_replace('/\n2 TIME ..:..:../', '', $original, 1); 354 $export = preg_replace('/\n2 TIME ..:..:../', '', $export, 1); 355 356 $this->assertSame($original, $export); 357 } 358} 359