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