snapshot of https://github.com/espocrm/espocrm.git (master, 2026-09-18; blobs > 131072B omitted)
Some checks failed
Test / Test on PHP 8.3 (push) Failing after 5s
Test / Test on PHP 8.4 (push) Failing after 4s
Test / Test on PHP 8.5 (push) Failing after 3s
TypeScript static analysis / TypeScript check (push) Failing after 14s
Test Integration on MySQL / Test on PHP 8.3 (push) Failing after 2s
Test Integration on MySQL / Test on PHP 8.5 (push) Failing after 0s
Test Integration on PostgreSQL / Test on PHP 8.4 fix (push) Failing after 1s
Test Integration on PostgreSQL / Test on PHP 8.4 master (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-18 04:19:15 +05:00
commit 7cc7e6b4f3
10077 changed files with 900756 additions and 0 deletions

View File

@@ -0,0 +1,159 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\Address;
use Espo\Core\{
Field\Address,
};
use Espo\Classes\{
AddressFormatters\Formatter1,
AddressFormatters\Formatter2,
AddressFormatters\Formatter3,
AddressFormatters\Formatter4,
};
class AddressFormattersTest extends \PHPUnit\Framework\TestCase
{
protected function setUp() : void
{
}
public function testFormat1All()
{
$address = Address::createBuilder()
->setStreet('street')
->setCity('city')
->setCountry('country')
->setState('state')
->setPostalCode('postalCode')
->build();
$formatter = new Formatter1();
$expected =
"street\n" .
"city, state postalCode\n" .
"country";
$result = $formatter->format($address);
$this->assertEquals($expected, $result);
}
public function testFormat1NoState()
{
$address = Address::createBuilder()
->setStreet('street')
->setCity('city')
->setCountry('country')
->setState(null)
->setPostalCode('postalCode')
->build();
$formatter = new Formatter1();
$expected =
"street\n" .
"city postalCode\n" .
"country";
$result = $formatter->format($address);
$this->assertEquals($expected, $result);
}
public function testFormat2All()
{
$address = Address::createBuilder()
->setStreet('street')
->setCity('city')
->setCountry('country')
->setState('state')
->setPostalCode('postalCode')
->build();
$formatter = new Formatter2();
$expected =
"street\n" .
"postalCode city\n" .
"state country";
$result = $formatter->format($address);
$this->assertEquals($expected, $result);
}
public function testFormat3All()
{
$address = Address::createBuilder()
->setStreet('street')
->setCity('city')
->setCountry('country')
->setState('state')
->setPostalCode('postalCode')
->build();
$formatter = new Formatter3();
$expected =
"country\n" .
"state postalCode city\n" .
"street";
$result = $formatter->format($address);
$this->assertEquals($expected, $result);
}
public function testFormat4All()
{
$address = Address::createBuilder()
->setStreet('street')
->setCity('city')
->setCountry('country')
->setState('state')
->setPostalCode('postalCode')
->build();
$formatter = new Formatter4();
$expected =
"street\n" .
"city\n" .
"country - state postalCode";
$result = $formatter->format($address);
$this->assertEquals($expected, $result);
}
}

View File

@@ -0,0 +1,132 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\Address;
use Espo\Core\{
Field\Address,
Field\Address\AddressFactory,
};
use Espo\ORM\Entity;
class AddressTest extends \PHPUnit\Framework\TestCase
{
protected function setUp() : void
{
}
public function testAddress1()
{
$address = Address::createBuilder()
->setStreet('street')
->setCity('city')
->setCountry('country')
->setState('state')
->setPostalCode('postalCode')
->build();
$this->assertEquals('street', $address->getStreet());
$this->assertEquals('city', $address->getCity());
$this->assertEquals('country', $address->getCountry());
$this->assertEquals('state', $address->getState());
$this->assertEquals('postalCode', $address->getPostalCode());
}
public function testBuilderClone()
{
$addressOriginal = Address::createBuilder()
->setStreet('street')
->setCity('city')
->setCountry('country')
->setState('state')
->setPostalCode('postalCode')
->build();
$address = Address::createBuilder()
->clone($addressOriginal)
->build();
$this->assertEquals('street', $address->getStreet());
$this->assertEquals('city', $address->getCity());
$this->assertEquals('country', $address->getCountry());
$this->assertEquals('state', $address->getState());
$this->assertEquals('postalCode', $address->getPostalCode());
}
public function testAddressWith()
{
$addressOriginal = Address::createBuilder()
->setStreet('street')
->setCity('city')
->setCountry('country')
->setState('state')
->setPostalCode('postalCode')
->build();
$address = $addressOriginal->withStreet('new street');
$this->assertEquals('new street', $address->getStreet());
$this->assertEquals('city', $address->getCity());
}
public function testCreateFromEntity()
{
$entity = $this->createMock(Entity::class);
$entity
->expects($this->any())
->method('get')
->willReturnMap([
['addressStreet', 'street'],
['addressCity', 'city'],
['addressCountry', 'country'],
['addressState', null],
['addressPostalCode', null],
]);
$factory = new AddressFactory();
$address = $factory->createFromEntity($entity, 'address');
$this->assertEquals('street', $address->getStreet());
$this->assertEquals('city', $address->getCity());
$this->assertEquals('country', $address->getCountry());
$this->assertEquals(null, $address->getState());
$this->assertEquals(null, $address->getPostalCode());
}
public function testCreateFromNothing()
{
$address = Address::create();
$this->assertEquals(null, $address->getState());
}
}

View File

@@ -0,0 +1,176 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\Currency;
use Espo\Core\Currency\ConfigDataProvider as CurrencyConfigDataProvider;
use Espo\Core\Currency\InternalRatesProvider;
use Espo\Core\Utils\Config;
use PHPUnit\Framework\TestCase;
use RuntimeException;
class CurrencyConfigDataProviderTest extends TestCase
{
private $config;
private $provider;
private $ratesProvider;
protected function setUp() : void
{
$this->config = $this->createMock(Config::class);
$this->ratesProvider = $this->createMock(InternalRatesProvider::class);
$this->provider = new CurrencyConfigDataProvider(
$this->config,
$this->ratesProvider,
);
}
public function testDefaultCurrency()
{
$this->config
->expects($this->once())
->method('get')
->with('defaultCurrency')
->willReturn('USD');
$currency = $this->provider->getDefaultCurrency();
$this->assertEquals('USD', $currency);
}
public function testBaseCurrency()
{
$this->config
->expects($this->once())
->method('get')
->with('baseCurrency')
->willReturn('USD');
$currency = $this->provider->getBaseCurrency();
$this->assertEquals('USD', $currency);
}
public function testCurrencyList()
{
$this->config
->expects($this->once())
->method('get')
->with('currencyList')
->willReturn(['USD', 'EUR']);
$result = $this->provider->getCurrencyList();
$this->assertEquals(['USD', 'EUR'], $result);
}
public function testHasCurrency()
{
$this->config
->expects($this->once())
->method('get')
->with('currencyList')
->willReturn(['USD', 'EUR']);
$result = $this->provider->hasCurrency('EUR');
$this->assertTrue($result);
}
public function testCurrencyRate1()
{
$this->ratesProvider
->expects($this->any())
->method('get')
->willReturn([
'EUR' => 1.2,
]);
$invokedCount = $this->exactly(2);
$this->config
->expects($invokedCount)
->method('get')
->willReturnCallback(function ($param) use ($invokedCount) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals('baseCurrency', $param);
return 'USD';
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals('currencyList', $param);
return ['USD', 'EUR'];
}
throw new RuntimeException();
});
$result = $this->provider->getCurrencyRate('EUR');
$this->assertEquals(1.2, $result);
}
public function testCurrencyRate2()
{
$this->ratesProvider
->expects($this->any())
->method('get')
->willReturn([
'EUR' => 1.2,
]);
$invokedCount = $this->exactly(2);
$this->config
->expects($invokedCount)
->method('get')
->willReturnCallback(function ($param) use ($invokedCount) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals('baseCurrency', $param);
return 'USD';
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals('currencyList', $param);
return ['USD', 'EUR'];
}
throw new RuntimeException();
});
$result = $this->provider->getCurrencyRate('USD');
$this->assertEquals(1.0, $result);
}
}

View File

