Новая сущность Kkt для ответов мониторинга (#8) + мелкий рефакторинг

- enum-константы перенесены в своё пространство Enums
- новые исключения EmptyMonitorDataException + NotEnoughMonitorDataException
- KktMonitor::getAll() теперь возвращает коллекцию объектов Kkt
- KktMonitor::getOne() теперь возвращает объект Kkt
- местами актуализированы return types + phpdoc

Покрытие тестами:
- 61% исключений
- 98% AtolClient (пока хз как покрыть 208-ую строку)
- 100% KktMonitor
- 100% Kkt
- 100% Client
- 100% Company
- 100% Entity
This commit is contained in:
2021-11-20 23:38:19 +08:00
parent 6551366d84
commit e1120051c1
24 changed files with 449 additions and 71 deletions

View File

@@ -46,7 +46,6 @@ class BasicTestCase extends TestCase
* Проверяет доступность API мониторинга
*
* @return bool
* @throws GuzzleException
*/
protected function isMonitoringOnline(): bool
{
@@ -54,9 +53,7 @@ class BasicTestCase extends TestCase
}
/**
* Пропускает текущий тест если API мониторинга недоступно
*
* @throws GuzzleException
* Пропускает текущий тест если API мониторинга недоступен
*/
protected function skipIfMonitoringIsOffline(): void
{
@@ -90,7 +87,7 @@ class BasicTestCase extends TestCase
* @param object|string $expected
* @param object|string $actual
*/
public function assertIsSameClass(object|string $expected, object|string $actual)
public function assertIsSameClass(object|string $expected, object|string $actual): void
{
$this->assertEquals(
is_object($expected) ? $expected::class : $expected,
@@ -104,7 +101,7 @@ class BasicTestCase extends TestCase
* @param string[] $parents
* @param object|string $actual
*/
public function assertExtendsClasses(array $parents, object|string $actual)
public function assertExtendsClasses(array $parents, object|string $actual): void
{
$this->checkClassesIntersection($parents, $actual, 'class_parents');
}
@@ -115,7 +112,7 @@ class BasicTestCase extends TestCase
* @param string[] $parents
* @param object|string $actual
*/
public function assertImplementsInterfaces(array $parents, object|string $actual)
public function assertImplementsInterfaces(array $parents, object|string $actual): void
{
$this->checkClassesIntersection($parents, $actual, 'class_implements');
}
@@ -126,7 +123,7 @@ class BasicTestCase extends TestCase
* @param string[] $parents
* @param object|string $actual
*/
public function assertUsesTraits(array $parents, object|string $actual)
public function assertUsesTraits(array $parents, object|string $actual): void
{
$this->checkClassesIntersection($parents, $actual, 'class_uses');
}

View File

@@ -10,8 +10,8 @@
namespace AtolOnlineTests;
use AtolOnline\{
Constants\SnoTypes,
Entities\Company,
Enums\SnoTypes,
Exceptions\InvalidEmailException,
Exceptions\InvalidInnLengthException,
Exceptions\InvalidPaymentAddressException,

View File

@@ -10,10 +10,10 @@
namespace AtolOnlineTests;
use AtolOnline\{
Constants\PaymentMethods,
Constants\PaymentObjects,
Constants\VatTypes,
Entities\Item,
Enums\PaymentMethods,
Enums\PaymentObjects,
Enums\VatTypes,
Exceptions\BasicTooManyException,
Exceptions\TooHighPriceException,
Exceptions\TooLongNameException,

153
tests/KktEntityTest.php Normal file
View File

@@ -0,0 +1,153 @@
<?php
/*
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
*
* This code is licensed under MIT.
* Этот код распространяется по лицензии MIT.
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
*/
declare(strict_types = 1);
namespace AtolOnlineTests;
use AtolOnline\Entities\Kkt;
use AtolOnline\Exceptions\EmptyMonitorDataException;
use AtolOnline\Exceptions\NotEnoughMonitorDataException;
use DateTime;
use Exception;
class KktEntityTest extends BasicTestCase
{
/**
* @var array Данные для создания объекта ККТ
*/
private array $sample_data = [
'serialNumber' => '00107703864827',
'registrationNumber' => '0000000003027865',
'deviceNumber' => 'KKT024219',
'fiscalizationDate' => '2019-07-22T14:03:00+00:00',
'fiscalStorageExpiration' => '2020-11-02T21:00:00+00:00',
'signedDocuments' => 213350,
'fiscalStoragePercentageUse' => 85.34,
'fiscalStorageINN' => '3026455760',
'fiscalStorageSerialNumber' => '9999078902004339',
'fiscalStoragePaymentAddress' => 'test.qa.ru',
'groupCode' => 'test-qa-ru_14605',
'timestamp' => '2019-12-05T10:45:30+00:00',
'isShiftOpened' => true,
'shiftNumber' => 126,
'shiftReceipt' => 2278,
//'unsentDocs' => 123,
'firstUnsetDocTimestamp' => 'there must be timestamp, but we want to get exception here to get string',
'networkErrorCode' => 2,
];
/**
* Тестирует создание объекта ККТ с валидными данными
*
* @covers \AtolOnline\Entities\Kkt::__construct
* @covers \AtolOnline\Entities\Kkt::__get
* @covers \AtolOnline\Entities\Kkt::jsonSerialize
* @covers \AtolOnline\Entities\Kkt::__toString
* @throws Exception
*/
public function testConstructor(): void
{
$kkt = new Kkt((object)$this->sample_data);
$this->assertIsSameClass(Kkt::class, $kkt);
$this->assertAtolable($kkt);
}
/**
* Тестирует исключение при попытке создать объект ККТ без данных от монитора
*
* @covers \AtolOnline\Entities\Kkt::__construct
* @covers \AtolOnline\Exceptions\EmptyMonitorDataException
* @throws EmptyMonitorDataException
* @throws NotEnoughMonitorDataException
*/
public function testEmptyMonitorDataException(): void
{
$this->expectException(EmptyMonitorDataException::class);
new Kkt((object)[]);
}
/**
* Тестирует исключение при попытке создать объект ККТ без данных от монитора
*
* @covers \AtolOnline\Entities\Kkt::__construct
* @covers \AtolOnline\Exceptions\NotEnoughMonitorDataException
* @throws EmptyMonitorDataException
* @throws NotEnoughMonitorDataException
*/
public function testNotEnoughMonitorDataException(): void
{
$this->expectException(NotEnoughMonitorDataException::class);
new Kkt((object)[
'fiscalizationDate' => '2021-11-20T10:21:00+00:00',
]);
}
/**
* Тестирует получение атрибутов через магический геттер
*
* @covers \AtolOnline\Entities\Kkt::__get
* @throws EmptyMonitorDataException
* @throws NotEnoughMonitorDataException
*/
public function testMagicGetter(): void
{
$kkt = new Kkt((object)$this->sample_data);
// string
$this->assertNotNull($kkt->serialNumber);
$this->assertIsString($kkt->serialNumber);
$this->assertEquals($this->sample_data['serialNumber'], $kkt->serialNumber);
// int
$this->assertNotNull($kkt->signedDocuments);
$this->assertIsInt($kkt->signedDocuments);
// float
$this->assertNotNull($kkt->signedDocuments);
$this->assertIsFloat($kkt->fiscalStoragePercentageUse);
// null
$this->assertNull($kkt->unsentDocs);
// DateTime
$this->assertNotNull($kkt->fiscalizationDate);
$this->assertIsSameClass(DateTime::class, $kkt->fiscalizationDate);
}
/**
* Тестирует исключение при попытке получить некорректный DateTime через магический геттер
*
* @covers \AtolOnline\Entities\Kkt::__get
* @throws EmptyMonitorDataException
* @throws NotEnoughMonitorDataException
*/
public function testDateTimeException(): void
{
$this->expectException(Exception::class);
(new Kkt((object)$this->sample_data))->firstUnsetDocTimestamp;
}
/**
* Тестирует получение данных о сетевой ошибке
*
* @covers \AtolOnline\Entities\Kkt::getNetworkError
* @throws EmptyMonitorDataException
* @throws NotEnoughMonitorDataException
*/
public function testGetNetworkError(): void
{
$kkt = new Kkt((object)$this->sample_data);
$this->assertIsObject($kkt->getNetworkError());
$this->assertEquals((object)[
'code' => $kkt->networkErrorCode,
'text' => $kkt::ERROR_CODES[$kkt->networkErrorCode],
], $kkt->getNetworkError());
}
}

View File

@@ -5,9 +5,12 @@ namespace AtolOnlineTests;
use AtolOnline\Api\AtolClient;
use AtolOnline\Api\KktMonitor;
use AtolOnline\Api\KktResponse;
use AtolOnline\Entities\Kkt;
use AtolOnline\Exceptions\AuthFailedException;
use AtolOnline\Exceptions\EmptyLoginException;
use AtolOnline\Exceptions\EmptyMonitorDataException;
use AtolOnline\Exceptions\EmptyPasswordException;
use AtolOnline\Exceptions\NotEnoughMonitorDataException;
use AtolOnline\Exceptions\TooLongLoginException;
use AtolOnline\Exceptions\TooLongPasswordException;
use AtolOnline\Helpers;
@@ -19,12 +22,29 @@ use GuzzleHttp\Exception\GuzzleException;
*/
class KktMonitorTest extends BasicTestCase
{
/**
* Возвращает объект клиента для тестирования с тестовым API АТОЛ
*
* @return AtolClient
* @throws EmptyLoginException
* @throws EmptyPasswordException
* @throws TooLongLoginException
* @throws TooLongPasswordException
*/
private function newTestClient(): KktMonitor
{
$credentials = TestEnvParams::FFD105();
return (new KktMonitor(true))
->setLogin($credentials['login'])
->setPassword($credentials['password']);
}
/**
* Тестирует успешное создание объекта монитора без аргументов конструктора
*
* @covers \AtolOnline\Api\KktMonitor::__construct
*/
public function testConstructorWithoutArgs()
public function testConstructorWithoutArgs(): void
{
$client = new KktMonitor();
$this->assertIsObject($client);
@@ -45,7 +65,7 @@ class KktMonitorTest extends BasicTestCase
* @throws TooLongLoginException
* @throws TooLongPasswordException
*/
public function testConstructorWithArgs()
public function testConstructorWithArgs(): void
{
$client = new KktMonitor(false, 'login', 'password', []);
$this->assertIsObject($client);
@@ -62,7 +82,7 @@ class KktMonitorTest extends BasicTestCase
* @throws EmptyLoginException
* @throws TooLongLoginException
*/
public function testLogin()
public function testLogin(): void
{
$client = new KktMonitor(login: 'login');
$this->assertEquals('login', $client->getLogin());
@@ -81,7 +101,7 @@ class KktMonitorTest extends BasicTestCase
* @covers \AtolOnline\Api\KktMonitor::setLogin
* @covers \AtolOnline\Exceptions\EmptyLoginException
*/
public function testEmptyLoginException()
public function testEmptyLoginException(): void
{
$this->expectException(EmptyLoginException::class);
new KktMonitor(login: '');
@@ -98,7 +118,7 @@ class KktMonitorTest extends BasicTestCase
* @throws TooLongLoginException
* @throws TooLongPasswordException
*/
public function testTooLongLoginException()
public function testTooLongLoginException(): void
{
$this->expectException(TooLongLoginException::class);
new KktMonitor(login: Helpers::randomStr(101));
@@ -113,7 +133,7 @@ class KktMonitorTest extends BasicTestCase
* @throws EmptyPasswordException
* @throws TooLongPasswordException
*/
public function testPassword()
public function testPassword(): void
{
$client = new KktMonitor(password: 'password');
$this->assertEquals('password', $client->getPassword());
@@ -132,7 +152,7 @@ class KktMonitorTest extends BasicTestCase
* @covers \AtolOnline\Api\KktMonitor::setPassword
* @covers \AtolOnline\Exceptions\EmptyPasswordException
*/
public function testEmptyPasswordException()
public function testEmptyPasswordException(): void
{
$this->expectException(EmptyPasswordException::class);
new KktMonitor(password: '');
@@ -148,7 +168,7 @@ class KktMonitorTest extends BasicTestCase
* @throws TooLongLoginException
* @throws TooLongPasswordException
*/
public function testConstructorWithLongPassword()
public function testConstructorWithLongPassword(): void
{
$this->expectException(TooLongPasswordException::class);
new KktMonitor(password: Helpers::randomStr(101));
@@ -161,7 +181,7 @@ class KktMonitorTest extends BasicTestCase
* @covers \AtolOnline\Api\KktMonitor::isTestMode
* @covers \AtolOnline\Api\KktMonitor::setTestMode
*/
public function testTestMode()
public function testTestMode(): void
{
$client = new KktMonitor();
$this->assertTrue($client->isTestMode());
@@ -182,23 +202,6 @@ class KktMonitorTest extends BasicTestCase
$this->assertFalse($client->isTestMode());
}
/**
* Возвращает объект клиента для тестирования с тестовым API АТОЛ
*
* @return AtolClient
* @throws EmptyLoginException
* @throws EmptyPasswordException
* @throws TooLongLoginException
* @throws TooLongPasswordException
*/
private function newTestClient(): KktMonitor
{
$credentials = TestEnvParams::FFD105();
return (new KktMonitor(true))
->setLogin($credentials['login'])
->setPassword($credentials['password']);
}
/**
* Тестирует авторизацию
*
@@ -207,6 +210,7 @@ class KktMonitorTest extends BasicTestCase
* @covers \AtolOnline\Api\KktMonitor::getAuthEndpoint
* @covers \AtolOnline\Api\KktMonitor::doAuth
* @covers \AtolOnline\Api\KktMonitor::auth
* @covers \AtolOnline\Exceptions\AuthFailedException
* @throws EmptyLoginException
* @throws EmptyPasswordException
* @throws TooLongLoginException
@@ -214,7 +218,7 @@ class KktMonitorTest extends BasicTestCase
* @throws AuthFailedException
* @throws GuzzleException
*/
public function testAuth()
public function testAuth(): void
{
$this->skipIfMonitoringIsOffline();
$result = $this->newTestClient()->auth();
@@ -227,6 +231,7 @@ class KktMonitorTest extends BasicTestCase
* @depends testAuth
* @covers \AtolOnline\Api\KktMonitor::setToken
* @covers \AtolOnline\Api\KktMonitor::getToken
* @covers \AtolOnline\Exceptions\AuthFailedException
* @throws AuthFailedException
* @throws EmptyLoginException
* @throws EmptyPasswordException
@@ -234,7 +239,7 @@ class KktMonitorTest extends BasicTestCase
* @throws TooLongLoginException
* @throws TooLongPasswordException
*/
public function testGetToken()
public function testGetToken(): void
{
$client = new KktMonitor();
$this->assertNull($client->getToken());
@@ -250,6 +255,7 @@ class KktMonitorTest extends BasicTestCase
*
* @depends testAuth
* @covers \AtolOnline\Api\KktMonitor::getResponse
* @covers \AtolOnline\Exceptions\AuthFailedException
* @throws AuthFailedException
* @throws EmptyLoginException
* @throws EmptyPasswordException
@@ -257,7 +263,7 @@ class KktMonitorTest extends BasicTestCase
* @throws TooLongLoginException
* @throws TooLongPasswordException
*/
public function testGetResponse()
public function testGetResponse(): void
{
$this->skipIfMonitoringIsOffline();
$client = $this->newTestClient();
@@ -273,6 +279,7 @@ class KktMonitorTest extends BasicTestCase
* @covers \AtolOnline\Api\AtolClient::getUrlToMethod
* @covers \AtolOnline\Api\KktMonitor::fetchAll
* @covers \AtolOnline\Api\KktMonitor::getAll
* @covers \AtolOnline\Exceptions\AuthFailedException
* @throws AuthFailedException
* @throws EmptyLoginException
* @throws EmptyPasswordException
@@ -280,7 +287,7 @@ class KktMonitorTest extends BasicTestCase
* @throws TooLongLoginException
* @throws TooLongPasswordException
*/
public function testMonitorGetAll()
public function testMonitorGetAll(): void
{
$this->skipIfMonitoringIsOffline();
$client = $this->newTestClient();
@@ -289,6 +296,7 @@ class KktMonitorTest extends BasicTestCase
$this->assertNotEmpty($client->getResponse()->getContent());
$this->assertIsCollection($kkts);
$this->assertTrue($kkts->count() > 0);
$this->assertIsSameClass(Kkt::class, $kkts->random());
}
/**
@@ -299,24 +307,30 @@ class KktMonitorTest extends BasicTestCase
* @covers \AtolOnline\Api\AtolClient::getUrlToMethod
* @covers \AtolOnline\Api\KktMonitor::fetchOne
* @covers \AtolOnline\Api\KktMonitor::getOne
* @covers \AtolOnline\Entities\Kkt::__construct
* @covers \AtolOnline\Entities\Kkt::__get
* @covers \AtolOnline\Entities\Kkt::jsonSerialize
* @covers \AtolOnline\Entities\Kkt::__toString
* @throws AuthFailedException
* @throws EmptyLoginException
* @throws EmptyPasswordException
* @throws GuzzleException
* @throws TooLongLoginException
* @throws TooLongPasswordException
* @throws EmptyMonitorDataException
* @throws NotEnoughMonitorDataException
*/
public function testGetOne()
public function testMOnitorGetOne(): void
{
$this->skipIfMonitoringIsOffline();
$client = $this->newTestClient();
$client->auth();
$kkts = $client->getAll();
$serial_number = $kkts->first()->serialNumber;
$client->getOne($serial_number);
$this->assertIsSameClass(KktResponse::class, $client->getResponse());
$serial_number = $client->getAll()->random()->serialNumber;
$kkt = $client->getOne($serial_number);
$this->assertNotEmpty($client->getResponse());
$this->assertNotNull($client->getResponse()->data->serialNumber);
$this->assertEquals($serial_number, $client->getResponse()->data->serialNumber);
$this->assertIsSameClass(Kkt::class, $kkt);
$this->assertAtolable($kkt);
$this->assertNotNull($kkt->serialNumber);
$this->assertEquals($serial_number, $kkt->serialNumber);
}
}

View File

@@ -10,9 +10,8 @@
namespace AtolOnlineTests;
use AtolOnline\{
Constants\VatTypes,
Entities\Vat
};
Entities\Vat,
Enums\VatTypes};
/**
* Class VatTest