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