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