xref: /webtrees/tests/feature/IndividualListTest.php (revision 202c018b592d5a516e4a465dc6dc515f3be37399)
1e9e85398SGreg Roach<?php
23976b470SGreg Roach
3e9e85398SGreg Roach/**
4e9e85398SGreg Roach * webtrees: online genealogy
5d11be702SGreg Roach * Copyright (C) 2023 webtrees development team
6e9e85398SGreg Roach * This program is free software: you can redistribute it and/or modify
7e9e85398SGreg Roach * it under the terms of the GNU General Public License as published by
8e9e85398SGreg Roach * the Free Software Foundation, either version 3 of the License, or
9e9e85398SGreg Roach * (at your option) any later version.
10e9e85398SGreg Roach * This program is distributed in the hope that it will be useful,
11e9e85398SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
12e9e85398SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13e9e85398SGreg Roach * GNU General Public License for more details.
14e9e85398SGreg Roach * You should have received a copy of the GNU General Public License
1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>.
16e9e85398SGreg Roach */
17fcfa147eSGreg Roach
18e9e85398SGreg Roachdeclare(strict_types=1);
19e9e85398SGreg Roach
20e9e85398SGreg Roachnamespace Fisharebest\Webtrees;
21e9e85398SGreg Roach
2271378461SGreg Roachuse Fig\Http\Message\RequestMethodInterface;
2371378461SGreg Roachuse Fig\Http\Message\StatusCodeInterface;
247dcc0dd1SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface;
2587cca37cSGreg Roachuse Fisharebest\Webtrees\Module\IndividualListModule;
267dcc0dd1SGreg Roachuse Fisharebest\Webtrees\Services\GedcomImportService;
277dcc0dd1SGreg Roachuse Fisharebest\Webtrees\Services\TreeService;
287dcc0dd1SGreg Roachuse Fisharebest\Webtrees\Services\UserService;
297dcc0dd1SGreg Roach
30*202c018bSGreg Roachuse PHPUnit\Framework\Attributes\CoversClass;
31*202c018bSGreg Roach
327dcc0dd1SGreg Roachuse function array_map;
337dcc0dd1SGreg Roachuse function preg_match_all;
34b9fc687eSGreg Roach
35*202c018bSGreg Roach#[CoversClass(IndividualListModule::class)]
36e5a6b4d4SGreg Roachclass IndividualListTest extends TestCase
37e9e85398SGreg Roach{
38cd94ca66SGreg Roach    protected static bool $uses_database = true;
39e9e85398SGreg Roach
407dcc0dd1SGreg Roach    private Tree $tree;
417dcc0dd1SGreg Roach    private User $user;
427dcc0dd1SGreg Roach
437dcc0dd1SGreg Roach    public function setUp(): void
447dcc0dd1SGreg Roach    {
45a26ec5edSGreg Roach        parent::setUp();
46a26ec5edSGreg Roach
477dcc0dd1SGreg Roach        I18N::init('en-US');
487dcc0dd1SGreg Roach
497dcc0dd1SGreg Roach        $user_service = new UserService();
507dcc0dd1SGreg Roach        $tree_service = new TreeService(new GedcomImportService());
517dcc0dd1SGreg Roach        $this->tree   = $tree_service->create('name', 'title');
527dcc0dd1SGreg Roach        $this->user   = $user_service->create('user', 'User', 'user@example.com', 'secret');
537dcc0dd1SGreg Roach        $this->user->setPreference(UserInterface::PREF_IS_ADMINISTRATOR, '1');
547dcc0dd1SGreg Roach        $this->user->setPreference(UserInterface::PREF_AUTO_ACCEPT_EDITS, '1');
557dcc0dd1SGreg Roach        Auth::login($this->user);
567dcc0dd1SGreg Roach        // The default "John Doe" individual will confuse the test results...
577dcc0dd1SGreg Roach        Registry::individualFactory()->make('X1', $this->tree)->deleteRecord();
587dcc0dd1SGreg Roach    }
597dcc0dd1SGreg Roach
607dcc0dd1SGreg Roach    public function testCollationOfInitials(): void
61e9e85398SGreg Roach    {
62a26ec5edSGreg Roach        $module = new IndividualListModule();
63a26ec5edSGreg Roach
647dcc0dd1SGreg Roach        $this->tree->createIndividual("0 @@ INDI\n1 NAME /Âaa/");
657dcc0dd1SGreg Roach        $this->tree->createIndividual("0 @@ INDI\n1 NAME /aaa/");
667dcc0dd1SGreg Roach        $this->tree->createIndividual("0 @@ INDI\n1 NAME /Ååå/");
677dcc0dd1SGreg Roach        $this->tree->createIndividual("0 @@ INDI\n1 NAME /æææ/");
687dcc0dd1SGreg Roach        $this->tree->createIndividual("0 @@ INDI\n1 NAME /Caa/");
697dcc0dd1SGreg Roach        $this->tree->createIndividual("0 @@ INDI\n1 NAME /Css/");
707dcc0dd1SGreg Roach        $this->tree->createIndividual("0 @@ INDI\n1 NAME /Dza/");
71b9fc687eSGreg Roach
727dcc0dd1SGreg Roach        I18N::init('en-US');
737dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, [], [], [], ['tree' => $this->tree]);
74a26ec5edSGreg Roach        $response = $module->handle($request);
757dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
767dcc0dd1SGreg Roach        preg_match_all('/%2Findividual-list&amp;alpha=([^"&]+)/', $html, $matches);
777dcc0dd1SGreg Roach        self::assertEquals(['A', 'C', 'D', 'Æ'], array_map(rawurldecode(...), $matches[1]));
78b9fc687eSGreg Roach
797dcc0dd1SGreg Roach        I18N::init('sv');
807dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, [], [], [], ['tree' => $this->tree]);
81a26ec5edSGreg Roach        $response = $module->handle($request);
827dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
837dcc0dd1SGreg Roach        preg_match_all('/%2Findividual-list&amp;alpha=([^"&]+)/', $html, $matches);
847dcc0dd1SGreg Roach        self::assertEquals(['A', 'C', 'D', 'Å', 'Æ'], array_map(rawurldecode(...), $matches[1]));
85b9fc687eSGreg Roach
867dcc0dd1SGreg Roach        I18N::init('hu');
877dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, [], [], [], ['tree' => $this->tree]);
88a26ec5edSGreg Roach        $response = $module->handle($request);
897dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
907dcc0dd1SGreg Roach        preg_match_all('/%2Findividual-list&amp;alpha=([^"&]+)/', $html, $matches);
917dcc0dd1SGreg Roach        self::assertEquals(['A', 'C', 'CS', 'DZ', 'Æ'], array_map(rawurldecode(...), $matches[1]));
927dcc0dd1SGreg Roach    }
93a67cd39fSGreg Roach
94a26ec5edSGreg Roach    public function xtestRedirectToCanonicalSurname(): void
957dcc0dd1SGreg Roach    {
96a26ec5edSGreg Roach        $module = new IndividualListModule();
97a26ec5edSGreg Roach
987dcc0dd1SGreg Roach        I18N::init('en-US');
99a26ec5edSGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'Muller'], [], [], ['tree' => $this->tree]);
100a26ec5edSGreg Roach        $response = $module->handle($request);
101a26ec5edSGreg Roach        self::assertSame(StatusCodeInterface::STATUS_MOVED_PERMANENTLY, $response->getStatusCode());
102a26ec5edSGreg Roach        self::assertStringContainsString('surname=MULLER', $response->getHeaderLine('Location'));
103a26ec5edSGreg Roach
1047dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'MÜLLER'], [], [], ['tree' => $this->tree]);
105a26ec5edSGreg Roach        $response = $module->handle($request);
1067dcc0dd1SGreg Roach        self::assertSame(StatusCodeInterface::STATUS_MOVED_PERMANENTLY, $response->getStatusCode());
1077dcc0dd1SGreg Roach        self::assertStringContainsString('surname=MULLER', $response->getHeaderLine('Location'));
108b9fc687eSGreg Roach
1097dcc0dd1SGreg Roach        I18N::init('de');
1107dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'MÜLLER'], [], [], ['tree' => $this->tree]);
111a26ec5edSGreg Roach        $response = $module->handle($request);
1127dcc0dd1SGreg Roach        self::assertSame(StatusCodeInterface::STATUS_MOVED_PERMANENTLY, $response->getStatusCode());
1137dcc0dd1SGreg Roach        self::assertStringContainsString('surname=MUELLER', $response->getHeaderLine('Location'));
1147dcc0dd1SGreg Roach    }
1157dcc0dd1SGreg Roach
1167dcc0dd1SGreg Roach    public function testCollationOfSurnames(): void
1177dcc0dd1SGreg Roach    {
118a26ec5edSGreg Roach        $module = new IndividualListModule();
119a26ec5edSGreg Roach
1207dcc0dd1SGreg Roach        $i1 = $this->tree->createIndividual("0 @@ INDI\n1 NAME /Muller/");
1217dcc0dd1SGreg Roach        $i2 = $this->tree->createIndividual("0 @@ INDI\n1 NAME /Müller/");
1227dcc0dd1SGreg Roach        $i3 = $this->tree->createIndividual("0 @@ INDI\n1 NAME /Mueller/");
1237dcc0dd1SGreg Roach
1247dcc0dd1SGreg Roach        I18N::init('en-US');
1257dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'MULLER'], [], [], ['tree' => $this->tree]);
126a26ec5edSGreg Roach        $response = $module->handle($request);
1277dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
1287dcc0dd1SGreg Roach        preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches);
1297dcc0dd1SGreg Roach        self::assertEqualsCanonicalizing([$i1->xref(), $i2->xref()], $matches[1], 'English, so U should match U and Ü');
1307dcc0dd1SGreg Roach
1317dcc0dd1SGreg Roach        I18N::init('de');
1327dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'MULLER'], [], [], ['tree' => $this->tree]);
133a26ec5edSGreg Roach        $response = $module->handle($request);
1347dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
1357dcc0dd1SGreg Roach        preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches);
1367dcc0dd1SGreg Roach        self::assertEqualsCanonicalizing([$i1->xref()], $matches[1], 'German, so U should only match U');
1377dcc0dd1SGreg Roach
1387dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['surname' => 'MUELLER'], [], [], ['tree' => $this->tree]);
139a26ec5edSGreg Roach        $response = $module->handle($request);
1407dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
1417dcc0dd1SGreg Roach        preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches);
1427dcc0dd1SGreg Roach        self::assertEqualsCanonicalizing([$i2->xref(), $i3->xref()], $matches[1], 'German, so UE should also match Ü');
1437dcc0dd1SGreg Roach    }
1447dcc0dd1SGreg Roach
145a26ec5edSGreg Roach    public function xtestUnknownVersusMissingSurname(): void
1467dcc0dd1SGreg Roach    {
147a26ec5edSGreg Roach        $module = new IndividualListModule();
148a26ec5edSGreg Roach
1497dcc0dd1SGreg Roach        $i1 = $this->tree->createIndividual("0 @@ INDI\n1 NAME John //");
1507dcc0dd1SGreg Roach        $i2 = $this->tree->createIndividual("0 @@ INDI\n1 NAME John");
1517dcc0dd1SGreg Roach
1527dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['alpha' => '@'], [], [], ['tree' => $this->tree]);
153a26ec5edSGreg Roach        $response = $module->handle($request);
1547dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
1557dcc0dd1SGreg Roach        preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches);
1567dcc0dd1SGreg Roach        self::assertEqualsCanonicalizing([$i1->xref()], $matches[1]);
1577dcc0dd1SGreg Roach
1587dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['alpha' => ','], [], [], ['tree' => $this->tree]);
159a26ec5edSGreg Roach        $response = $module->handle($request);
1607dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
1617dcc0dd1SGreg Roach        preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches);
1627dcc0dd1SGreg Roach        self::assertEqualsCanonicalizing([$i2->xref()], $matches[1]);
1637dcc0dd1SGreg Roach    }
1647dcc0dd1SGreg Roach
165a26ec5edSGreg Roach    public function xtestAllSurnamesExcludesUnknownAndMissing(): void
1667dcc0dd1SGreg Roach    {
167a26ec5edSGreg Roach        $module = new IndividualListModule();
168a26ec5edSGreg Roach
1697dcc0dd1SGreg Roach        $i1 = $this->tree->createIndividual("0 @@ INDI\n1 NAME John /Black/");
1707dcc0dd1SGreg Roach        $i2 = $this->tree->createIndividual("0 @@ INDI\n1 NAME Mary /White/");
1717dcc0dd1SGreg Roach        $this->tree->createIndividual("0 @@ INDI\n1 NAME Peter //");
1727dcc0dd1SGreg Roach        $this->tree->createIndividual("0 @@ INDI\n1 NAME Paul");
1737dcc0dd1SGreg Roach
1747dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['show_all' => 'yes'], [], [], ['tree' => $this->tree]);
175a26ec5edSGreg Roach        $response = $module->handle($request);
1767dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
1777dcc0dd1SGreg Roach        preg_match_all('/individual-list&amp;surname=([A-Z]+)/', $html, $matches);
1787dcc0dd1SGreg Roach        self::assertEqualsCanonicalizing(['BLACK', 'WHITE'], $matches[1]);
1797dcc0dd1SGreg Roach
1807dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['show_all' => 'yes', 'show' => 'indi'], [], [], ['tree' => $this->tree]);
181a26ec5edSGreg Roach        $response = $module->handle($request);
1827dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
1837dcc0dd1SGreg Roach        preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches);
1847dcc0dd1SGreg Roach        self::assertEqualsCanonicalizing([$i1->xref(), $i2->xref()], $matches[1]);
1857dcc0dd1SGreg Roach    }
1867dcc0dd1SGreg Roach
187a26ec5edSGreg Roach    public function xtestSurnameInitial(): void
1887dcc0dd1SGreg Roach    {
189a26ec5edSGreg Roach        $module = new IndividualListModule();
190a26ec5edSGreg Roach
1917dcc0dd1SGreg Roach        $i1 = $this->tree->createIndividual("0 @@ INDI\n1 NAME John /Black/");
1927dcc0dd1SGreg Roach        $i2 = $this->tree->createIndividual("0 @@ INDI\n1 NAME Mary /Brown/");
1937dcc0dd1SGreg Roach        $this->tree->createIndividual("0 @@ INDI\n1 NAME Peter /White/");
1947dcc0dd1SGreg Roach        $this->tree->createIndividual("0 @@ INDI\n1 NAME Paul /Green/");
1957dcc0dd1SGreg Roach
1967dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['alpha' => 'B'], [], [], ['tree' => $this->tree]);
197a26ec5edSGreg Roach        $response = $module->handle($request);
1987dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
1997dcc0dd1SGreg Roach        preg_match_all('/individual-list&amp;surname=([A-Z]+)/', $html, $matches);
2007dcc0dd1SGreg Roach        self::assertEqualsCanonicalizing(['BLACK', 'BROWN'], $matches[1]);
2017dcc0dd1SGreg Roach
2027dcc0dd1SGreg Roach        $request  = self::createRequest(RequestMethodInterface::METHOD_GET, ['alpha' => 'B', 'show' => 'indi'], [], [], ['tree' => $this->tree]);
203a26ec5edSGreg Roach        $response = $module->handle($request);
2047dcc0dd1SGreg Roach        $html     = $response->getBody()->getContents();
2057dcc0dd1SGreg Roach        preg_match_all('/%2Fname%2Findividual%2F(X\d+)%2F/', $html, $matches);
2067dcc0dd1SGreg Roach        self::assertEqualsCanonicalizing([$i1->xref(), $i2->xref()], $matches[1]);
207e9e85398SGreg Roach    }
208e9e85398SGreg Roach}
209