From bdcdcf9f57c9692a6b3b9adf5c2f00191e268e5f Mon Sep 17 00:00:00 2001 From: Alexander Hofbauer Date: Wed, 19 Feb 2025 09:40:00 +0100 Subject: [PATCH] Modernize library *) Use GitHub Actions instead of Travis *) Use PHPUnit 10.5 code coverage *) PHP 8.1 or greater code compatibility *) Type hints *) Constants *) Final classes and interfaces for Client and Validator *) Exception interface --- .gitattributes | 2 - .github/workflows/ci.yml | 34 +++ .gitignore | 4 +- .scrutinizer.yml | 5 - .travis.yml | 24 -- README.md | 7 +- composer.json | 13 +- phpstan-baseline.neon | 19 ++ phpstan.neon.dist | 8 + phpunit.xml.dist | 29 +- src/Exception/ServiceUnreachableException.php | 13 + src/Exception/ViesException.php | 7 +- src/Exception/ViesExceptionInterface.php | 7 + src/Validator.php | 69 ++--- src/ValidatorInterface.php | 19 ++ src/Vies/Client.php | 78 +++--- src/Vies/ClientInterface.php | 25 ++ src/Vies/Response/CheckVatResponse.php | 55 +--- tests/ValidatorTest.php | 255 ++++++++---------- tests/Vies/ClientTest.php | 18 +- 20 files changed, 359 insertions(+), 332 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .scrutinizer.yml delete mode 100644 .travis.yml create mode 100644 phpstan-baseline.neon create mode 100644 phpstan.neon.dist create mode 100644 src/Exception/ServiceUnreachableException.php create mode 100644 src/Exception/ViesExceptionInterface.php create mode 100644 src/ValidatorInterface.php create mode 100644 src/Vies/ClientInterface.php diff --git a/.gitattributes b/.gitattributes index cf62a55..d117092 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,5 @@ /tests export-ignore /.gitattributes export-ignore /.gitignore export-ignore -/.scrutinizer.yml export-ignore -/.travis.yml export-ignore /phpunit.xml.dist export-ignore /README.md export-ignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..27fa662 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,34 @@ +name: Tests + +on: + push: + pull_request: + +jobs: + tests: + name: "Tests" + runs-on: ubuntu-latest + + strategy: + matrix: + php-version: ['8.1', '8.2', '8.3', '8.4'] + include: + - { php-version: '8.1', dependencies: '--prefer-lowest' } + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + coverage: xdebug + + - name: Install PHP dependencies + run: composer update --no-interaction ${{ matrix.dependencies }} + + - name: Run tests + run: vendor/bin/phpunit + + - name: Run PHPStan + run: vendor/bin/phpstan diff --git a/.gitignore b/.gitignore index 4f4acd3..bc617b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ +.idea/ +.phpunit.cache/ vendor/ -composer.lock \ No newline at end of file +composer.lock diff --git a/.scrutinizer.yml b/.scrutinizer.yml deleted file mode 100644 index e2cb043..0000000 --- a/.scrutinizer.yml +++ /dev/null @@ -1,5 +0,0 @@ -imports: - - php - -tools: - external_code_coverage: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a792ef4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: php - -php: - - 5.6 - - 7.0 - - 7.1 - - 7.2 - - 7.3 - - 7.4 - -cache: - directories: - - $HOME/.composer/cache - -before_script: - - travis_retry composer install --dev - -script: - - composer validate --strict - - vendor/bin/phpunit --coverage-clover=coverage.clover - -after_script: - - wget https://scrutinizer-ci.com/ocular.phar - - php ocular.phar code-coverage:upload --format=php-clover coverage.clover diff --git a/README.md b/README.md index 09bab00..d55feaa 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,5 @@ VATIN ===== -[![Build Status](https://travis-ci.org/ddeboer/vatin.svg?branch=master)](https://travis-ci.org/ddeboer/vatin) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/ddeboer/vatin/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/ddeboer/vatin/?branch=master) -[![Code Coverage](https://scrutinizer-ci.com/g/ddeboer/vatin/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/ddeboer/vatin/?branch=master) [![Latest Stable Version](https://poser.pugx.org/ddeboer/vatin/v/stable.png)](https://packagist.org/packages/ddeboer/vatin) A small PHP library for validating VAT identification numbers (VATINs). @@ -27,7 +24,7 @@ Validate a VAT number’s format: ```php use Ddeboer\Vatin\Validator; -$validator = new Validator; +$validator = new Validator(); $bool = $validator->isValid('NL123456789B01'); ``` @@ -37,6 +34,6 @@ Information Exchange System (VIES)](https://ec.europa.eu/taxation_customs/vies/f ```php use Ddeboer\Vatin\Validator; -$validator = new Validator; +$validator = new Validator(); $bool = $validator->isValid('NL123456789B01', true); ``` diff --git a/composer.json b/composer.json index 3a3c084..9514978 100644 --- a/composer.json +++ b/composer.json @@ -15,11 +15,15 @@ } ], "require": { - "php": ">=5.6.0" + "php": ">=8.1" }, "require-dev": { "ext-soap": "*", - "phpunit/phpunit": "^5.7 || ^6.5" + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-symfony": "^2.0", + "phpstan/extension-installer": "^1.4", + "phpunit/phpunit": "^10.5" }, "suggest": { "ext-soap": "Required if you want to check the VAT number via VIES" @@ -33,5 +37,10 @@ "psr-4": { "Ddeboer\\Vatin\\Test\\": "tests/" } + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true + } } } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..a0ecf9d --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,19 @@ +parameters: + ignoreErrors: + - + message: '#^Method Ddeboer\\Vatin\\Vies\\Client\:\:checkVat\(\) should return Ddeboer\\Vatin\\Vies\\Response\\CheckVatResponse but returns mixed\.$#' + identifier: return.type + count: 1 + path: src/Vies/Client.php + + - + message: '#^Readonly property Ddeboer\\Vatin\\Vies\\Response\\CheckVatResponse\:\:\$date is assigned outside of the constructor\.$#' + identifier: property.readOnlyAssignNotInConstructor + count: 1 + path: src/Vies/Response/CheckVatResponse.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''DateTimeImmutable'' and DateTimeImmutable will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 1 + path: tests/Vies/ClientTest.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..3a36a39 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,8 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: max + paths: + - src + - tests diff --git a/phpunit.xml.dist b/phpunit.xml.dist index f2bf738..1f57890 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,15 +1,28 @@ - - + ./tests/ - - - ./src - - - \ No newline at end of file + + + ./src + + + diff --git a/src/Exception/ServiceUnreachableException.php b/src/Exception/ServiceUnreachableException.php new file mode 100644 index 0000000..ac0f6b6 --- /dev/null +++ b/src/Exception/ServiceUnreachableException.php @@ -0,0 +1,13 @@ + * @link http://ec.europa.eu/taxation_customs/vies/faq.html?locale=lt#item_11 */ - private $patterns = array( + private const PATTERNS = [ 'AT' => 'U[A-Z\d]{8}', 'BE' => '[01]{1}\d{9}', 'BG' => '\d{9,10}', @@ -52,38 +52,19 @@ class Validator 'SI' => '\d{8}', 'SK' => '\d{10}', 'XI' => '\d{9,12}|(GD|HA)\d{3}' - ); - - /** - * Client for the VIES web service - * - * @var Client - */ - private $viesClient; + ]; /** * Constructor * - * @param Client|null $viesClient Client for the VIES web service + * @param ClientInterface $viesClient Client for the VIES web service */ - public function __construct(Client $viesClient = null) - { - $this->viesClient = $viesClient; + public function __construct( + private readonly ClientInterface $viesClient = new Client() + ) { } - /** - * Returns true if value is a valid VAT identification number, false - * otherwise - * - * @param string $value Value - * @param bool $checkExistence In addition to checking the VATIN's format - * for validity, also check whether the VATIN - * exists. This requires a call to the VIES - * web service. - * - * @return bool - */ - public function isValid($value, $checkExistence = false) + public function isValid(?string $value, bool $checkExistence = false): bool { if (null === $value || '' === $value) { return false; @@ -96,42 +77,24 @@ public function isValid($value, $checkExistence = false) return false; } - if (0 === preg_match('/^(?:'.$this->patterns[$countryCode].')$/', $vatin)) { + if (0 === preg_match('/^(?:'.self::PATTERNS[$countryCode].')$/', $vatin)) { return false; } if (true === $checkExistence) { - $result = $this->getViesClient()->checkVat($countryCode, $vatin); + $result = $this->viesClient->checkVat($countryCode, $vatin); - return $result->isValid(); + return $result->valid; } return true; } /** - * Returns true if value is valid country code, false otherwise - * - * @param string $value Value - * - * @return bool + * @return bool true if value is valid country code, false otherwise */ - private function isValidCountryCode($value) + private function isValidCountryCode(string $value): bool { - return isset($this->patterns[$value]); - } - - /** - * Get VIES client - * - * @return Client - */ - private function getViesClient() - { - if ($this->viesClient === null) { - $this->viesClient = new Client(); - } - - return $this->viesClient; + return isset(self::PATTERNS[$value]); } } diff --git a/src/ValidatorInterface.php b/src/ValidatorInterface.php new file mode 100644 index 0000000..0ec2e20 --- /dev/null +++ b/src/ValidatorInterface.php @@ -0,0 +1,19 @@ + */ - private $soapClient; + private const CLASS_MAP = [ + 'checkVatResponse' => CheckVatResponse::class, + ]; /** - * SOAP classmap - * - * @var array + * SOAP client */ - private $classmap = [ - 'checkVatResponse' => 'Ddeboer\Vatin\Vies\Response\CheckVatResponse' - ]; + private ?\SoapClient $soapClient = null; /** * Constructor * - * @param string|null $wsdl URL to WSDL + * @param string $wsdl URL to WSDL */ - public function __construct($wsdl = null) - { - if ($wsdl) { - $this->wsdl = $wsdl; - } + public function __construct( + private readonly string $wsdl = self::DEFAULT_WSDL + ) { } - /** - * Check VAT - * - * @param string $countryCode Country code - * @param string $vatNumber VAT number - * - * @return Response\CheckVatResponse - * @throws ViesException - */ - public function checkVat($countryCode, $vatNumber) + public function checkVat(string $countryCode, string $vatNumber): Response\CheckVatResponse { try { - return $this->getSoapClient()->checkVat( + // silenced error because exceptions are thrown according to the client configuration + $client = @$this->getSoapClient(); + + return $client->checkVat( [ 'countryCode' => $countryCode, 'vatNumber' => $vatNumber ] ); - } catch (SoapFault $e) { - throw new ViesException('Error communicating with VIES service', 0, $e); + } catch (\SoapFault $e) { + throw $this->buildExceptionFromSoapFault($e); } } /** - * Get SOAP client + * @return \SoapClient a single instance of the local soap client * - * @return \SoapClient + * @throws \SoapFault */ - private function getSoapClient() + private function getSoapClient(): \SoapClient { if (null === $this->soapClient) { $this->soapClient = new \SoapClient( $this->wsdl, [ - 'classmap' => $this->classmap, + 'classmap' => self::CLASS_MAP, 'user_agent' => 'Mozilla', // the request fails unless a (dummy) user agent is specified 'exceptions' => true, ] @@ -88,4 +75,13 @@ private function getSoapClient() return $this->soapClient; } + + private function buildExceptionFromSoapFault(\SoapFault $e): ViesExceptionInterface + { + if (str_contains($e->faultstring, 'failed to load')) { + return new ServiceUnreachableException($e); + } + + return new ViesException($e); + } } diff --git a/src/Vies/ClientInterface.php b/src/Vies/ClientInterface.php new file mode 100644 index 0000000..b1dd2af --- /dev/null +++ b/src/Vies/ClientInterface.php @@ -0,0 +1,25 @@ +countryCode; - } - - public function getVatNumber() - { - return $this->vatNumber; + public function __construct( + public readonly string $countryCode, + public readonly string $vatNumber, + public readonly \DateTimeImmutable $date, + public readonly bool $valid, + public readonly ?string $name, + public readonly ?string $address, + ) { } - public function getRequestDate() + public function __set(string $name, mixed $value): void { - if (!$this->requestDate instanceof \DateTime) { - $this->requestDate = new \DateTime($this->requestDate); + if ('requestDate' === $name && is_string($value)) { + $this->date = new \DateTimeImmutable($value); } - - return $this->requestDate; - } - - public function isValid() - { - return $this->valid; - } - - public function getName() - { - return $this->name; - } - - public function getAddress() - { - return $this->address; } -} \ No newline at end of file +} diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php index e455e5d..4b59b59 100644 --- a/tests/ValidatorTest.php +++ b/tests/ValidatorTest.php @@ -2,194 +2,175 @@ namespace Ddeboer\Vatin\Test; +use Ddeboer\Vatin\Exception\ServiceUnreachableException; +use Ddeboer\Vatin\Exception\ViesException; use Ddeboer\Vatin\Validator; -use Ddeboer\Vatin\Test\Mock\Vies\Response\CheckVatResponse; use Ddeboer\Vatin\Vies\Client; +use Ddeboer\Vatin\Vies\ClientInterface; +use Ddeboer\Vatin\Vies\Response\CheckVatResponse; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; class ValidatorTest extends TestCase { - private $validator; - - public function setUp() - { - $this->validator = new Validator(); - } - - /** - * @dataProvider getValidVatins - */ - public function testValid($value) + #[DataProvider('getValidVatins')] + public function testValid(string $value): void { - $this->assertTrue($this->validator->isValid($value)); + $validator = new Validator(); + $this->assertTrue($validator->isValid($value)); } - /** - * @dataProvider getInvalidVatins - */ - public function testInvalid($value) + #[DataProvider('getInvalidVatins')] + public function testInvalid(?string $value): void { - $this->assertFalse($this->validator->isValid($value)); + $validator = new Validator(); + $this->assertFalse($validator->isValid($value)); } - public function testValidWithVies() + public function testValidWithVies(): void { $client = $this->getViesClientMock(); $client ->expects($this->once()) ->method('checkVat') ->with('NL', '002065538B01') - ->willReturn($this->getCheckVatResponseMock(true)); + ->willReturn(new CheckVatResponse( + 'NL', '002065538B01', new \DateTimeImmutable(), true, '---', '---', + )); - $this->validator = new Validator($client); - $this->assertTrue($this->validator->isValid('NL002065538B01', true)); + $validator = new Validator($client); + $this->assertTrue($validator->isValid('NL002065538B01', true)); } - public function testInvalidWithVies() + public function testInvalidWithVies(): void { $client = $this->getViesClientMock(); $client ->expects($this->once()) ->method('checkVat') ->with('NL', '123456789B01') - ->willReturn($this->getCheckVatResponseMock(false)); + ->willReturn(new CheckVatResponse( + 'NL', '123456789B01', new \DateTimeImmutable(), false, '---', '---', + )); - $this->validator = new Validator($client); - $this->assertFalse($this->validator->isValid('NL123456789B01', true)); + $validator = new Validator($client); + $this->assertFalse($validator->isValid('NL123456789B01', true)); } - /** - * @expectedException \Ddeboer\Vatin\Exception\ViesException - */ - public function testWrongConnectionThrowsException() + public function testWrongConnectionThrowsException(): void { - $this->validator = new Validator(new Client('meh')); - $this->validator->isValid('NL002065538B01', true); + $this->expectException(ServiceUnreachableException::class); + + $validator = new Validator(new Client('meh')); + $validator->isValid('NL002065538B01', true); } /** - * @return array + * @return list */ - public function getValidVatins() + public static function getValidVatins(): array { - return array( + return [ // Examples from Wikipedia (https://en.wikipedia.org/wiki/VAT_identification_number) - array('ATU99999999'), // Austria - array('BE0999999999'), // Belgium - array('BE1999999999'), // Belgium - array('HR12345678901'), // Croatia - array('CY99999999L'), // Cyprus - array('DK99999999'), // Denmark - array('FI99999999'), // Finland - array('FRXX999999999'), // France - array('DE999999999'), // Germany - array('HU12345678'), // Hungary - array('IE1234567T'), // Ireland - array('IE1234567TW'), // Ireland - array('IE1234567FA'), // Ireland (since January 2013) - array('NL999999999B99'), // The Netherlands - array('NO999999999'), // Norway - array('NO999999999MVA'), // Norway (including MVA) - array('ES99999999R'), // Spain - array('SE999999999901'), // Sweden - array('CHE-123.456.788 TVA'), // Switzerland - array('GB999999973'), // United Kingdom (standard) - array('GBGD001'), // United Kingdom (government departments) - array('GBHA599'), // United Kingdom (health authorities) + ['ATU99999999'], // Austria + ['BE0999999999'], // Belgium + ['BE1999999999'], // Belgium + ['HR12345678901'], // Croatia + ['CY99999999L'], // Cyprus + ['DK99999999'], // Denmark + ['FI99999999'], // Finland + ['FRXX999999999'], // France + ['DE999999999'], // Germany + ['HU12345678'], // Hungary + ['IE1234567T'], // Ireland + ['IE1234567TW'], // Ireland + ['IE1234567FA'], // Ireland (since January 2013) + ['NL999999999B99'], // The Netherlands + ['NO999999999'], // Norway + ['NO999999999MVA'], // Norway (including MVA) + ['ES99999999R'], // Spain + ['SE999999999901'], // Sweden + ['CHE-123.456.788 TVA'], // Switzerland + ['GB999999973'], // United Kingdom (standard) + ['GBGD001'], // United Kingdom (government departments) + ['GBHA599'], // United Kingdom (health authorities) // Examples from the EU (http://ec.europa.eu/taxation_customs/vies/faqvies.do#item_11) - array('ATU99999999'), // AT-Austria - array('BE0999999999'), // BE-Belgium - array('BG999999999'), // BG-Bulgaria - array('BG9999999999'), // BG-Bulgaria - array('CY99999999L'), // CY-Cyprus - array('CZ99999999'), // CZ-Czech Republic - array('CZ999999999'), // CZ-Czech Republic - array('CZ9999999999'), // CZ-Czech Republic - array('DE999999999'), // DE-Germany - array('DK99999999'), // DK-Denmark - array('EE999999999'), // EE-Estonia - array('EL999999999'), // EL-Greece - array('ESX9999999X'), // ES-Spain - array('FI99999999'), // FI-Finland - array('FRXX999999999'), // FR-France - array('GB999999999'), // GB-United Kingdom - array('GB999999999999'), // GB-United Kingdom - array('GBGD999'), // GB-United Kingdom - array('GBHA999'), // GB-United Kingdom - array('HR99999999999'), // HR-Croatia - array('HU99999999'), // HU-Hungary - array('IE9S99999L'), // IE-Ireland - array('IE9999999WI'), // IE-Ireland - array('IT99999999999'), // IT-Italy - array('LT999999999'), // LT-Lithuania - array('LT999999999999'), // LT-Lithuania - array('LU99999999'), // LU-Luxembourg - array('LV99999999999'), // LV-Latvia - array('MT99999999'), // MT-Malta - array('NL999999999B99'), // NL-The Netherlands - array('PL9999999999'), // PL-Poland - array('PT999999999'), // PT-Portugal - array('RO999999999'), // RO-Romania - array('SE999999999999'), // SE-Sweden - array('SI99999999'), // SI-Slovenia - array('SK9999999999'), // SK-Slovakia + ['ATU99999999'], // AT-Austria + ['BE0999999999'], // BE-Belgium + ['BG999999999'], // BG-Bulgaria + ['BG9999999999'], // BG-Bulgaria + ['CY99999999L'], // CY-Cyprus + ['CZ99999999'], // CZ-Czech Republic + ['CZ999999999'], // CZ-Czech Republic + ['CZ9999999999'], // CZ-Czech Republic + ['DE999999999'], // DE-Germany + ['DK99999999'], // DK-Denmark + ['EE999999999'], // EE-Estonia + ['EL999999999'], // EL-Greece + ['ESX9999999X'], // ES-Spain + ['FI99999999'], // FI-Finland + ['FRXX999999999'], // FR-France + ['GB999999999'], // GB-United Kingdom + ['GB999999999999'], // GB-United Kingdom + ['GBGD999'], // GB-United Kingdom + ['GBHA999'], // GB-United Kingdom + ['HR99999999999'], // HR-Croatia + ['HU99999999'], // HU-Hungary + ['IE9S99999L'], // IE-Ireland + ['IE9999999WI'], // IE-Ireland + ['IT99999999999'], // IT-Italy + ['LT999999999'], // LT-Lithuania + ['LT999999999999'], // LT-Lithuania + ['LU99999999'], // LU-Luxembourg + ['LV99999999999'], // LV-Latvia + ['MT99999999'], // MT-Malta + ['NL999999999B99'], // NL-The Netherlands + ['PL9999999999'], // PL-Poland + ['PT999999999'], // PT-Portugal + ['RO999999999'], // RO-Romania + ['SE999999999999'], // SE-Sweden + ['SI99999999'], // SI-Slovenia + ['SK9999999999'], // SK-Slovakia // Real world examples - array('GB226148083'), // Fuller's Brewery, United Kingdom - array('NL002230884B01'), // Albert Heijn BV., The Netherlands - array('ESG82086810'), // Fundación Telefónica, Spain - array('IE9514041I'), // Lego Systems A/S, Denmark with Irish VAT ID - array('IE9990705T'), // Amazon EU Sarl, Luxembourg with Irish VAT ID - array('DK61056416'), // Carlsberg A/S, Denmark - array('BE0648836958'), // Delhaize Logistics, Belgium - array('CZ00514152'), // Budějovický Budvar, Budweiser, Czech Republic + ['GB226148083'], // Fuller's Brewery, United Kingdom + ['NL002230884B01'], // Albert Heijn BV., The Netherlands + ['ESG82086810'], // Fundación Telefónica, Spain + ['IE9514041I'], // Lego Systems A/S, Denmark with Irish VAT ID + ['IE9990705T'], // Amazon EU Sarl, Luxembourg with Irish VAT ID + ['DK61056416'], // Carlsberg A/S, Denmark + ['BE0648836958'], // Delhaize Logistics, Belgium + ['CZ00514152'], // Budějovický Budvar, Budweiser, Czech Republic // Various examples - array('FR9X999999999'), - array('NL123456789B01'), - array('IE9574245O'), - array('CHE123456788TVA') - ); - } - - /** - * @return array - */ - public function getInvalidVatins() - { - return array( - array(null), - array(''), - array('123456789'), - array('XX123'), - array('GB999999973dsflksdjflsk'), - array('BE2999999999'), // Belgium - "the first digit following the prefix is always zero ("0") or ("1")" - array('CHE12345678 MWST') - ); + ['FR9X999999999'], + ['NL123456789B01'], + ['IE9574245O'], + ['CHE123456788TVA'], + ]; } /** - * @return \Ddeboer\Vatin\Vies\Client + * @return list */ - private function getViesClientMock() + public static function getInvalidVatins(): array { - return $this->getMockBuilder('\Ddeboer\Vatin\Vies\Client') - ->disableOriginalConstructor() - ->getMock(); + return [ + [null], + [''], + ['123456789'], + ['XX123'], + ['GB999999973dsflksdjflsk'], + ['BE2999999999'], // Belgium - "the first digit following the prefix is always zero ("0") or ("1")" + ['CHE12345678 MWST'], + ]; } - private function getCheckVatResponseMock($valid) + private function getViesClientMock(): MockObject&ClientInterface { - $mock = $this->getMockBuilder('\Ddeboer\Vatin\Vies\Response\CheckVatResponse') + return $this->getMockBuilder(ClientInterface::class) ->getMock(); - - $mock - ->expects($this->any()) - ->method('isValid') - ->willReturn($valid); - - return $mock; } - } diff --git a/tests/Vies/ClientTest.php b/tests/Vies/ClientTest.php index 9441bdb..6397d40 100644 --- a/tests/Vies/ClientTest.php +++ b/tests/Vies/ClientTest.php @@ -3,22 +3,20 @@ namespace Ddeboer\Vatin\Test\Vies; use Ddeboer\Vatin\Vies\Client; -use Ddeboer\Vatin\Vies\Response\CheckVatResponse; use PHPUnit\Framework\TestCase; class ClientTest extends TestCase { - public function testCheckVat() + public function testCheckVat(): void { $client = new Client(); $response = $client->checkVat('NL', '123456789B01'); - $this->assertInstanceOf(CheckVatResponse::class, $response); - $this->assertFalse($response->isValid()); - $this->assertEquals('NL', $response->getCountryCode()); - $this->assertEquals('123456789B01', $response->getVatNumber()); - $this->assertInstanceOf('\DateTime', $response->getRequestDate()); - $this->assertEquals('---', $response->getName()); - $this->assertEquals('---', $response->getAddress()); + $this->assertFalse($response->valid); + $this->assertEquals('NL', $response->countryCode); + $this->assertEquals('123456789B01', $response->vatNumber); + $this->assertInstanceOf(\DateTimeImmutable::class, $response->date); + $this->assertEquals('---', $response->name); + $this->assertEquals('---', $response->address); } -} \ No newline at end of file +}