@@ -0,0 +1,154 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\Currency;
use Espo\Core\{
Field\Currency,
Currency\Converter as CurrencyConverter,
Currency\ConfigDataProvider as CurrencyConfigDataProvider,
Currency\Rates as CurrencyRates,
};
class CurrencyConverterTest extends \PHPUnit\Framework\TestCase
{
public function testConvert1()
{
$currencyConfigDataProvider = $this->createMock(CurrencyConfigDataProvider::class);
$currencyConfigDataProvider
->expects($this->any())
->method('hasCurrency')
->with('EUR')
->willReturn(true);
$currencyConfigDataProvider
->expects($this->any())
->method('getCurrencyRate')
->willReturnMap([
['USD', 1.0],
['EUR', 1.2],
]);
$value = new Currency(2.0, 'USD');
$converter = new CurrencyConverter($currencyConfigDataProvider);
$convertedValue = $converter->convert($value, 'EUR');
$this->assertEquals('EUR', $convertedValue->getCode());
$this->assertEquals(round(2.0 / 1.2, 10), round($convertedValue->getAmount(), 10));
}
public function testConvert2()
{
$currencyConfigDataProvider = $this->createMock(CurrencyConfigDataProvider::class);
$currencyConfigDataProvider
->expects($this->any())
->method('hasCurrency')
->with('EUR')
->willReturn(true);
$currencyConfigDataProvider
->expects($this->any())
->method('getCurrencyRate')
->willReturnMap([
['USD', 1.0],
['EUR', 1.2],
['UAH', 0.035],
]);
$value = new Currency(2.0, 'UAH');
$converter = new CurrencyConverter($currencyConfigDataProvider);
$convertedValue = $converter->convert($value, 'EUR');
$this->assertEquals('EUR', $convertedValue->getCode());
$this->assertEquals(round(2.0 * 0.035 / 1.2, 10), round($convertedValue->getAmount(), 10));
}
public function testConvertToDefault()
{
$currencyConfigDataProvider = $this->createMock(CurrencyConfigDataProvider::class);
$currencyConfigDataProvider
->expects($this->any())
->method('getDefaultCurrency')
->willReturn('USD');
$currencyConfigDataProvider
->expects($this->any())
->method('hasCurrency')
->with('USD')
->willReturn(true);
$currencyConfigDataProvider
->expects($this->any())
->method('getCurrencyRate')
->willReturnMap([
['USD', 1.0],
['EUR', 1.2],
]);
$value = new Currency(2.0, 'EUR');
$converter = new CurrencyConverter($currencyConfigDataProvider);
$convertedValue = $converter->convertToDefault($value);
$this->assertEquals('USD', $convertedValue->getCode());
$this->assertEquals(round(2.0 * 1.2, 10), round($convertedValue->getAmount(), 10));
}
public function testConvertWithRates()
{
$currencyConfigDataProvider = $this->createMock(CurrencyConfigDataProvider::class);
$rates = CurrencyRates::fromAssoc([
'USD' => 1.0,
'EUR' => 1.2,
'UAH' => 0.035,
]);
$value = new Currency(2.0, 'UAH');
$converter = new CurrencyConverter($currencyConfigDataProvider);
$convertedValue = $converter->convertWithRates($value, 'EUR', $rates);
$this->assertEquals('EUR', $convertedValue->getCode());
$this->assertEquals(round(2.0 * 0.035 / 1.2, 10), round($convertedValue->getAmount(), 10));
}
}

View File

@@ -0,0 +1,285 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\Currency;
use Espo\Core\Field\Currency;
use Espo\Core\Field\Currency\CurrencyFactory;
use Espo\ORM\Entity;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
class CurrencyTest extends TestCase
{
public function testValue1()
{
$value = Currency::create(2.0, 'USD');
$this->assertEquals(2.0, $value->getAmount());
$this->assertEquals('USD', $value->getCode());
}
public function testValue()
{
$value = Currency::create(0.5, 'USD');
$this->assertEquals('0.5', $value->getAmountAsString());
$this->assertEquals('USD', $value->getCode());
}
public function testAdd()
{
$value = (new Currency(2.0, 'USD'))->add(
new Currency(1.0, 'USD')
);
$this->assertEquals(3.0, $value->getAmount());
$this->assertEquals('USD', $value->getCode());
}
public function testSubtract()
{
$value = (new Currency(2.0, 'USD'))->subtract(
new Currency(3.0, 'USD')
);
$this->assertEquals(-1.0, $value->getAmount());
$this->assertEquals('USD', $value->getCode());
}
public function testMultiply1()
{
$value = (new Currency(2.0, 'USD'))->multiply(3.0);
$this->assertEquals(6.0, $value->getAmount());
$this->assertEquals('USD', $value->getCode());
}
public function testMultiply2()
{
$value = (new Currency(2.0, 'USD'))->multiply(0.5);
$this->assertEquals('1.00000000000000', $value->getAmountAsString());
$this->assertEquals('USD', $value->getCode());
}
public function testDivide1()
{
$value = (new Currency(6.0, 'USD'))->divide(3.0);
$this->assertEquals(2.0, $value->getAmount());
$this->assertEquals('USD', $value->getCode());
}
public function testDivide2()
{
$value = (new Currency(6.0, 'USD'))->divide(0.5);
$this->assertEquals('12.00000000000000', $value->getAmount());
$this->assertEquals('USD', $value->getCode());
}
public function testRound1()
{
$value = (new Currency(2.306, 'USD'))->round(2);
$this->assertEquals(2.31, $value->getAmount());
$this->assertEquals('USD', $value->getCode());
}
public function testRound2()
{
$value = (new Currency(2.306, 'USD'))->round(4);
$this->assertEquals(2.306, $value->getAmount());
}
public function testRound3()
{
$value = (new Currency(2.306, 'USD'))->round(0);
$this->assertEquals(2, $value->getAmount());
}
public function testRound4()
{
$value = (new Currency(-2.306, 'USD'))->round(2);
$this->assertEquals(-2.31, $value->getAmount());
}
public function testRound5()
{
$value = (new Currency(-2.5, 'USD'))->round(0);
$this->assertEquals(-3, $value->getAmount());
}
public function testBadAdd()
{
$this->expectException(InvalidArgumentException::class);
(new Currency(2.0, 'USD'))->add(
new Currency(1.0, 'EUR')
);
}
public function testGetBadCode()
{
$this->expectException(InvalidArgumentException::class);
new Currency(2.0, '');
}
public function testCreateFromEntity()
{
$entity = $this->createMock(Entity::class);
$entity
->expects($this->any())
->method('get')
->willReturnMap([
['test', 10.0],
['testCurrency', 'USD'],
]);
$entity
->expects($this->any())
->method('has')
->willReturnMap([
['test', true],
['testCurrency', true],
]);
$factory = new CurrencyFactory();
$value = $factory->createFromEntity($entity, 'test');
$this->assertEquals(10.0, $value->getAmount());
$this->assertEquals('USD', $value->getCode());
}
public function testCreatableFromEntityTrue()
{
$entity = $this->createMock(Entity::class);
$entity
->expects($this->any())
->method('get')
->willReturnMap([
['test', 5],
['testCurrency', 'USD'],
]);
$factory = new CurrencyFactory();
$this->assertTrue(
$factory->isCreatableFromEntity($entity, 'test')
);
}
public function testCreatableFromEntityFalse()
{
$entity = $this->createMock(Entity::class);
$entity
->expects($this->any())
->method('get')
->willReturnMap([
['test', 5.0],
['testCurrency', null],
]);
$factory = new CurrencyFactory();
$this->assertFalse(
$factory->isCreatableFromEntity($entity, 'test')
);
}
public function testCompare1(): void
{
$this->assertEquals(
1,
Currency::create(2.0, 'USD')
->compare(
Currency::create(1.0, 'USD')
)
);
}
public function testCompare2(): void
{
$this->assertEquals(
0,
Currency::create(2.1, 'USD')
->compare(
Currency::create(2.1, 'USD')
)
);
}
public function testCompare3(): void
{
$this->assertEquals(
-1,
Currency::create(2.1, 'USD')
->compare(
Currency::create(3.1, 'USD')
)
);
}
public function testCompare4(): void
{
$this->expectException(InvalidArgumentException::class);
Currency::create(2.1, 'EUR')
->compare(
Currency::create(2.1, 'USD')
);
}
public function testIsNegative1(): void
{
$this->assertTrue(Currency::create(-1.0, 'USD')->isNegative());
}
public function testIsNegative2(): void
{
$this->assertFalse(Currency::create(1.0, 'USD')->isNegative());
}
public function testIsNegative3(): void
{
$this->assertFalse(Currency::create(0.0, 'USD')->isNegative());
}
}

View File

