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