1a25f0a04SGreg Roach<?php 23976b470SGreg Roach 3a25f0a04SGreg Roach/** 4a25f0a04SGreg Roach * webtrees: online genealogy 589f7189bSGreg Roach * Copyright (C) 2021 webtrees development team 6a25f0a04SGreg Roach * This program is free software: you can redistribute it and/or modify 7a25f0a04SGreg Roach * it under the terms of the GNU General Public License as published by 8a25f0a04SGreg Roach * the Free Software Foundation, either version 3 of the License, or 9a25f0a04SGreg Roach * (at your option) any later version. 10a25f0a04SGreg Roach * This program is distributed in the hope that it will be useful, 11a25f0a04SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 12a25f0a04SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13a25f0a04SGreg Roach * GNU General Public License for more details. 14a25f0a04SGreg 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/>. 16a25f0a04SGreg Roach */ 17fcfa147eSGreg Roach 18e7f56f2aSGreg Roachdeclare(strict_types=1); 19e7f56f2aSGreg Roach 2084e2cf4eSGreg Roachnamespace Fisharebest\Webtrees; 21a25f0a04SGreg Roach 2269675509SGreg Roachuse Fisharebest\Webtrees\Contracts\CacheFactoryInterface; 231fe542e9SGreg Roachuse Fisharebest\Webtrees\Contracts\UserInterface; 245afbc57aSGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsImport; 2569c05a6eSGreg Roachuse Fisharebest\Webtrees\Services\GedcomExportService; 265afbc57aSGreg Roachuse Fisharebest\Webtrees\Services\TreeService; 27e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Services\UserService; 283cfcc809SGreg Roachuse InvalidArgumentException; 2969675509SGreg Roachuse Symfony\Component\Cache\Adapter\NullAdapter; 303976b470SGreg Roach 3194026f20SGreg Roachuse function stream_get_contents; 3294026f20SGreg Roach 33a25f0a04SGreg Roach/** 34a25f0a04SGreg Roach * Test harness for the class Tree 35a25f0a04SGreg Roach */ 36e5a6b4d4SGreg Roachclass TreeTest extends TestCase 37c1010edaSGreg Roach{ 38126654d7SGreg Roach protected static $uses_database = true; 39126654d7SGreg Roach 4069675509SGreg Roach public function setUp(): void 4169675509SGreg Roach { 4269675509SGreg Roach parent::setUp(); 4369675509SGreg Roach 445e933c21SGreg Roach $cache_factory = self::createMock(CacheFactoryInterface::class); 4569675509SGreg Roach $cache_factory->method('array')->willReturn(new Cache(new NullAdapter())); 466b9cb339SGreg Roach Registry::cache($cache_factory); 4769675509SGreg Roach } 4869675509SGreg Roach 49a25f0a04SGreg Roach /** 50126654d7SGreg Roach * @covers \Fisharebest\Webtrees\Tree::__construct 51126654d7SGreg Roach * @covers \Fisharebest\Webtrees\Tree::id 52126654d7SGreg Roach * @covers \Fisharebest\Webtrees\Tree::name 53126654d7SGreg Roach * @covers \Fisharebest\Webtrees\Tree::title 5452348eb8SGreg Roach * @return void 55a25f0a04SGreg Roach */ 56126654d7SGreg Roach public function testConstructor(): void 57c1010edaSGreg Roach { 581e653452SGreg Roach $tree_service = new TreeService(); 591e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 60126654d7SGreg Roach 615e933c21SGreg Roach self::assertSame('name', $tree->name()); 625e933c21SGreg Roach self::assertSame('title', $tree->title()); 63126654d7SGreg Roach } 64126654d7SGreg Roach 65126654d7SGreg Roach /** 66126654d7SGreg Roach * @covers \Fisharebest\Webtrees\Tree::getPreference 67126654d7SGreg Roach * @covers \Fisharebest\Webtrees\Tree::setPreference 68126654d7SGreg Roach * @return void 69126654d7SGreg Roach */ 70af343084SGreg Roach public function testTreePreferences(): void 71126654d7SGreg Roach { 721e653452SGreg Roach $tree_service = new TreeService(); 731e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 74126654d7SGreg Roach 75126654d7SGreg Roach $pref = $tree->getPreference('foo', 'default'); 765e933c21SGreg Roach self::assertSame('default', $pref); 77126654d7SGreg Roach 78126654d7SGreg Roach $tree->setPreference('foo', 'bar'); 79126654d7SGreg Roach $pref = $tree->getPreference('foo', 'default'); 805e933c21SGreg Roach self::assertSame('bar', $pref); 81a25f0a04SGreg Roach } 82af343084SGreg Roach 83af343084SGreg Roach /** 84af343084SGreg Roach * @covers \Fisharebest\Webtrees\Tree::getUserPreference 85000dd58cSGreg Roach * @covers \Fisharebest\Webtrees\Tree::setUserPreference 86af343084SGreg Roach * @return void 87af343084SGreg Roach */ 88af343084SGreg Roach public function testUserTreePreferences(): void 89af343084SGreg Roach { 90e5a6b4d4SGreg Roach $user_service = new UserService(); 911e653452SGreg Roach $tree_service = new TreeService(); 921e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 93e5a6b4d4SGreg Roach $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 94af343084SGreg Roach 95af343084SGreg Roach $pref = $tree->getUserPreference($user, 'foo', 'default'); 965e933c21SGreg Roach self::assertSame('default', $pref); 97af343084SGreg Roach 98af343084SGreg Roach $tree->setUserPreference($user, 'foo', 'bar'); 99af343084SGreg Roach $pref = $tree->getUserPreference($user, 'foo', 'default'); 1005e933c21SGreg Roach self::assertSame('bar', $pref); 1017d76853dSGreg Roach } 1027d76853dSGreg Roach 1037d76853dSGreg Roach /** 1047d76853dSGreg Roach * @covers \Fisharebest\Webtrees\Tree::createIndividual 1057d76853dSGreg Roach * @return void 1067d76853dSGreg Roach */ 1077d76853dSGreg Roach public function testCreateInvalidIndividual(): void 1087d76853dSGreg Roach { 1093cfcc809SGreg Roach $this->expectException(InvalidArgumentException::class); 1103cfcc809SGreg Roach 111e5a6b4d4SGreg Roach $user_service = new UserService(); 1121e653452SGreg Roach $tree_service = new TreeService(); 1131e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 114e5a6b4d4SGreg Roach $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 1151fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_IS_ADMINISTRATOR, '1'); 1167d76853dSGreg Roach Auth::login($user); 1177d76853dSGreg Roach 1187d76853dSGreg Roach $tree->createIndividual("0 @@ FOO\n1 SEX U"); 1197d76853dSGreg Roach } 1207d76853dSGreg Roach 1217d76853dSGreg Roach /** 122963fbaeeSGreg Roach * @covers \Fisharebest\Webtrees\Tree::createIndividual 123963fbaeeSGreg Roach * @return void 124963fbaeeSGreg Roach */ 125963fbaeeSGreg Roach public function testCreateIndividual(): void 126963fbaeeSGreg Roach { 127e5a6b4d4SGreg Roach $user_service = new UserService(); 1281e653452SGreg Roach $tree_service = new TreeService(); 1291e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 130e5a6b4d4SGreg Roach $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 1311fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_IS_ADMINISTRATOR, '1'); 132963fbaeeSGreg Roach Auth::login($user); 133963fbaeeSGreg Roach 1348f9b0fb2SGreg Roach $record = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 1355e933c21SGreg Roach self::assertTrue($record->isPendingAddition()); 136963fbaeeSGreg Roach 1371fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_AUTO_ACCEPT_EDITS, '1'); 1388f9b0fb2SGreg Roach $record = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 1395e933c21SGreg Roach self::assertFalse($record->isPendingAddition()); 1408f9b0fb2SGreg Roach } 141963fbaeeSGreg Roach 1428f9b0fb2SGreg Roach /** 1437d76853dSGreg Roach * @covers \Fisharebest\Webtrees\Tree::createFamily 1448f9b0fb2SGreg Roach * @return void 1458f9b0fb2SGreg Roach */ 1467d76853dSGreg Roach public function testCreateInvalidFamily(): void 1478f9b0fb2SGreg Roach { 1483cfcc809SGreg Roach $this->expectException(InvalidArgumentException::class); 1493cfcc809SGreg Roach 150e5a6b4d4SGreg Roach $user_service = new UserService(); 1511e653452SGreg Roach $tree_service = new TreeService(); 1521e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 153e5a6b4d4SGreg Roach $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 1541fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_IS_ADMINISTRATOR, '1'); 1557d76853dSGreg Roach Auth::login($user); 156963fbaeeSGreg Roach 1577d76853dSGreg Roach $tree->createFamily("0 @@ FOO\n1 MARR Y"); 1588f9b0fb2SGreg Roach } 159963fbaeeSGreg Roach 1608f9b0fb2SGreg Roach /** 1618f9b0fb2SGreg Roach * @covers \Fisharebest\Webtrees\Tree::createFamily 1628f9b0fb2SGreg Roach * @return void 1638f9b0fb2SGreg Roach */ 1648f9b0fb2SGreg Roach public function testCreateFamily(): void 1658f9b0fb2SGreg Roach { 166e5a6b4d4SGreg Roach $user_service = new UserService(); 1671e653452SGreg Roach $tree_service = new TreeService(); 1681e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 169e5a6b4d4SGreg Roach $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 1701fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_IS_ADMINISTRATOR, '1'); 1718f9b0fb2SGreg Roach Auth::login($user); 1728f9b0fb2SGreg Roach 1738f9b0fb2SGreg Roach $record = $tree->createFamily("0 @@ FAM\n1 MARR Y"); 1745e933c21SGreg Roach self::assertTrue($record->isPendingAddition()); 1758f9b0fb2SGreg Roach 1761fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_AUTO_ACCEPT_EDITS, '1'); 1778f9b0fb2SGreg Roach $record = $tree->createFamily("0 @@ FAM\n1 MARR Y"); 1785e933c21SGreg Roach self::assertFalse($record->isPendingAddition()); 1798f9b0fb2SGreg Roach } 1808f9b0fb2SGreg Roach 1818f9b0fb2SGreg Roach /** 1827d76853dSGreg Roach * @covers \Fisharebest\Webtrees\Tree::createMediaObject 1837d76853dSGreg Roach * @return void 1847d76853dSGreg Roach */ 1857d76853dSGreg Roach public function testCreateInvalidMediaObject(): void 1867d76853dSGreg Roach { 1873cfcc809SGreg Roach $this->expectException(InvalidArgumentException::class); 1883cfcc809SGreg Roach 189e5a6b4d4SGreg Roach $user_service = new UserService(); 1901e653452SGreg Roach $tree_service = new TreeService(); 1911e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 192e5a6b4d4SGreg Roach $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 1931fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_IS_ADMINISTRATOR, '1'); 1947d76853dSGreg Roach Auth::login($user); 1957d76853dSGreg Roach 1967d76853dSGreg Roach $tree->createMediaObject("0 @@ FOO\n1 MARR Y"); 1977d76853dSGreg Roach } 1987d76853dSGreg Roach 1997d76853dSGreg Roach /** 2007d76853dSGreg Roach * @covers \Fisharebest\Webtrees\Tree::createMediaObject 2017d76853dSGreg Roach * @return void 2027d76853dSGreg Roach */ 2037d76853dSGreg Roach public function testCreateMediaObject(): void 2047d76853dSGreg Roach { 205e5a6b4d4SGreg Roach $user_service = new UserService(); 2061e653452SGreg Roach $tree_service = new TreeService(); 2071e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 208e5a6b4d4SGreg Roach $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 2091fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_IS_ADMINISTRATOR, '1'); 2107d76853dSGreg Roach Auth::login($user); 2117d76853dSGreg Roach 2127d76853dSGreg Roach $record = $tree->createMediaObject("0 @@ OBJE\n1 FILE foo.jpeg"); 2135e933c21SGreg Roach self::assertTrue($record->isPendingAddition()); 2147d76853dSGreg Roach 2151fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_AUTO_ACCEPT_EDITS, '1'); 2167d76853dSGreg Roach $record = $tree->createMediaObject("0 @@ OBJE\n1 FILE foo.jpeg"); 2175e933c21SGreg Roach self::assertFalse($record->isPendingAddition()); 2187d76853dSGreg Roach } 2197d76853dSGreg Roach 2207d76853dSGreg Roach /** 221bec87e94SGreg Roach * @covers \Fisharebest\Webtrees\Tree::createRecord 222bec87e94SGreg Roach * @return void 223bec87e94SGreg Roach */ 224bec87e94SGreg Roach public function testCreateInvalidRecord(): void 225bec87e94SGreg Roach { 2263cfcc809SGreg Roach $this->expectException(InvalidArgumentException::class); 2273cfcc809SGreg Roach 228e5a6b4d4SGreg Roach $user_service = new UserService(); 2291e653452SGreg Roach $tree_service = new TreeService(); 2301e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 231e5a6b4d4SGreg Roach $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 2321fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_IS_ADMINISTRATOR, '1'); 233bec87e94SGreg Roach Auth::login($user); 234bec87e94SGreg Roach 235bec87e94SGreg Roach $tree->createRecord("0 @@FOO\n1 NOTE noted"); 236bec87e94SGreg Roach } 237bec87e94SGreg Roach 238bec87e94SGreg Roach /** 239bec87e94SGreg Roach * @covers \Fisharebest\Webtrees\Tree::createRecord 240bec87e94SGreg Roach * @return void 241bec87e94SGreg Roach */ 242bec87e94SGreg Roach public function testCreateRecord(): void 243bec87e94SGreg Roach { 244e5a6b4d4SGreg Roach $user_service = new UserService(); 2451e653452SGreg Roach $tree_service = new TreeService(); 2461e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 247e5a6b4d4SGreg Roach $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 2481fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_IS_ADMINISTRATOR, '1'); 249bec87e94SGreg Roach Auth::login($user); 250bec87e94SGreg Roach 251bec87e94SGreg Roach $record = $tree->createRecord("0 @@ FOO\n1 NOTE noted"); 2525e933c21SGreg Roach self::assertTrue($record->isPendingAddition()); 253bec87e94SGreg Roach 2541fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_AUTO_ACCEPT_EDITS, '1'); 255bec87e94SGreg Roach $record = $tree->createRecord("0 @@ FOO\n1 NOTE noted"); 2565e933c21SGreg Roach self::assertFalse($record->isPendingAddition()); 257bec87e94SGreg Roach } 258bec87e94SGreg Roach 259bec87e94SGreg Roach /** 2608f9b0fb2SGreg Roach * @covers \Fisharebest\Webtrees\Tree::significantIndividual 2618f9b0fb2SGreg Roach * @return void 2628f9b0fb2SGreg Roach */ 2638f9b0fb2SGreg Roach public function testSignificantIndividual(): void 2648f9b0fb2SGreg Roach { 265e5a6b4d4SGreg Roach $user_service = new UserService(); 2661e653452SGreg Roach $tree_service = new TreeService(); 2671e653452SGreg Roach $tree = $tree_service->create('name', 'title'); 268e5a6b4d4SGreg Roach $user = $user_service->create('user', 'User', 'user@example.com', 'secret'); 2691fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_AUTO_ACCEPT_EDITS, '1'); 2708f9b0fb2SGreg Roach Auth::login($user); 2718f9b0fb2SGreg Roach 2725afbc57aSGreg Roach // Delete the tree's default individual. 2735afbc57aSGreg Roach FunctionsImport::updateRecord('0 @X1@ INDI', $tree, true); 2745afbc57aSGreg Roach 2751f244d77SGreg Roach // No individuals in tree? Fake individual 2765e933c21SGreg Roach self::assertSame('I', $tree->significantIndividual($user)->xref()); 2778f9b0fb2SGreg Roach 2788f9b0fb2SGreg Roach $record1 = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 2798f9b0fb2SGreg Roach $record2 = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 2808f9b0fb2SGreg Roach $record3 = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 2818f9b0fb2SGreg Roach $record4 = $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 2828f9b0fb2SGreg Roach 2838f9b0fb2SGreg Roach // Individuals exist? First one (lowest XREF). 2845e933c21SGreg Roach self::assertSame($record1->xref(), $tree->significantIndividual($user)->xref()); 2858f9b0fb2SGreg Roach 2868f9b0fb2SGreg Roach // Preference for tree? 2878f9b0fb2SGreg Roach $tree->setPreference('PEDIGREE_ROOT_ID', $record2->xref()); 2885e933c21SGreg Roach self::assertSame($record2->xref(), $tree->significantIndividual($user)->xref()); 2898f9b0fb2SGreg Roach 2908f9b0fb2SGreg Roach // User preference 2911fe542e9SGreg Roach $tree->setUserPreference($user, UserInterface::PREF_TREE_ACCOUNT_XREF, $record3->xref()); 2925e933c21SGreg Roach self::assertSame($record3->xref(), $tree->significantIndividual($user)->xref()); 2938f9b0fb2SGreg Roach 2948f9b0fb2SGreg Roach // User record 2951fe542e9SGreg Roach $tree->setUserPreference($user, UserInterface::PREF_TREE_DEFAULT_XREF, $record4->xref()); 2965e933c21SGreg Roach self::assertSame($record4->xref(), $tree->significantIndividual($user)->xref()); 297963fbaeeSGreg Roach } 298a7890280SGreg Roach 299a7890280SGreg Roach /** 300*5cd281f4SGreg Roach * @covers \Fisharebest\Webtrees\Services\TreeService::importGedcomFile 301*5cd281f4SGreg Roach * @covers \Fisharebest\Webtrees\Services\TreeService::deleteGenealogyData 302a7890280SGreg Roach * @return void 303a7890280SGreg Roach */ 304a7890280SGreg Roach public function testImportAndDeleteGedcomFile(): void 305a7890280SGreg Roach { 3065afbc57aSGreg Roach $tree_service = new TreeService(); 307a7890280SGreg Roach $tree = $this->importTree('demo.ged'); 3085e933c21SGreg Roach self::assertNotNull($tree_service->all()->get('demo.ged')); 309432ff88aSGreg Roach Site::setPreference('DEFAULT_GEDCOM', $tree->name()); 310a7890280SGreg Roach 3115afbc57aSGreg Roach $tree_service->delete($tree); 312432ff88aSGreg Roach 3135e933c21SGreg Roach self::assertNull($tree_service->all()->get('demo.ged')); 3145e933c21SGreg Roach self::assertSame('', Site::getPreference('DEFAULT_GEDCOM')); 315a7890280SGreg Roach } 31615a3f100SGreg Roach 31715a3f100SGreg Roach /** 31815a3f100SGreg Roach * @covers \Fisharebest\Webtrees\Tree::hasPendingEdit 31915a3f100SGreg Roach * @return void 32015a3f100SGreg Roach */ 32115a3f100SGreg Roach public function testHasPendingEdits(): void 32215a3f100SGreg Roach { 323e5a6b4d4SGreg Roach $user_service = new UserService(); 32415a3f100SGreg Roach $tree = $this->importTree('demo.ged'); 325e5a6b4d4SGreg Roach $user = $user_service->create('admin', 'Administrator', 'admin@example.com', 'secret'); 3261fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_IS_ADMINISTRATOR, '1'); 32715a3f100SGreg Roach Auth::login($user); 32815a3f100SGreg Roach 3291fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_AUTO_ACCEPT_EDITS, '1'); 33015a3f100SGreg Roach $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 3315e933c21SGreg Roach self::assertFalse($tree->hasPendingEdit()); 33215a3f100SGreg Roach 3331fe542e9SGreg Roach $user->setPreference(UserInterface::PREF_AUTO_ACCEPT_EDITS, ''); 33415a3f100SGreg Roach $tree->createIndividual("0 @@ INDI\n1 SEX F\n1 NAME Foo /Bar/"); 3355e933c21SGreg Roach self::assertTrue($tree->hasPendingEdit()); 33615a3f100SGreg Roach } 33794026f20SGreg Roach 33894026f20SGreg Roach /** 33969c05a6eSGreg Roach * @covers \Fisharebest\Webtrees\Services\GedcomExportService::export 34094026f20SGreg Roach * @return void 34194026f20SGreg Roach */ 34294026f20SGreg Roach public function testExportGedcom(): void 34394026f20SGreg Roach { 34494026f20SGreg Roach $tree = $this->importTree('demo.ged'); 34594026f20SGreg Roach 346803193feSGreg Roach $fp = fopen('php://memory', 'wb'); 34794026f20SGreg Roach 34869c05a6eSGreg Roach $gedcom_export_service = new GedcomExportService(); 34969c05a6eSGreg Roach $gedcom_export_service->export($tree, $fp, true); 35094026f20SGreg Roach 35194026f20SGreg Roach rewind($fp); 35294026f20SGreg Roach 35394026f20SGreg Roach $original = file_get_contents(__DIR__ . '/../data/demo.ged'); 35494026f20SGreg Roach $export = stream_get_contents($fp); 35594026f20SGreg Roach 35669c05a6eSGreg Roach // The version, date and time in the HEAD record will be different. 35769c05a6eSGreg Roach $original = preg_replace('/\n2 VERS .*/', '', $original, 1); 35869c05a6eSGreg Roach $export = preg_replace('/\n2 VERS .*/', '', $export, 1); 35994026f20SGreg Roach $original = preg_replace('/\n1 DATE .. ... ..../', '', $original, 1); 36094026f20SGreg Roach $export = preg_replace('/\n1 DATE .. ... ..../', '', $export, 1); 36194026f20SGreg Roach $original = preg_replace('/\n2 TIME ..:..:../', '', $original, 1); 36294026f20SGreg Roach $export = preg_replace('/\n2 TIME ..:..:../', '', $export, 1); 36394026f20SGreg Roach 3645e933c21SGreg Roach self::assertSame($original, $export); 36594026f20SGreg Roach } 366a25f0a04SGreg Roach} 367