@@ -0,0 +1,274 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\Date;
use Espo\Core\Field\Date;
use DateTimeImmutable;
use DateTimeZone;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use DateInterval;
class DateTest extends TestCase
{
public function testFromString()
{
$value = Date::fromString('2021-05-01');
$this->assertEquals('2021-05-01', $value->toString());
}
public function testFromDateTime()
{
$dt = new DateTimeImmutable('2021-05-01', new DateTimeZone('UTC'));
$value = Date::fromDateTime($dt);
$this->assertEquals('2021-05-01', $value->toString());
}
public function testBad1()
{
$this->expectException(InvalidArgumentException::class);
Date::fromString('2021-05-A');
}
public function testBad2()
{
$this->expectException(InvalidArgumentException::class);
Date::fromString('2021-05-1');
}
public function testEmpty()
{
$this->expectException(InvalidArgumentException::class);
Date::fromString('');
}
public function testGetDateTime()
{
$value = Date::fromString('2021-05-01');
$this->assertEquals('2021-05-01', $value->toDateTime()->format('Y-m-d'));
}
public function testGetMethods()
{
$value = Date::fromString('2021-05-01');
$dt = new DateTimeImmutable('2021-05-01', new DateTimeZone('UTC'));
$this->assertEquals(1, $value->getDay());
$this->assertEquals(5, $value->getMonth());
$this->assertEquals(2021, $value->getYear());
$this->assertEquals(6, $value->getDayOfWeek());
$this->assertEquals($dt->getTimestamp(), $value->toTimestamp());
}
public function testAdd()
{
$value = Date::fromString('2021-05-01');
$modifiedValue = $value->add(DateInterval::createFromDateString('1 day'));
$this->assertEquals('2021-05-02', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testSubtract()
{
$value = Date::fromString('2021-05-01');
$modifiedValue = $value->subtract(DateInterval::createFromDateString('1 day'));
$this->assertEquals('2021-04-30', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testModify()
{
$value = Date::fromString('2021-05-01');
$modifiedValue = $value->modify('+1 month');
$this->assertEquals('2021-06-01', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testDiff(): void
{
$value1 = Date::fromString('2021-05-01');
$value2 = Date::fromString('2021-05-02');
$this->assertEquals(1, $value1->diff($value2)->d);
$this->assertEquals(0, $value1->diff($value2)->invert);
}
public function testToday(): void
{
$value1 = Date::createToday();
$value2 = Date::createToday(new DateTimeZone('Europe/Kyiv'));
$this->assertEquals(0, $value1->diff($value2)->invert);
}
public function testComparison(): void
{
$value = Date::fromString('2021-05-01');
$this->assertTrue(
$value->isEqualTo(
$value->modify('+1 day')->modify('-1 day')
)
);
$this->assertFalse(
$value->isEqualTo(
$value->modify('+1 day')
)
);
$this->assertFalse(
$value->isGreaterThan(
$value->modify('+1 day')
)
);
$this->assertFalse(
$value->isLessThan(
$value->modify('-1 day')
)
);
$this->assertTrue(
$value->isGreaterThan(
$value->modify('-1 day')
)
);
$this->assertTrue(
$value->isLessThan(
$value->modify('+1 day')
)
);
$this->assertTrue(
$value->isGreaterThanOrEqualTo(
$value
)
);
$this->assertTrue(
$value->isLessThanOrEqualTo(
$value
)
);
$this->assertTrue(
$value->isGreaterThanOrEqualTo(
$value->modify('-1 day')
)
);
$this->assertTrue(
$value->isLessThanOrEqualTo(
$value->modify('+1 day')
)
);
}
public function testAddDays(): void
{
$value = Date::fromString('2023-01-01');
$this->assertEquals(
Date::fromString('2023-01-02'),
$value->addDays(1)
);
$this->assertEquals(
Date::fromString('2023-01-03'),
$value->addDays(2)
);
$this->assertEquals(
Date::fromString('2022-12-31'),
$value->addDays(-1)
);
}
public function testAddMonths(): void
{
$value = Date::fromString('2023-01-01');
$this->assertEquals(
Date::fromString('2023-02-01'),
$value->addMonths(1)
);
$this->assertEquals(
Date::fromString('2023-03-01'),
$value->addMonths(2)
);
$this->assertEquals(
Date::fromString('2022-12-01'),
$value->addMonths(-1)
);
}
public function testAddYears(): void
{
$value = Date::fromString('2023-01-01');
$this->assertEquals(
Date::fromString('2024-01-01'),
$value->addYears(1)
);
$this->assertEquals(
Date::fromString('2025-01-01'),
$value->addYears(2)
);
$this->assertEquals(
Date::fromString('2022-01-01'),
$value->addYears(-1)
);
}
}

View File

@@ -0,0 +1,408 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\DateTime;
use Espo\Core\Field\DateTime;
use DateTimeImmutable;
use DateTimeZone;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
use DateInterval;
class DateTimeTest extends TestCase
{
public function testFromString1()
{
$value = DateTime::fromString('2021-05-01 10:20:30');
$this->assertEquals('2021-05-01 10:20:30', $value->toString());
}
public function testFromString2()
{
$value = DateTime::fromString('2021-05-01 10:20');
$this->assertEquals('2021-05-01 10:20:00', $value->toString());
}
public function testFromDateTime1()
{
$dt = new DateTimeImmutable('2021-05-01 10:20:30', new DateTimeZone('UTC'));
$value = DateTime::fromDateTime($dt);
$this->assertEquals('2021-05-01 10:20:30', $value->toString());
}
public function testFromDateTime2()
{
$dt = new DateTimeImmutable('2021-05-01 10:20:30', new DateTimeZone('Europe/Kyiv'));
$value = DateTime::fromDateTime($dt);
$this->assertEquals('2021-05-01 07:20:30', $value->toString());
}
public function testBad1()
{
$this->expectException(InvalidArgumentException::class);
DateTime::fromString('2021-05-A 10:20:30');
}
public function testBad2()
{
$this->expectException(InvalidArgumentException::class);
DateTime::fromString('2021-05-1 10:20:30');
}
public function testEmpty()
{
$this->expectException(InvalidArgumentException::class);
DateTime::fromString('');
}
public function testGetDateTime()
{
$value = DateTime::fromString('2021-05-01 10:20:30');
$this->assertEquals('2021-05-01', $value->toDateTime()->format('Y-m-d'));
}
public function testGetMethods()
{
$value = DateTime::fromString('2021-05-01 10:20:30');
$dt = new DateTimeImmutable('2021-05-01 10:20:30', new DateTimeZone('UTC'));
$this->assertEquals(1, $value->getDay());
$this->assertEquals(5, $value->getMonth());
$this->assertEquals(2021, $value->getYear());
$this->assertEquals(6, $value->getDayOfWeek());
$this->assertEquals(10, $value->getHour());
$this->assertEquals(20, $value->getMinute());
$this->assertEquals(30, $value->getSecond());
$this->assertEquals($dt->getTimestamp(), $value->toTimestamp());
}
public function testAdd()
{
$value = DateTime::fromString('2021-05-01 10:20:30');
$modifiedValue = $value->add(DateInterval::createFromDateString('1 day'));
$this->assertEquals('2021-05-02 10:20:30', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testSubtract()
{
$value = DateTime::fromString('2021-05-01 10:20:30');
$modifiedValue = $value->subtract(DateInterval::createFromDateString('1 day'));
$this->assertEquals('2021-04-30 10:20:30', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testModify()
{
$value = DateTime::fromString('2021-05-01 10:20:30');
$modifiedValue = $value->modify('+1 month');
$this->assertEquals('2021-06-01 10:20:30', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testWithTimezone()
{
$value = DateTime
::fromString('2021-05-01 10:20:30')
->withTimezone(new DateTimeZone('Europe/Kyiv'));
$this->assertEquals('2021-05-01 10:20:30', $value->toString());
$this->assertEquals(13, $value->getHour());
}
public function getGetTimezone()
{
$value = DateTime
::fromString('2021-05-01 10:20:30')
->withTimezone(new DateTimeZone('Europe/Kyiv'));
$this->assertEquals(new DateTimeZone('Europe/Kyiv'), $value->getTimezone());
}
public function testDiff(): void
{
$value1 = DateTime::fromString('2021-05-01 10:10:30');
$value2 = DateTime::fromString('2021-05-01 10:20:30');
$this->assertEquals(10, $value1->diff($value2)->i);
$this->assertEquals(0, $value1->diff($value2)->invert);
}
public function testNow(): void
{
$value = DateTime::createNow();
$this->assertNotNull($value);
}
public function testWithTime(): void
{
$value = DateTime::fromString('2021-05-01 10:10:30');
$this->assertEquals(
'2021-05-01 00:00:00',
$value->withTime(0, 0, 0)->toString()
);
$this->assertEquals(
'2021-05-01 00:10:30',
$value->withTime(0, null, null)->toString()
);
$this->assertEquals(
'2021-05-01 10:00:00',
$value->withTime(null, 0)->toString()
);
$this->assertEquals(
'2021-05-01 10:00:10',
$value->withTime(null, 0, 10)->toString()
);
}
public function testComparison(): void
{
$value = DateTime::fromString('2021-05-01 10:10:30')
->withTimezone(new DateTimeZone('Europe/Kyiv'));
$this->assertTrue(
$value->isEqualTo(
$value->withTimezone(new DateTimeZone('UTC'))
)
);
$this->assertFalse(
$value->isEqualTo(
$value->modify('+1 minute')
)
);
$this->assertFalse(
$value->isGreaterThan(
$value->modify('+1 minute')
)
);
$this->assertFalse(
$value->isLessThan(
$value->modify('-1 minute')
)
);
$this->assertTrue(
$value->isGreaterThan(
$value->modify('-1 minute')
)
);
$this->assertTrue(
$value->isLessThan(
$value->modify('+1 minute')
)
);
$this->assertTrue(
$value->isGreaterThanOrEqualTo(
$value
)
);
$this->assertTrue(
$value->isLessThanOrEqualTo(
$value
)
);
$this->assertTrue(
$value->isGreaterThanOrEqualTo(
$value->modify('-1 minute')
)
);
$this->assertTrue(
$value->isLessThanOrEqualTo(
$value->modify('+1 minute')
)
);
}
public function testAddDays(): void
{
$value = DateTime::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTime::fromString('2023-01-02 00:00:00'),
$value->addDays(1)
);
$this->assertEquals(
DateTime::fromString('2023-01-03 00:00:00'),
$value->addDays(2)
);
$this->assertEquals(
DateTime::fromString('2022-12-31 00:00:00'),
$value->addDays(-1)
);
}
public function testAddMonths(): void
{
$value = DateTime::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTime::fromString('2023-02-01 00:00:00'),
$value->addMonths(1)
);
$this->assertEquals(
DateTime::fromString('2023-03-01 00:00:00'),
$value->addMonths(2)
);
$this->assertEquals(
DateTime::fromString('2022-12-01 00:00:00'),
$value->addMonths(-1)
);
}
public function testAddYears(): void
{
$value = DateTime::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTime::fromString('2024-01-01 00:00:00'),
$value->addYears(1)
);
$this->assertEquals(
DateTime::fromString('2025-01-01 00:00:00'),
$value->addYears(2)
);
$this->assertEquals(
DateTime::fromString('2022-01-01 00:00:00'),
$value->addYears(-1)
);
}
public function testAddHours(): void
{
$value = DateTime::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTime::fromString('2023-01-01 01:00:00'),
$value->addHours(1)
);
$this->assertEquals(
DateTime::fromString('2022-12-31 23:00:00'),
$value->addHours(-1)
);
$this->assertEquals(
$value,
$value->addHours(0)
);
}
public function testAddMinutes(): void
{
$value = DateTime::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTime::fromString('2023-01-01 00:01:00'),
$value->addMinutes(1)
);
$this->assertEquals(
DateTime::fromString('2022-12-31 23:59:00'),
$value->addMinutes(-1)
);
$this->assertEquals(
$value,
$value->addMinutes(0)
);
}
public function testAddSeconds(): void
{
$value = DateTime::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTime::fromString('2023-01-01 00:00:01'),
$value->addSeconds(1)
);
$this->assertEquals(
DateTime::fromString('2022-12-31 23:59:59'),
$value->addSeconds(-1)
);
$this->assertEquals(
$value,
$value->addSeconds(0)
);
}
public function testFromTimestamp(): void
{
$timestamp = 1664959621;
$value = DateTime::fromTimestamp($timestamp);
$this->assertEquals($timestamp, $value->toTimestamp());
}
}

View File

@@ -0,0 +1,231 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\DateTimeOptional;
use Espo\Core\Field\DateTimeOptional;
use DateTimeImmutable;
use DateTimeZone;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
use DateInterval;
class DateTimeOptionalDateTest extends TestCase
{
public function testFromString()
{
$value = DateTimeOptional::fromString('2021-05-01');
$this->assertEquals('2021-05-01', $value->toString());
$this->assertTrue($value->isAllDay());
}
public function testFromDateTime()
{
$dt = new DateTimeImmutable('2021-05-01', new DateTimeZone('UTC'));
$value = DateTimeOptional::fromDateTimeAllDay($dt);
$this->assertEquals('2021-05-01', $value->toString());
}
public function testBad1()
{
$this->expectException(InvalidArgumentException::class);
DateTimeOptional::fromString('2021-05-A');
}
public function testBad2()
{
$this->expectException(InvalidArgumentException::class);
DateTimeOptional::fromString('2021-05-1');
}
public function testEmpty()
{
$this->expectException(InvalidArgumentException::class);
DateTimeOptional::fromString('');
}
public function testGetDateTime()
{
$value = DateTimeOptional::fromString('2021-05-01');
$this->assertEquals('2021-05-01', $value->toDateTime()->format('Y-m-d'));
}
public function testGetTimezone()
{
$value = DateTimeOptional::fromString('2021-05-01');
$this->assertEquals(new DateTimeZone('UTC'), $value->toDateTime()->getTimezone());
}
public function testGetMethods()
{
$value = DateTimeOptional::fromString('2021-05-01');
$dt = new DateTimeImmutable('2021-05-01', new DateTimeZone('UTC'));
$this->assertEquals(1, $value->getDay());
$this->assertEquals(5, $value->getMonth());
$this->assertEquals(2021, $value->getYear());
$this->assertEquals(6, $value->getDayOfWeek());
$this->assertEquals($dt->getTimestamp(), $value->toTimestamp());
}
public function testAdd()
{
$value = DateTimeOptional::fromString('2021-05-01');
$modifiedValue = $value->add(DateInterval::createFromDateString('1 day'));
$this->assertEquals('2021-05-02', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testSubtract()
{
$value = DateTimeOptional::fromString('2021-05-01');
$modifiedValue = $value->subtract(DateInterval::createFromDateString('1 day'));
$this->assertEquals('2021-04-30', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testModify()
{
$value = DateTimeOptional::fromString('2021-05-01');
$modifiedValue = $value->modify('+1 month');
$this->assertEquals('2021-06-01', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testWithTimezone()
{
$value = DateTimeOptional
::fromString('2021-05-01')
->withTimezone(new DateTimeZone('Europe/Kyiv'));
$this->assertEquals('2021-05-01 00:00:00', $value->toString());
$this->assertEquals(new DateTimeZone('Europe/Kyiv'), $value->getTimezone());
$this->assertFalse($value->isAllDay());
}
public function testDiff(): void
{
$value1 = DateTimeOptional::fromString('2021-05-01');
$value2 = DateTimeOptional::fromString('2021-05-02');
$this->assertEquals(1, $value1->diff($value2)->d);
$this->assertEquals(0, $value1->diff($value2)->invert);
}
public function testToday(): void
{
$value1 = DateTimeOptional::createToday();
$value2 = DateTimeOptional::createToday(new DateTimeZone('Europe/Kyiv'));
$this->assertEquals(0, $value1->diff($value2)->invert);
}
public function testAddDays(): void
{
$value = DateTimeOptional::fromString('2023-01-01');
$this->assertEquals(
DateTimeOptional::fromString('2023-01-02'),
$value->addDays(1)
);
$this->assertEquals(
DateTimeOptional::fromString('2023-01-03'),
$value->addDays(2)
);
$this->assertEquals(
DateTimeOptional::fromString('2022-12-31'),
$value->addDays(-1)
);
}
public function testAddMonths(): void
{
$value = DateTimeOptional::fromString('2023-01-01');
$this->assertEquals(
DateTimeOptional::fromString('2023-02-01'),
$value->addMonths(1)
);
$this->assertEquals(
DateTimeOptional::fromString('2023-03-01'),
$value->addMonths(2)
);
$this->assertEquals(
DateTimeOptional::fromString('2022-12-01'),
$value->addMonths(-1)
);
}
public function testAddYears(): void
{
$value = DateTimeOptional::fromString('2023-01-01');
$this->assertEquals(
DateTimeOptional::fromString('2024-01-01'),
$value->addYears(1)
);
$this->assertEquals(
DateTimeOptional::fromString('2025-01-01'),
$value->addYears(2)
);
$this->assertEquals(
DateTimeOptional::fromString('2022-01-01'),
$value->addYears(-1)
);
}
}

View File

@@ -0,0 +1,437 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\DateTimeOptionalTest;
use Espo\Core\Field\DateTimeOptional;
use DateTimeImmutable;
use DateTimeZone;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
use DateInterval;
class DateTimeOptionalTest extends TestCase
{
public function testFromString1()
{
$value = DateTimeOptional::fromString('2021-05-01 10:20:30');
$this->assertEquals('2021-05-01 10:20:30', $value->toString());
$this->assertFalse($value->isAllDay());
}
public function testFromString2()
{
$value = DateTimeOptional::fromString('2021-05-01 10:20');
$this->assertEquals('2021-05-01 10:20:00', $value->toString());
$this->assertFalse($value->isAllDay());
}
public function testFromDateTime1()
{
$dt = new DateTimeImmutable('2021-05-01 10:20:30', new DateTimeZone('UTC'));
$value = DateTimeOptional::fromDateTime($dt);
$this->assertEquals('2021-05-01 10:20:30', $value->toString());
}
public function testFromDateTime2()
{
$dt = new DateTimeImmutable('2021-05-01 10:20:30', new DateTimeZone('Europe/Kyiv'));
$value = DateTimeOptional::fromDateTime($dt);
$this->assertEquals('2021-05-01 07:20:30', $value->toString());
}
public function testBad1()
{
$this->expectException(InvalidArgumentException::class);
DateTimeOptional::fromString('2021-05-A 10:20:30');
}
public function testBad2()
{
$this->expectException(InvalidArgumentException::class);
DateTimeOptional::fromString('2021-05-1 10:20:30');
}
public function testEmpty()
{
$this->expectException(InvalidArgumentException::class);
DateTimeOptional::fromString('');
}
public function testGetDateTime()
{
$value = DateTimeOptional::fromString('2021-05-01 10:20:30');
$this->assertEquals('2021-05-01', $value->toDateTime()->format('Y-m-d'));
}
public function testGetMethods()
{
$value = DateTimeOptional::fromString('2021-05-01 10:20:30');
$dt = new DateTimeImmutable('2021-05-01 10:20:30', new DateTimeZone('UTC'));
$this->assertEquals(1, $value->getDay());
$this->assertEquals(5, $value->getMonth());
$this->assertEquals(2021, $value->getYear());
$this->assertEquals(6, $value->getDayOfWeek());
$this->assertEquals(10, $value->getHour());
$this->assertEquals(20, $value->getMinute());
$this->assertEquals(30, $value->getSecond());
$this->assertEquals($dt->getTimestamp(), $value->getTimestamp());
}
public function testAdd()
{
$value = DateTimeOptional::fromString('2021-05-01 10:20:30');
$modifiedValue = $value->add(DateInterval::createFromDateString('1 day'));
$this->assertEquals('2021-05-02 10:20:30', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testSubtract()
{
$value = DateTimeOptional::fromString('2021-05-01 10:20:30');
$modifiedValue = $value->subtract(DateInterval::createFromDateString('1 day'));
$this->assertEquals('2021-04-30 10:20:30', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testModify()
{
$value = DateTimeOptional::fromString('2021-05-01 10:20:30');
$modifiedValue = $value->modify('+1 month');
$this->assertEquals('2021-06-01 10:20:30', $modifiedValue->toString());
$this->assertNotSame($modifiedValue, $value);
}
public function testWithTimezone()
{
$value = DateTimeOptional
::fromString('2021-05-01 10:20:30')
->withTimezone(new DateTimeZone('Europe/Kyiv'));
$this->assertEquals('2021-05-01 10:20:30', $value->toString());
$this->assertEquals(13, $value->getHour());
}
public function getGetTimezone()
{
$value = DateTimeOptional
::fromString('2021-05-01 10:20:30')
->withTimezone(new DateTimeZone('Europe/Kyiv'));
$this->assertEquals(new DateTimeZone('Europe/Kyiv'), $value->getTimezone());
}
public function testDiff(): void
{
$value1 = DateTimeOptional::fromString('2021-05-01 10:10:30');
$value2 = DateTimeOptional::fromString('2021-05-01 10:20:30');
$this->assertEquals(10, $value1->diff($value2)->i);
$this->assertEquals(0, $value1->diff($value2)->invert);
}
public function testNow(): void
{
$value = DateTimeOptional::createNow();
$this->assertNotNull($value);
}
public function testWithTime1(): void
{
$value = DateTimeOptional::fromString('2021-05-01 10:10:30');
$this->assertEquals(
'2021-05-01 00:00:00',
$value->withTime(0, 0, 0)->toString()
);
$this->assertEquals(
'2021-05-01 00:10:30',
$value->withTime(0, null, null)->toString()
);
$this->assertEquals(
'2021-05-01 10:00:00',
$value->withTime(null, 0)->toString()
);
$this->assertEquals(
'2021-05-01 10:00:10',
$value->withTime(null, 0, 10)->toString()
);
}
public function testWithTime2(): void
{
$value = DateTimeOptional::fromString('2021-05-01');
$this->assertEquals(
'2021-05-01 00:00:00',
$value->withTime(0, 0, 0)->toString()
);
$this->assertEquals(
'2021-05-01 00:00:00',
$value->withTime(0, null, null)->toString()
);
$this->assertEquals(
'2021-05-01 00:00:00',
$value->withTime(null, 0)->toString()
);
$this->assertEquals(
'2021-05-01 00:00:10',
$value->withTime(null, 0, 10)->toString()
);
}
public function testComparison(): void
{
$value = DateTimeOptional::fromString('2021-05-01 10:10:30')
->withTimezone(new DateTimeZone('Europe/Kyiv'));
$this->assertTrue(
$value->isEqualTo(
$value->withTimezone(new DateTimeZone('UTC'))
)
);
$this->assertFalse(
$value->isEqualTo(
$value->modify('+1 minute')
)
);
$this->assertFalse(
$value->isGreaterThan(
$value->modify('+1 minute')
)
);
$this->assertFalse(
$value->isLessThan(
$value->modify('-1 minute')
)
);
$this->assertTrue(
$value->isGreaterThan(
$value->modify('-1 minute')
)
);
$this->assertTrue(
$value->isLessThan(
$value->modify('+1 minute')
)
);
$this->assertTrue(
$value->isGreaterThanOrEqualTo(
$value
)
);
$this->assertTrue(
$value->isLessThanOrEqualTo(
$value
)
);
$this->assertTrue(
$value->isGreaterThanOrEqualTo(
$value->modify('-1 minute')
)
);
$this->assertTrue(
$value->isLessThanOrEqualTo(
$value->modify('+1 minute')
)
);
}
public function testAddDays(): void
{
$value = DateTimeOptional::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTimeOptional::fromString('2023-01-02 00:00:00'),
$value->addDays(1)
);
$this->assertEquals(
DateTimeOptional::fromString('2023-01-03 00:00:00'),
$value->addDays(2)
);
$this->assertEquals(
DateTimeOptional::fromString('2022-12-31 00:00:00'),
$value->addDays(-1)
);
}
public function testAddMonths(): void
{
$value = DateTimeOptional::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTimeOptional::fromString('2023-02-01 00:00:00'),
$value->addMonths(1)
);
$this->assertEquals(
DateTimeOptional::fromString('2023-03-01 00:00:00'),
$value->addMonths(2)
);
$this->assertEquals(
DateTimeOptional::fromString('2022-12-01 00:00:00'),
$value->addMonths(-1)
);
}
public function testAddYears(): void
{
$value = DateTimeOptional::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTimeOptional::fromString('2024-01-01 00:00:00'),
$value->addYears(1)
);
$this->assertEquals(
DateTimeOptional::fromString('2025-01-01 00:00:00'),
$value->addYears(2)
);
$this->assertEquals(
DateTimeOptional::fromString('2022-01-01 00:00:00'),
$value->addYears(-1)
);
}
public function testAddHours(): void
{
$value = DateTimeOptional::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTimeOptional::fromString('2023-01-01 01:00:00'),
$value->addHours(1)
);
$this->assertEquals(
DateTimeOptional::fromString('2022-12-31 23:00:00'),
$value->addHours(-1)
);
$this->assertEquals(
$value,
$value->addHours(0)
);
}
public function testAddMinutes(): void
{
$value = DateTimeOptional::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTimeOptional::fromString('2023-01-01 00:01:00'),
$value->addMinutes(1)
);
$this->assertEquals(
DateTimeOptional::fromString('2022-12-31 23:59:00'),
$value->addMinutes(-1)
);
$this->assertEquals(
$value,
$value->addMinutes(0)
);
}
public function testAddSeconds(): void
{
$value = DateTimeOptional::fromString('2023-01-01 00:00:00');
$this->assertEquals(
DateTimeOptional::fromString('2023-01-01 00:00:01'),
$value->addSeconds(1)
);
$this->assertEquals(
DateTimeOptional::fromString('2022-12-31 23:59:59'),
$value->addSeconds(-1)
);
$this->assertEquals(
$value,
$value->addSeconds(0)
);
}
public function testFromTimestamp(): void
{
$timestamp = 1664959621;
$value = DateTimeOptional::fromTimestamp($timestamp);
$this->assertEquals($timestamp, $value->getTimestamp());
}
}

View File

@@ -0,0 +1,88 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\EmailAddress;
use Espo\Core\Field\EmailAddress;
use Espo\Core\Field\EmailAddress\EmailAddressGroupAttributeExtractor;
use Espo\Core\Field\EmailAddressGroup;
use PHPUnit\Framework\TestCase;
class EmailAddressGroupAttributeExtractorTest extends TestCase
{
public function testExtract()
{
$group = EmailAddressGroup
::create([
EmailAddress::create('ONE@test.com'),
EmailAddress::create('two@test.com')->optedOut(),
]);
$valueMap = (new EmailAddressGroupAttributeExtractor())->extract($group, 'emailAddress');
$this->assertEquals(
(object) [
'emailAddress' => 'ONE@test.com',
'emailAddressData' => [
(object) [
'emailAddress' => 'ONE@test.com',
'lower' => 'one@test.com',
'primary' => true,
'optOut' => false,
'invalid' => false,
],
(object) [
'emailAddress' => 'two@test.com',
'lower' => 'two@test.com',
'primary' => false,
'optOut' => true,
'invalid' => false,
],
]
],
$valueMap
);
}
public function testEmpty()
{
$group = EmailAddressGroup
::create([]);
$valueMap = (new EmailAddressGroupAttributeExtractor())->extract($group, 'emailAddress');
$this->assertEquals(
(object) [
'emailAddress' => null,
'emailAddressData' => [],
],
$valueMap
);
}
}

View File

@@ -0,0 +1,309 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\EmailAddress;
use Espo\Core\Field\EmailAddress\EmailAddressGroupFactory;
use Espo\Core\Utils\Metadata;
use Espo\ORM\Entity;
use Espo\ORM\EntityManager;
use Espo\Repositories\EmailAddress as EmailAddressRepository;
use PHPUnit\Framework\TestCase;
use RuntimeException;
class EmailAddressGroupFactoryTest extends TestCase
{
/**
* @var Metadata
*/
private $metadata;
/**
* @var EmailAddressRepository
*/
private $emailAddressRepository;
/**
* @var EmailAddressGroupFactory
*/
private $factory;
public function setUp() : void
{
$this->metadata = $this->createMock(Metadata::class);
$entityManager = $this->createMock(EntityManager::class);
$this->emailAddressRepository = $this->createMock(EmailAddressRepository::class);
$this->factory = new EmailAddressGroupFactory($this->metadata, $entityManager);
$entityManager
->expects($this->any())
->method('getRepository')
->with('EmailAddress')
->willReturn($this->emailAddressRepository);
}
private function initField(string $entityType, string $field, string $type) : void
{
$this->metadata
->expects($this->any())
->method('get')
->with(['entityDefs', $entityType, 'fields', $field, 'type'])
->willReturn($type);
}
private function createEntityMock(string $entityType) : Entity
{
$entity = $this->createMock(Entity::class);
$entity
->expects($this->any())
->method('getEntityType')
->willReturn($entityType);
return $entity;
}
private function initEmailAddressRepository(Entity $entity, array $dataList) : void
{
$this->emailAddressRepository
->expects($this->once())
->method('getEmailAddressData')
->with($entity)
->willReturn($dataList);
}
public function testIsCreatableFromEntityTrue() : void
{
$this->initField('Test', 'test', 'email');
$entity = $this->createEntityMock('Test');
$this->assertTrue($this->factory->isCreatableFromEntity($entity, 'test'));
}
public function testIsCreatableFromEntityBad() : void
{
$this->initField('Test', 'test', 'varchar');
$entity = $this->createEntityMock('Test');
$this->assertFalse($this->factory->isCreatableFromEntity($entity, 'test'));
}
public function testCreateException() : void
{
$this->initField('Test', 'test', 'varchar');
$entity = $this->createEntityMock('Test');
$this->expectException(RuntimeException::class);
$this->factory->createFromEntity($entity, 'test');
}
public function testCreateFromEmailAddressRepository() : void
{
$this->initField('Test', 'test', 'email');
$entity = $this->createEntityMock('Test');
$dataList = [
(object) [
'emailAddress' => 'ONE@test.com',
'lower' => 'one@test.com',
'primary' => true,
'optOut' => false,
'invalid' => false,
],
(object) [
'emailAddress' => 'TWO@test.com',
'lower' => 'two@test.com',
'primary' => false,
'optOut' => false,
'invalid' => true,
],
(object) [
'emailAddress' => 'THREE@test.com',
'lower' => 'three@test.com',
'primary' => false,
'optOut' => true,
'invalid' => false,
],
];
$this->initEmailAddressRepository($entity, $dataList);
$entity
->method('has')
->willReturnMap(
[
['testData', false],
['test', true],
]
);
$entity
->method('get')
->willReturnMap(
[
['testData', null],
['test', 'ONE@test.com'],
]
);
$group = $this->factory->createFromEntity($entity, 'test');
$this->assertEquals(3, $group->getCount());
$one = $group->getList()[0];
$two = $group->getList()[1];
$three = $group->getList()[2];
$this->assertEquals('ONE@test.com', $one->getAddress());
$this->assertTrue($two->isInvalid());
$this->assertTrue($three->isOptedOut());
$this->assertEquals('ONE@test.com', $group->getPrimary()->getAddress());
}
public function testCreateFromDataAttribute() : void
{
$this->initField('Test', 'test', 'email');
$entity = $this->createEntityMock('Test');
$dataList = [
(object) [
'emailAddress' => 'ONE@test.com',
'lower' => 'one@test.com',
'primary' => true,
'optOut' => false,
'invalid' => false,
],
(object) [
'emailAddress' => 'TWO@test.com',
'lower' => 'two@test.com',
'primary' => false,
'optOut' => false,
'invalid' => true,
],
(object) [
'emailAddress' => 'THREE@test.com',
'lower' => 'three@test.com',
'primary' => false,
'optOut' => true,
'invalid' => false,
],
];
$entity
->expects($this->once())
->method('has')
->with('testData')
->willReturn(true);
$entity
->expects($this->once())
->method('get')
->with('testData')
->willReturn($dataList);
$group = $this->factory->createFromEntity($entity, 'test');
$this->assertEquals(3, $group->getCount());
$one = $group->getList()[0];
$two = $group->getList()[1];
$three = $group->getList()[2];
$this->assertEquals('ONE@test.com', $one->getAddress());
$this->assertTrue($two->isInvalid());
$this->assertTrue($three->isOptedOut());
$this->assertEquals('ONE@test.com', $group->getPrimary()->getAddress());
}
public function testCreateEmpty1() : void
{
$this->initField('Test', 'test', 'email');
$entity = $this->createEntityMock('Test');
$dataList = [];
$this->initEmailAddressRepository($entity, $dataList);
$group = $this->factory->createFromEntity($entity, 'test');
$this->assertEquals(0, $group->getCount());
}
public function testCreateEmpty2() : void
{
$this->initField('Test', 'test', 'email');
$entity = $this->createEntityMock('Test');
$dataList = [];
$this->initEmailAddressRepository($entity, $dataList);
$entity
->method('has')
->willReturnMap(
[
['testData', false],
['test', true],
]
);
$entity
->method('get')
->willReturnMap(
[
['testData', null],
['test', null],
]
);
$group = $this->factory->createFromEntity($entity, 'test');
$this->assertEquals(0, $group->getCount());
}
}

View File

@@ -0,0 +1,249 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\EmailAddress;
use Espo\Core\Field\EmailAddress;
use Espo\Core\Field\EmailAddressGroup;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
class EmailAddressGroupTest extends TestCase
{
public function testEmpty()
{
$group = EmailAddressGroup::create();
$this->assertEquals(0, count($group->getAddressList()));
$this->assertEquals(0, count($group->getSecondaryList()));
$this->assertNull($group->getPrimary());
$this->assertNull($group->getPrimaryAddress());
$this->assertEquals(0, $group->getCount());
}
public function testDuplicate1()
{
$this->expectException(InvalidArgumentException::class);
EmailAddressGroup
::create([
EmailAddress::create('one@test.com'),
EmailAddress::create('one@test.com'),
]);
}
public function testDuplicate2()
{
$this->expectException(InvalidArgumentException::class);
EmailAddressGroup
::create([
EmailAddress::create('one@test.com'),
EmailAddress::create('ONE@test.com'),
]);
}
public function testWithPrimary1()
{
$primary = EmailAddress::create('primary@test.com')->invalid();
$group = EmailAddressGroup
::create()
->withPrimary($primary);
$this->assertEquals(1, count($group->getList()));
$this->assertEquals(0, count($group->getSecondaryList()));
$this->assertNotNull($group->getPrimary());
$this->assertEquals('primary@test.com', $group->getPrimary()->getAddress());
$this->assertEquals('primary@test.com', $group->getPrimaryAddress());
$primaryAnother = EmailAddress::create('primaryAnother@test.com');
$groupAnother = $group->withPrimary($primaryAnother);
$this->assertEquals(2, count($groupAnother->getList()));
$this->assertEquals(1, count($groupAnother->getSecondaryList()));
$this->assertEquals('primaryAnother@test.com', $groupAnother->getPrimary()->getAddress());
$this->assertEquals('primary@test.com', $groupAnother->getList()[1]->getAddress());
$this->assertTrue($groupAnother->getList()[1]->isInvalid());
$this->assertTrue($groupAnother->hasAddress('primary@test.com'));
$this->assertTrue($groupAnother->hasAddress('primaryAnother@test.com'));
}
public function testWithPrimary2()
{
$address = EmailAddress::create('one@test.com')->invalid();
$group = EmailAddressGroup
::create([$address])
->withAdded(
EmailAddress::create('two@test.com')
)
->withPrimary(
EmailAddress::create('two@test.com')
);
$this->assertEquals('two@test.com', $group->getPrimary()->getAddress());
$this->assertEquals(2, count($group->getList()));
}
public function testWithAdded1()
{
$address = EmailAddress::create('one@test.com')->invalid();
$group = EmailAddressGroup
::create([$address])
->withAdded(
EmailAddress::create('two@test.com')
);
$this->assertEquals('one@test.com', $group->getPrimary()->getAddress());
$this->assertEquals(2, count($group->getList()));
$this->assertEquals(2, $group->getCount());
}
public function testWithAddedList()
{
$group = EmailAddressGroup
::create()
->withAddedList([
EmailAddress::create('one@test.com'),
EmailAddress::create('two@test.com'),
]);
$this->assertEquals('one@test.com', $group->getPrimary()->getAddress());
$this->assertEquals(2, count($group->getList()));
}
public function testWithRemoved1()
{
$group = EmailAddressGroup
::create([
EmailAddress::create('one@test.com'),
EmailAddress::create('two@test.com'),
EmailAddress::create('three@test.com'),
])
->withRemoved(EmailAddress::create('two@test.com'));
$this->assertEquals('one@test.com', $group->getPrimary()->getAddress());
$this->assertEquals(2, count($group->getList()));
}
public function testWithRemoved2()
{
$group = EmailAddressGroup
::create([
EmailAddress::create('one@test.com'),
EmailAddress::create('two@test.com'),
EmailAddress::create('three@test.com'),
])
->withRemoved(EmailAddress::create('one@test.com'));
$this->assertEquals('two@test.com', $group->getPrimary()->getAddress());
$this->assertEquals(2, count($group->getList()));
}
public function testWithRemoved3()
{
$group = EmailAddressGroup
::create([
EmailAddress::create('one@test.com'),
])
->withRemoved(EmailAddress::create('one@test.com'));
$this->assertNull($group->getPrimary());
$this->assertEquals(0, count($group->getList()));
$this->assertEquals(0, $group->getCount());
}
public function testHasAddress()
{
$group = EmailAddressGroup
::create([
EmailAddress::create('one@test.com'),
EmailAddress::create('two@test.com'),
]);
$this->assertTrue($group->hasAddress('one@test.com'));
$this->assertTrue($group->hasAddress('two@test.com'));
$this->assertFalse($group->hasAddress('four@test.com'));
}
public function testGetByAddress()
{
$group = EmailAddressGroup
::create([
EmailAddress::create('one@test.com'),
EmailAddress::create('two@test.com'),
EmailAddress::create('three@test.com'),
]);
$this->assertEquals('one@test.com', $group->getByAddress('one@test.com')->getAddress());
$this->assertNull($group->getByAddress('four@test.com'));
}
public function testClone()
{
$group = EmailAddressGroup
::create([
EmailAddress::create('one@test.com'),
EmailAddress::create('two@test.com'),
EmailAddress::create('three@test.com'),
]);
$cloned = clone $group;
$this->assertEquals('one@test.com', $cloned->getByAddress('one@test.com')->getAddress());
$this->assertEquals($cloned->getPrimary()->getAddress(), $group->getPrimary()->getAddress());
$this->assertNotSame($cloned->getPrimary(), $group->getPrimary());
$this->assertNotSame($cloned->getList()[1], $group->getList()[1]);
}
}

View File

@@ -0,0 +1,82 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\EmailAddress;
use Espo\Core\Field\EmailAddress;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
class EmailAddressTest extends TestCase
{
public function testInvalidAddress()
{
$this->expectException(InvalidArgumentException::class);
EmailAddress::create('one');
}
public function testInvalidEmpty()
{
$this->expectException(InvalidArgumentException::class);
EmailAddress::create('');
}
public function testCloneInvalid()
{
$address = EmailAddress::create('test@test.com')->invalid();
$this->assertEquals('test@test.com', $address->getAddress());
$this->assertTrue($address->isInvalid());
$this->assertFalse($address->isOptedOut());
}
public function testCloneOptedOut()
{
$address = EmailAddress::create('test@test.com')->optedOut();
$this->assertFalse($address->isInvalid());
$this->assertTrue($address->isOptedOut());
}
public function testCloneNotOptedOut()
{
$address = EmailAddress::create('test@test.com')
->optedOut()
->notOptedOut()
->invalid()
->notInvalid();
$this->assertFalse($address->isInvalid());
$this->assertFalse($address->isOptedOut());
}
}

View File

@@ -0,0 +1,60 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\Link;
use Espo\Core\Field\Link;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
class LinkTest extends TestCase
{
public function testCreate()
{
$value = Link::create('id');
$this->assertEquals('id', $value->getId());
$this->assertEquals(null, $value->getName());
}
public function testBad1()
{
$this->expectException(InvalidArgumentException::class);
Link::create('');
}
public function testWithName()
{
$value = Link::create('id')->withName('Name');
$this->assertEquals('Name', $value->getName());
}
}

View File

@@ -0,0 +1,179 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\LinkMultiple;
use Espo\Core\Field\LinkMultiple;
use Espo\Core\Field\LinkMultipleItem;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
class LinkMultipleTest extends TestCase
{
public function testEmpty()
{
$value = LinkMultiple::create();
$this->assertEquals(0, count($value->getIdList()));
$this->assertEquals(0, count($value->getList()));
$this->assertEquals(0, $value->getCount());
}
public function testDuplicate()
{
$this->expectException(InvalidArgumentException::class);
LinkMultiple
::create([
LinkMultipleItem::create('1'),
LinkMultipleItem::create('1'),
]);
}
public function testWithAdded1()
{
$item = LinkMultipleItem::create('1')->withName('test-1');
$group = LinkMultiple
::create([$item])
->withAdded(
LinkMultipleItem::create('2')
);
$this->assertEquals(2, $group->getCount());
$this->assertEquals('1', $group->getList()[0]->getId());
$this->assertEquals('test-1', $group->getList()[0]->getName());
$this->assertEquals(null, $group->getList()[1]->getName());
}
public function testWithAddedId()
{
$item = LinkMultipleItem::create('1')->withName('test-1');
$group = LinkMultiple
::create([$item])
->withAddedId('2');
$this->assertEquals(2, $group->getCount());
$this->assertEquals('1', $group->getList()[0]->getId());
$this->assertEquals('test-1', $group->getList()[0]->getName());
$this->assertEquals('2', $group->getList()[1]->getId());
}
public function testWithAddedIdList(): void
{
$item = LinkMultipleItem::create('1')->withName('test-1');
$group = LinkMultiple
::create([$item])
->withAddedIdList(['2', '3']);
$this->assertEquals(3, $group->getCount());
$this->assertEquals('1', $group->getList()[0]->getId());
$this->assertEquals('test-1', $group->getList()[0]->getName());
$this->assertEquals('2', $group->getList()[1]->getId());
}
public function testWithAddedList()
{
$group = LinkMultiple
::create()
->withAddedList([
LinkMultipleItem::create('1'),
LinkMultipleItem::create('2'),
]);
$this->assertEquals(2, $group->getCount());
}
public function testWithRemoved1()
{
$group = LinkMultiple
::create([
LinkMultipleItem::create('1'),
LinkMultipleItem::create('2'),
LinkMultipleItem::create('3'),
])
->withRemoved(LinkMultipleItem::create('1'));
$this->assertEquals(2, $group->getCount());
}
public function testGetById()
{
$group = LinkMultiple
::create([
LinkMultipleItem::create('1'),
LinkMultipleItem::create('2'),
LinkMultipleItem::create('3'),
]);
$this->assertEquals('1', $group->getById('1')->getId());
$this->assertNull($group->getById('4'));
}
public function testClone()
{
$group = LinkMultiple
::create([
LinkMultipleItem::create('1'),
LinkMultipleItem::create('2'),
LinkMultipleItem::create('3'),
]);
$cloned = clone $group;
$this->assertEquals('1', $cloned->getById('1')->getId());
$this->assertNotSame($cloned->getList()[1], $group->getList()[1]);
}
public function testItemColumn()
{
$item = LinkMultipleItem
::create('1')
->withColumnValue('key', 'value');
$this->assertTrue($item->hasColumnValue('key'));
$this->assertFalse($item->hasColumnValue('key-bad'));
$this->assertEquals('value', $item->getColumnValue('key'));
$this->assertEquals(['key'], $item->getColumnList());
}
}

View File

@@ -0,0 +1,68 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\LinkParent;
use Espo\Core\Field\LinkParent;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
class LinkParentTest extends TestCase
{
public function testCreate()
{
$value = LinkParent::create('Test', 'id');
$this->assertEquals('Test', $value->getEntityType());
$this->assertEquals('id', $value->getId());
$this->assertEquals(null, $value->getName());
}
public function testBad1()
{
$this->expectException(InvalidArgumentException::class);
LinkParent::create('Test', '');
}
public function testBad2()
{
$this->expectException(InvalidArgumentException::class);
LinkParent::create('', 'id');
}
public function testWithName()
{
$value = LinkParent::create('Test', 'id')->withName('Name');
$this->assertEquals('Name', $value->getName());
}
}

View File

@@ -0,0 +1,88 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\PhoneNumber;
use Espo\Core\Field\PhoneNumber;
use Espo\Core\Field\PhoneNumber\PhoneNumberGroupAttributeExtractor;
use Espo\Core\Field\PhoneNumberGroup;
use PHPUnit\Framework\TestCase;
class PhoneNumberGroupAttributeExtractorTest extends TestCase
{
public function testExtract()
{
$group = PhoneNumberGroup
::create([
PhoneNumber::create('+1')->withType('Test-1'),
PhoneNumber::create('+2')->withType('Test-2')->optedOut(),
]);
$valueMap = (new PhoneNumberGroupAttributeExtractor())->extract($group, 'phoneNumber');
$this->assertEquals(
(object) [
'phoneNumber' => '+1',
'phoneNumberData' => [
(object) [
'phoneNumber' => '+1',
'type' => 'Test-1',
'primary' => true,
'optOut' => false,
'invalid' => false,
],
(object) [
'phoneNumber' => '+2',
'type' => 'Test-2',
'primary' => false,
'optOut' => true,
'invalid' => false,
],
]
],
$valueMap
);
}
public function testEmpty()
{
$group = PhoneNumberGroup
::create([]);
$valueMap = (new PhoneNumberGroupAttributeExtractor())->extract($group, 'phoneNumber');
$this->assertEquals(
(object) [
'phoneNumber' => null,
'phoneNumberData' => [],
],
$valueMap
);
}
}

View File

@@ -0,0 +1,317 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\PhoneNumber;
use Espo\Core\Field\PhoneNumber\PhoneNumberGroupFactory;
use Espo\Core\Utils\Metadata;
use Espo\ORM\Entity;
use Espo\ORM\EntityManager;
use Espo\Repositories\PhoneNumber as PhoneNumberRepository;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
use RuntimeException;
class PhoneNumberGroupFactoryTest extends TestCase
{
/**
* @var Metadata
*/
private $metadata;
/**
* @var EntityManager
*/
private $entityManager;
/**
* @var PhoneNumberRepository
*/
private $phoneNumberRepository;
/**
* @var PhoneNumberGroupFactory
*/
private $factory;
public function setUp() : void
{
$this->metadata = $this->createMock(Metadata::class);
$this->entityManager = $this->createMock(EntityManager::class);
$this->phoneNumberRepository = $this->createMock(PhoneNumberRepository::class);
$this->factory = new PhoneNumberGroupFactory($this->metadata, $this->entityManager);
$this->entityManager
->expects($this->any())
->method('getRepository')
->with('PhoneNumber')
->willReturn($this->phoneNumberRepository);
}
private function initField(string $entityType, string $field, string $type) : void
{
$this->metadata
->expects($this->any())
->method('get')
->with(['entityDefs', $entityType, 'fields', $field, 'type'])
->willReturn($type);
}
private function createEntityMock(string $entityType) : Entity
{
$entity = $this->createMock(Entity::class);
$entity
->expects($this->any())
->method('getEntityType')
->willReturn($entityType);
return $entity;
}
private function initPhoneNumberRepository(Entity $entity, array $dataList) : void
{
$this->phoneNumberRepository
->expects($this->once())
->method('getPhoneNumberData')
->with($entity)
->willReturn($dataList);
}
public function testIsCreatableFromEntityTrue() : void
{
$this->initField('Test', 'test', 'phone');
$entity = $this->createEntityMock('Test');
$this->assertTrue($this->factory->isCreatableFromEntity($entity, 'test'));
}
public function testIsCreatableFromEntityBad() : void
{
$this->initField('Test', 'test', 'varchar');
$entity = $this->createEntityMock('Test');
$this->assertFalse($this->factory->isCreatableFromEntity($entity, 'test'));
}
public function testCreateException() : void
{
$this->initField('Test', 'test', 'varchar');
$entity = $this->createEntityMock('Test');
$this->expectException(RuntimeException::class);
$this->factory->createFromEntity($entity, 'test');
}
public function testCreateFromPhoneNumberRepository() : void
{
$this->initField('Test', 'test', 'phone');
$entity = $this->createEntityMock('Test');
$dataList = [
(object) [
'phoneNumber' => '+1',
'type' => 'Test-1',
'primary' => true,
'optOut' => false,
'invalid' => false,
],
(object) [
'phoneNumber' => '+2',
'type' => 'Test-2',
'primary' => false,
'optOut' => false,
'invalid' => true,
],
(object) [
'phoneNumber' => '+3',
'type' => 'Test-3',
'primary' => false,
'optOut' => true,
'invalid' => false,
],
];
$this->initPhoneNumberRepository($entity, $dataList);
$entity
->method('has')
->willReturnMap(
[
['testData', false],
['test', true],
]
);
$entity
->method('get')
->willReturnMap(
[
['testData', null],
['test', '+1'],
]
);
$group = $this->factory->createFromEntity($entity, 'test');
$this->assertEquals(3, $group->getCount());
$one = $group->getList()[0];
$two = $group->getList()[1];
$three = $group->getList()[2];
$this->assertEquals('+1', $one->getNumber());
$this->assertTrue($two->isInvalid());
$this->assertTrue($three->isOptedOut());
$this->assertEquals('Test-1', $one->getType());
$this->assertEquals('+1', $group->getPrimary()->getNumber());
}
public function testCreateFromDataAttribute() : void
{
$this->initField('Test', 'test', 'phone');
$entity = $this->createEntityMock('Test');
$dataList = [
(object) [
'phoneNumber' => '+1',
'type' => '1',
'primary' => true,
'optOut' => false,
'invalid' => false,
],
(object) [
'phoneNumber' => '+2',
'type' => '2',
'primary' => false,
'optOut' => false,
'invalid' => true,
],
(object) [
'phoneNumber' => '+3',
'type' => '3',
'primary' => false,
'optOut' => true,
'invalid' => false,
],
];
$entity
->expects($this->once())
->method('has')
->with('testData')
->willReturn(true);
$entity
->expects($this->once())
->method('get')
->with('testData')
->willReturn($dataList);
$group = $this->factory->createFromEntity($entity, 'test');
$this->assertEquals(3, $group->getCount());
$one = $group->getList()[0];
$two = $group->getList()[1];
$three = $group->getList()[2];
$this->assertEquals('+1', $one->getNumber());
$this->assertTrue($two->isInvalid());
$this->assertTrue($three->isOptedOut());
$this->assertEquals('+1', $group->getPrimary()->getNumber());
}
public function testCreateEmpty1() : void
{
$this->initField('Test', 'test', 'phone');
$entity = $this->createEntityMock('Test');
$dataList = [];
$this->initPhoneNumberRepository($entity, $dataList);
$group = $this->factory->createFromEntity($entity, 'test');
$this->assertEquals(0, $group->getCount());
}
public function testCreateEmpty2() : void
{
$this->initField('Test', 'test', 'phone');
$entity = $this->createEntityMock('Test');
$dataList = [];
$this->initPhoneNumberRepository($entity, $dataList);
$entity
->method('has')
->willReturnMap(
[
['testData', false],
['test', true],
]
);
$entity
->method('get')
->willReturnMap(
[
['testData', null],
['test', null],
]
);
$group = $this->factory->createFromEntity($entity, 'test');
$this->assertEquals(0, $group->getCount());
}
}

View File

@@ -0,0 +1,237 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\PhoneNumber;
use Espo\Core\Field\PhoneNumber;
use Espo\Core\Field\PhoneNumberGroup;
use PHPUnit\Framework\TestCase;
use InvalidArgumentException;
class PhoneNumberGroupTest extends TestCase
{
public function testEmpty()
{
$group = PhoneNumberGroup::create();
$this->assertEquals(0, count($group->getNumberList()));
$this->assertEquals(0, count($group->getSecondaryList()));
$this->assertNull($group->getPrimary());
$this->assertNull($group->getPrimaryNumber());
$this->assertEquals(0, $group->getCount());
}
public function testDuplicate()
{
$this->expectException(InvalidArgumentException::class);
PhoneNumberGroup
::create([
PhoneNumber::create('+100'),
PhoneNumber::create('+100'),
]);
}
public function testWithPrimary1()
{
$primary = PhoneNumber::create('+000')->invalid();
$group = PhoneNumberGroup
::create()
->withPrimary($primary);
$this->assertEquals(1, count($group->getList()));
$this->assertEquals(0, count($group->getSecondaryList()));
$this->assertNotNull($group->getPrimary());
$this->assertEquals('+000', $group->getPrimary()->getNumber());
$this->assertEquals('+000', $group->getPrimaryNumber());
$primaryAnother = PhoneNumber::create('+001');
$groupAnother = $group->withPrimary($primaryAnother);
$this->assertEquals(2, count($groupAnother->getList()));
$this->assertEquals(1, count($groupAnother->getSecondaryList()));
$this->assertEquals('+001', $groupAnother->getPrimary()->getNumber());
$this->assertEquals('+000', $groupAnother->getList()[1]->getNumber());
$this->assertTrue($groupAnother->getList()[1]->isInvalid());
$this->assertTrue($groupAnother->hasNumber('+000'));
$this->assertTrue($groupAnother->hasNumber('+001'));
}
public function testWithPrimary2()
{
$number = PhoneNumber::create('+100')->invalid();
$group = PhoneNumberGroup
::create([$number])
->withAdded(
PhoneNumber::create('+200')
)
->withPrimary(
PhoneNumber::create('+200')
);
$this->assertEquals('+200', $group->getPrimary()->getNumber());
$this->assertEquals(2, count($group->getList()));
}
public function testWithAdded1()
{
$number = PhoneNumber::create('+100')->invalid();
$group = PhoneNumberGroup
::create([$number])
->withAdded(
PhoneNumber::create('+200')
);
$this->assertEquals('+100', $group->getPrimary()->getNumber());
$this->assertEquals(2, count($group->getList()));
$this->assertEquals(2, $group->getCount());
}
public function testWithAddedList()
{
$group = PhoneNumberGroup
::create()
->withAddedList([
PhoneNumber::create('+100'),
PhoneNumber::create('+200'),
]);
$this->assertEquals('+100', $group->getPrimary()->getNumber());
$this->assertEquals(2, count($group->getList()));
}
public function testWithRemoved1()
{
$group = PhoneNumberGroup
::create([
PhoneNumber::create('+100'),
PhoneNumber::create('+200'),
PhoneNumber::create('+300'),
])
->withRemoved(PhoneNumber::create('+200'));
$this->assertEquals('+100', $group->getPrimary()->getNumber());
$this->assertEquals(2, count($group->getList()));
}
public function testWithRemoved2()
{
$group = PhoneNumberGroup
::create([
PhoneNumber::create('+100'),
PhoneNumber::create('+200'),
PhoneNumber::create('+300'),
])
->withRemoved(PhoneNumber::create('+100'));
$this->assertEquals('+200', $group->getPrimary()->getNumber());
$this->assertEquals(2, count($group->getList()));
}
public function testWithRemoved3()
{
$group = PhoneNumberGroup
::create([
PhoneNumber::create('+100'),
])
->withRemoved(PhoneNumber::create('+100'));
$this->assertNull($group->getPrimary());
$this->assertEquals(0, count($group->getList()));
$this->assertEquals(0, $group->getCount());
}
public function testHasNumber()
{
$group = PhoneNumberGroup
::create([
PhoneNumber::create('+100'),
PhoneNumber::create('+200'),
]);
$this->assertTrue($group->hasNumber('+100'));
$this->assertTrue($group->hasNumber('+200'));
$this->assertFalse($group->hasNumber('+400'));
}
public function testGetByNumber()
{
$group = PhoneNumberGroup
::create([
PhoneNumber::create('+100'),
PhoneNumber::create('+200'),
PhoneNumber::create('+300'),
]);
$this->assertEquals('+100', $group->getByNumber('+100')->getNumber());
$this->assertNull($group->getByNumber('+400'));
}
public function testClone()
{
$group = PhoneNumberGroup
::create([
PhoneNumber::create('+100'),
PhoneNumber::create('+200'),
PhoneNumber::create('+300'),
]);
$cloned = clone $group;
$this->assertEquals('+100', $cloned->getByNumber('+100')->getNumber());
$this->assertEquals($cloned->getPrimary()->getNumber(), $group->getPrimary()->getNumber());
$this->assertNotSame($cloned->getPrimary(), $group->getPrimary());
$this->assertNotSame($cloned->getList()[1], $group->getList()[1]);
}
}

View File

@@ -0,0 +1,85 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM – Open Source CRM application.
* Copyright (C) 2014-2026 EspoCRM, Inc.
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace tests\unit\Espo\Core\Field\PhoneNumber;
use Espo\Core\Field\PhoneNumber;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
class PhoneNumberTest extends TestCase
{
public function testInvalidEmpty()
{
$this->expectException(InvalidArgumentException::class);
PhoneNumber::create('');
}
public function testCloneInvalid()
{
$number = PhoneNumber::create('+100')->invalid();
$this->assertEquals('+100', $number->getNumber());
$this->assertTrue($number->isInvalid());
$this->assertFalse($number->isOptedOut());
$this->assertNull($number->getType());
}
public function testCloneOptedOut()
{
$number = PhoneNumber::create('+100')->optedOut();
$this->assertFalse($number->isInvalid());
$this->assertTrue($number->isOptedOut());
}
public function testCloneWithType()
{
$number = PhoneNumber::createWithType('+100', 'Office');
$this->assertEquals('+100', $number->getNumber());
$this->assertEquals('Office', $number->getType());
}
public function testCloneNotOptedOut()
{
$number = PhoneNumber::create('+100')
->optedOut()
->notOptedOut()
->invalid()
->notInvalid();
$this->assertFalse($number->isInvalid());
$this->assertFalse($number->isOptedOut());
}
}