diff --git a/.github/workflows/min-stability.yml b/.github/workflows/min-stability.yml
new file mode 100644
index 0000000..75925f8
--- /dev/null
+++ b/.github/workflows/min-stability.yml
@@ -0,0 +1,30 @@
+name: Minimum Stability
+
+on:
+ push:
+ branches:
+ - "**"
+ pull_request:
+ branches: [ "master" ]
+
+permissions:
+ contents: read
+
+jobs:
+ standard:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.1'
+
+ - name: Composer Install
+ run: composer update --prefer-dist --no-progress --prefer-lowest
+
+ - name: PHPUnit
+ run: ./vendor/bin/phpunit --testsuite Full
diff --git a/.github/workflows/phpcodesniffer.yml b/.github/workflows/phpcodesniffer.yml
new file mode 100644
index 0000000..53351c3
--- /dev/null
+++ b/.github/workflows/phpcodesniffer.yml
@@ -0,0 +1,23 @@
+name: PHP_CodeSniffer
+
+on:
+ push:
+ branches:
+ - "**"
+
+permissions:
+ contents: read
+
+jobs:
+ standard:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Composer Install
+ run: composer install --prefer-dist --no-progress
+
+ - name: PHP_CodeSniffer
+ run: ./vendor/bin/phpcs
diff --git a/.github/workflows/php.yml b/.github/workflows/phpcoverage.yml
similarity index 67%
rename from .github/workflows/php.yml
rename to .github/workflows/phpcoverage.yml
index 3fd5a8e..47d34bf 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/phpcoverage.yml
@@ -1,11 +1,9 @@
-name: PHP Composer
+name: PHPCoverage
on:
push:
branches:
- "**"
- pull_request:
- branches: [ "master" ]
schedule:
- cron: "0 1 * * *"
@@ -23,14 +21,8 @@ jobs:
- name: Composer Install
run: composer install --prefer-dist --no-progress
- - name: PHPUnit
+ - name: PHPUnitCoverage
run: XDEBUG_MODE=coverage ./vendor/bin/phpunit --log-junit junit_report.xml --coverage-clover clover.xml --coverage-text --colors=never
- - name: PHPStan
- run: ./vendor/bin/phpstan
-
- - name: PHP_CodeSniffer
- run: ./vendor/bin/phpcs
-
- - name: CodeCov
+ - name: CodeCov
uses: codecov/codecov-action@v3
diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml
new file mode 100644
index 0000000..c2adca4
--- /dev/null
+++ b/.github/workflows/phpstan.yml
@@ -0,0 +1,23 @@
+name: PHPStan
+
+on:
+ push:
+ branches:
+ - "**"
+
+permissions:
+ contents: read
+
+jobs:
+ standard:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Composer Install
+ run: composer install --prefer-dist --no-progress
+
+ - name: PHPStan
+ run: ./vendor/bin/phpstan --memory-limit=256M
diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml
new file mode 100644
index 0000000..8d80c1a
--- /dev/null
+++ b/.github/workflows/phpunit.yml
@@ -0,0 +1,27 @@
+name: PHPUnit
+
+on:
+ push:
+ branches:
+ - "**"
+ pull_request:
+ branches: [ "master" ]
+ schedule:
+ - cron: "0 1 * * *"
+
+permissions:
+ contents: read
+
+jobs:
+ standard:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Composer Install
+ run: composer install --prefer-dist --no-progress
+
+ - name: PHPUnit
+ run: XDEBUG_MODE=coverage ./vendor/bin/phpunit
diff --git a/.idea/currency-rates.iml b/.idea/currency-rates.iml
index 497f7b2..70bde57 100644
--- a/.idea/currency-rates.iml
+++ b/.idea/currency-rates.iml
@@ -40,6 +40,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/php-docker-settings.xml b/.idea/php-docker-settings.xml
index aa7f0f3..1303964 100644
--- a/.idea/php-docker-settings.xml
+++ b/.idea/php-docker-settings.xml
@@ -3,6 +3,21 @@
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..b2b3bf3
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,12 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+## [1.1.0] - 2023-12-02
+
+### Added
+- Exchanger - Bank of England - [\#1](../../../issues/1)
diff --git a/composer.json b/composer.json
index 16dd6d5..20cb625 100644
--- a/composer.json
+++ b/composer.json
@@ -36,18 +36,26 @@
"require": {
"php": "^8.1",
"mibo/currencies": "^1.0",
- "ext-xmlreader": "*"
+ "ext-xmlreader": "*",
+ "nesbot/carbon": "^2.72"
},
"require-dev": {
- "phpunit/phpunit": "^10.0",
+ "phpunit/phpunit": "^10.1",
"phpunit/php-invoker": "^4.0",
"phpstan/phpstan": "^1.5",
"squizlabs/php_codesniffer": "^3.6",
"phpstan/phpstan-strict-rules": "^1.5",
- "jetbrains/phpstorm-attributes": "^1.0"
+ "jetbrains/phpstorm-attributes": "^1.0",
+ "slevomat/coding-standard": "^8.13",
+ "phpstan/extension-installer": "^1.3",
+ "php-parallel-lint/php-parallel-lint": "^1.3"
},
"config": {
"platform-check": true,
- "lock": false
+ "lock": false,
+ "allow-plugins": {
+ "phpstan/extension-installer": true,
+ "dealerdirect/phpcodesniffer-composer-installer": true
+ }
}
}
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 8d2b10e..dfa2ed3 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -7,129 +7,79 @@
./src
+ ./tests
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
+
+ ./src/Contracts/*
-
- 0
+
+ ./src/Exceptions/*
-
- 0
+
+ ./src/Exceptions/*
-
- 0
-
-
+
-
-
+
+
+
+
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
+
+ ./tests/*
-
- 0
+
+ ./tests/*
-
- 0
+
+ ./tests/*
-
- 0
+
+ ./tests/*
-
- 0
-
-
-
-
-
-
-
+
-
+
-
- 0
+
+ ./src/Exchangers/*
-
- 0
-
-
- 0
-
-
-
-
-
diff --git a/src/Contracts/ExchangerInterface.php b/src/Contracts/ExchangerInterface.php
index 751cb9c..d723cb5 100644
--- a/src/Contracts/ExchangerInterface.php
+++ b/src/Contracts/ExchangerInterface.php
@@ -60,7 +60,7 @@ public function getExchangeRates(): array;
/**
* Lists all available currencies for the Exchanger.
*
- * @return string[] Available currencies.
+ * @return array Available currencies.
*/
public function getAvailableCurrencies(): array;
}
diff --git a/src/Exchangers/BoE.php b/src/Exchangers/BoE.php
new file mode 100644
index 0000000..e48c77c
--- /dev/null
+++ b/src/Exchangers/BoE.php
@@ -0,0 +1,230 @@
+
+ *
+ * @since 1.1.0
+ *
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise.
+ */
+class BoE implements ExchangerInterface
+{
+ use ExchangerHelper;
+
+ private const URL = 'https://www.bankofengland.co.uk/boeapps/database/_iadb-fromshowcolumns.asp?csv.y=yes';
+ private const SERIES = [
+ 'XUDLADS' => 'AUD',
+ 'XUDLBK25' => 'CZK',
+ 'XUDLBK33' => 'HUF',
+ 'XUDLBK47' => 'PLN',
+ 'XUDLBK78' => 'ILS',
+ 'XUDLBK83' => 'MYR',
+ 'XUDLBK87' => 'THB',
+ 'XUDLBK89' => 'CNY',
+ 'XUDLBK93' => 'KRW',
+ 'XUDLBK95' => 'TRY',
+ 'XUDLBK97' => 'INR',
+ 'XUDLCDS' => 'CAD',
+ 'XUDLDKS' => 'DKK',
+ 'XUDLERS' => 'EUR',
+ 'XUDLHDS' => 'HKD',
+ 'XUDLJYS' => 'JPY',
+ 'XUDLNDS' => 'NZD',
+ 'XUDLNKS' => 'NOK',
+ 'XUDLSFS' => 'CHF',
+ 'XUDLSGS' => 'SGD',
+ 'XUDLSKS' => 'SEK',
+ 'XUDLSRS' => 'SAR',
+ 'XUDLTWS' => 'TWD',
+ 'XUDLUSS' => 'USD',
+ 'XUDLZRS' => 'ZAR',
+ ];
+
+ /**
+ * @inheritDoc
+ */
+ final public function getDefaultCurrencyCode(): string
+ {
+ return 'GBP';
+ }
+
+ /**
+ * @return non-empty-string
+ */
+ final protected function composeUlr(): string
+ {
+ /** @phpstan-var \Carbon\Carbon $currentTime */
+ $currentTime = Carbon::now()->isWeekend() ? Carbon::now()->previous(CarbonInterface::FRIDAY) : Carbon::now();
+
+ /** @phpstan-var \Carbon\Carbon $timeFrom */
+ $timeFrom = $currentTime->copy()->subDays(3);
+ $queries = [
+ 'csv.x' => 'yes',
+ 'CSVF' => 'CN',
+ 'DAT' => 'RNG',
+ 'FD' => $timeFrom->day,
+ 'Filter' => 'N',
+ 'FM' => $timeFrom->format('M'),
+ 'FNY' => '',
+ 'FromSeries' => 1,
+ 'FY' => $timeFrom->year,
+ 'TD' => $currentTime->day,
+ 'TM' => $currentTime->format('M'),
+ 'ToSeries' => 50,
+ 'Travel' => 'NIxIRxSUx',
+ 'TY' => $currentTime->year,
+ ];
+ $currencies = [
+ 'C=EC3',
+ 'C=DS7',
+ 'C=5LA',
+ 'C=5OW',
+ 'C=IN7',
+ 'C=IN8',
+ 'C=INA',
+ 'C=INB',
+ 'C=INC',
+ 'C=IND',
+ 'C=INE',
+ 'C=ECL',
+ 'C=ECH',
+ 'C=C8J',
+ 'C=ECN',
+ 'C=C8N',
+ 'C=ECO',
+ 'C=EC6',
+ 'C=ECU',
+ 'C=ECQ',
+ 'C=ECC',
+ 'C=ECZ',
+ 'C=ECD',
+ 'C=C8P',
+ 'C=ECE',
+ ];
+
+ return self::URL . '&' . http_build_query($queries) . '&' . implode('&', $currencies);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getExchangeRates(): array
+ {
+ $content = file_get_contents($this->composeUlr());
+
+ if ($content === false) {
+ throw new ExchangeRateNotAvailableException();
+ }
+
+ return $this->csvContentIntoArray($content);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getAvailableCurrencies(): array
+ {
+ return array_merge(array_values(self::SERIES), [$this->getDefaultCurrencyCode()]);
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @param array $rates
+ */
+ protected function getFor(array $rates, string $currency, string $fromCurrency): float
+ {
+ $rate = $rates[$currency]["rate"];
+
+ if ($fromCurrency === $this->getDefaultCurrencyCode()) {
+ return $rate;
+ }
+
+ return 1 / $rates[$fromCurrency]["rate"] * $rate;
+ }
+
+ /**
+ * @param string $data
+ *
+ * @return array, rate: float}>
+ */
+ private function csvContentIntoArray(string $data): array
+ {
+ $rows = explode("\n", $data);
+
+ unset($rows[0]);
+
+ /** @phpstan-var array{0: string, 1: key-of, 2: numeric-string} $rows */
+ $rows = array_map('str_getcsv', $rows);
+ // @phpstan-ignore-next-line
+ $rows = array_filter($rows, static fn (array $row): bool => count($row) === 3);
+ $rows = array_map(
+ // @phpstan-ignore-next-line
+ static fn (array $row): array => [
+ 'currency' => self::SERIES[$row[1]],
+ 'date' => Carbon::createFromFormat('d M Y', $row[0]),
+ 'value' => (float) $row[2],
+ ],
+ $rows
+ );
+
+ /** @phpstan-var \Carbon\Carbon|null $latestDate */
+ $latestDate = null;
+
+ /** @var array{date: \Carbon\Carbon, value: float, currency: string} $row */
+ foreach ($rows as $row) {
+ $latestDate ??= $row['date'];
+
+ if ($latestDate->isAfter($row['date']) || $latestDate->isSameDay($row['date'])) {
+ break;
+ }
+ }
+
+ /** @phpstan-var array $rows */
+ array_filter($rows, static fn (array $row): bool => $row['date']->isSameDay($latestDate));
+
+ $result = [];
+
+ foreach ($rows as $row) {
+ $result[$row['currency']] = [
+ 'amount' => 1,
+ 'rate' => $row['value'],
+ ];
+ }
+
+ return $result;
+ }
+}
diff --git a/src/Exchangers/CNB.php b/src/Exchangers/CNB.php
index d5d9755..3734b91 100644
--- a/src/Exchangers/CNB.php
+++ b/src/Exchangers/CNB.php
@@ -7,6 +7,7 @@
use MiBo\Currency\Rates\Contracts\ExchangerInterface;
use MiBo\Currency\Rates\Exceptions\ExchangeRateNotAvailableException;
use MiBo\Currency\Rates\Traits\ExchangerHelper;
+use function count;
/**
* Class CNB
@@ -70,25 +71,10 @@ final public function getDefaultCurrencyCode(): string
return "CZK";
}
- /**
- * @inheritDoc
- *
- * @param array $rates
- */
- protected function getFor(array $rates, string $currency, string $fromCurrency): float
- {
- $rate = ($rates[$currency]["amount"] ?? 1) / $rates[$currency]["rate"];
-
- if ($fromCurrency === $this->getDefaultCurrencyCode()) {
- return $rate;
- }
-
- return $rate / (($rates[$fromCurrency]["amount"] ?? 1) * $rates[$fromCurrency]["rate"]);
- }
-
/**
* @inheritDoc
*/
+ // @phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
public function getExchangeRates(): array
{
$content = file_get_contents(static::URL);
@@ -124,4 +110,20 @@ public function getExchangeRates(): array
return $rates;
}
+
+ /**
+ * @inheritDoc
+ *
+ * @param array $rates
+ */
+ protected function getFor(array $rates, string $currency, string $fromCurrency): float
+ {
+ $rate = ($rates[$currency]["amount"] ?? 1) / $rates[$currency]["rate"];
+
+ if ($fromCurrency === $this->getDefaultCurrencyCode()) {
+ return $rate;
+ }
+
+ return $rate / (($rates[$fromCurrency]["amount"] ?? 1) * $rates[$fromCurrency]["rate"]);
+ }
}
diff --git a/src/Exchangers/ECB.php b/src/Exchangers/ECB.php
index 3ae10dc..1be411a 100644
--- a/src/Exchangers/ECB.php
+++ b/src/Exchangers/ECB.php
@@ -13,14 +13,14 @@
* Class ECB
*
* The European Central Bank (ECB) is the prime component of the Eurosystem and the European System of
- * Central Banks (ESCB) as well as one of seven institutions of the European Union.[2] It is one of the
+ * Central Banks (ESCB) as well as one of seven institutions of the European Union. It is one of the
* world's most important central banks.
*
* The ECB Governing Council makes monetary policy for the Eurozone and the European Union, administers
* the foreign exchange reserves of EU member states, engages in foreign exchange operations, and defines
* the intermediate monetary objectives and key interest rate of the EU. The ECB Executive Board enforces
* the policies and decisions of the Governing Council, and may direct the national central banks when
- * doing so.[3] The ECB has the exclusive right to authorise the issuance of euro banknotes. Member states can
+ * doing so. The ECB has the exclusive right to authorise the issuance of euro banknotes. Member states can
* issue euro coins, but the volume must be approved by the ECB beforehand. The bank also operates the TARGET2
* payments system.
*
@@ -29,13 +29,13 @@
* the official status of an EU institution. When the ECB was created, it covered a Eurozone of eleven
* members. Since then, Greece joined in January 2001, Slovenia in January 2007, Cyprus and Malta in January
* 2008, Slovakia in January 2009, Estonia in January 2011, Latvia in January 2014, Lithuania in January 2015
- * and Croatia in January 2023.[4] The current President of the ECB is Christine Lagarde. Seated in Frankfurt,
+ * and Croatia in January 2023. The current President of the ECB is Christine Lagarde. Seated in Frankfurt,
* Germany, the bank formerly occupied the Eurotower prior to the construction of its new seat.
*
* The ECB is directly governed by European Union law. Its capital stock, worth €11 billion, is owned by
* all 27 central banks of the EU member states as shareholders.[5] The initial capital allocation key was
* determined in 1998 on the basis of the states' population and GDP, but the capital key has been readjusted
- * since.[5] Shares in the ECB are not transferable and cannot be used as collateral.
+ * since. Shares in the ECB are not transferable and cannot be used as collateral.
*
* @link https://www.ecb.europa.eu/
*
@@ -56,30 +56,15 @@ class ECB implements ExchangerInterface
/**
* @inheritDoc
*/
- public function getDefaultCurrencyCode(): string
+ final public function getDefaultCurrencyCode(): string
{
return "EUR";
}
- /**
- * @inheritDoc
- *
- * @param array $rates
- */
- protected function getFor(array $rates, string $currency, string $fromCurrency): float
- {
- $rate = $rates[$currency]["rate"];
-
- if ($fromCurrency === $this->getDefaultCurrencyCode()) {
- return $rate;
- }
-
- return (1 / $rates[$fromCurrency]["rate"] ) * $rate;
- }
-
/**
* @inheritDoc
*/
+ // @phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
public function getExchangeRates(): array
{
$rates = [];
@@ -106,14 +91,30 @@ public function getExchangeRates(): array
break;
}
+ /** @phpstan-var object{value: string}|null $currency */
$currency = $DOMNode->attributes->item(0);
- $rate = $DOMNode->attributes->item(1);
- /** @var object{value: string}|null $currency */
- /** @var object{value: string}|null $rate */
+ /** @phpstan-var object{value: string}|null $rate */
+ $rate = $DOMNode->attributes->item(1);
$rates[$currency?->value] = ["rate" => (float) $rate?->value];
}
return $rates;
}
+
+ /**
+ * @inheritDoc
+ *
+ * @param array $rates
+ */
+ protected function getFor(array $rates, string $currency, string $fromCurrency): float
+ {
+ $rate = $rates[$currency]["rate"];
+
+ if ($fromCurrency === $this->getDefaultCurrencyCode()) {
+ return $rate;
+ }
+
+ return 1 / $rates[$fromCurrency]["rate"] * $rate;
+ }
}
diff --git a/src/Traits/ExchangerHelper.php b/src/Traits/ExchangerHelper.php
index d2eebd7..c714163 100644
--- a/src/Traits/ExchangerHelper.php
+++ b/src/Traits/ExchangerHelper.php
@@ -42,6 +42,7 @@ abstract protected function getFor(array $rates, string $currency, string $fromC
/**
* @inheritDoc
*/
+ // @phpcs:ignore SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
public function getRateFor(
CurrencyInterface|string $currency,
CurrencyInterface|string|null $fromCurrency = null
@@ -49,9 +50,9 @@ public function getRateFor(
{
$rates = $this->getExchangeRates();
$currency = $currency instanceof CurrencyInterface ? $currency->getAlphabeticalCode() : $currency;
- $fromCurrency = $fromCurrency instanceof CurrencyInterface ?
- $fromCurrency->getAlphabeticalCode() :
- $fromCurrency;
+ $fromCurrency = $fromCurrency instanceof CurrencyInterface
+ ? $fromCurrency->getAlphabeticalCode()
+ : $fromCurrency;
if ($currency === $fromCurrency || ($currency === $this->getDefaultCurrencyCode() && $fromCurrency === null)) {
return 1;
diff --git a/tests/Core/BoETest.php b/tests/Core/BoETest.php
new file mode 100644
index 0000000..2ec557d
--- /dev/null
+++ b/tests/Core/BoETest.php
@@ -0,0 +1,59 @@
+
+ *
+ * @since 1.1.0
+ *
+ * @no-named-arguments Parameter names are not covered by the backward compatibility promise.
+ *
+ * @coversDefaultClass \MiBo\Currency\Rates\Exchangers\BoE
+ */
+final class BoETest extends ExchangerTestCase
+{
+ /**
+ * @medium
+ *
+ * @covers ::getExchangeRates
+ * @covers ::getAvailableCurrencies
+ * @covers ::getRateFor
+ * @covers ::getFor
+ * @covers ::getDefaultCurrencyCode
+ * @covers ::composeUlr
+ * @covers ::csvContentIntoArray
+ *
+ * @return void
+ */
+ public function test(): void
+ {
+ $class = new BoE();
+
+ $this->assertAvailableCountries(
+ [
+ "CZK",
+ "EUR",
+ "AUD",
+ "USD",
+ "CAD",
+ "SEK",
+ "GBP",
+ "PLN",
+ "JPY",
+ ],
+ $class->getAvailableCurrencies()
+ );
+
+ $this->assertRate(1.16, $class->getRateFor("EUR"));
+ $this->assertRate(28.22, $class->getRateFor('CZK'));
+ }
+}
diff --git a/tests/Core/CNBTest.php b/tests/Core/CNBTest.php
index b5435c2..a9d6a1e 100644
--- a/tests/Core/CNBTest.php
+++ b/tests/Core/CNBTest.php
@@ -19,7 +19,7 @@
*
* @coversDefaultClass \MiBo\Currency\Rates\Exchangers\CNB
*/
-class CNBTest extends ExchangerTestCase
+final class CNBTest extends ExchangerTestCase
{
/**
* @medium
diff --git a/tests/Core/ECBTest.php b/tests/Core/ECBTest.php
index 9c37d45..33c2bdb 100644
--- a/tests/Core/ECBTest.php
+++ b/tests/Core/ECBTest.php
@@ -4,7 +4,6 @@
namespace MiBo\Currency\Rates\Tests;
-use MiBo\Currency\Rates\Exchangers\CNB;
use MiBo\Currency\Rates\Exchangers\ECB;
/**
@@ -20,7 +19,7 @@
*
* @coversDefaultClass \MiBo\Currency\Rates\Exchangers\ECB
*/
-class ECBTest extends ExchangerTestCase
+final class ECBTest extends ExchangerTestCase
{
/**
* @medium
diff --git a/tests/Core/ExchangerTestCase.php b/tests/Core/ExchangerTestCase.php
index 12d5cbd..be066a3 100644
--- a/tests/Core/ExchangerTestCase.php
+++ b/tests/Core/ExchangerTestCase.php
@@ -17,34 +17,27 @@
*
* @no-named-arguments Parameter names are not covered by the backward compatibility promise.
*/
-class ExchangerTestCase extends TestCase
+abstract class ExchangerTestCase extends TestCase
{
/**
- * @param string[] $expected
- * @param string[] $actual
+ * @param array $expected
+ * @param array $actual
*
* @return void
*/
public static function assertAvailableCountries(array $expected, array $actual): void
{
foreach ($expected as $country) {
- static::assertContains($country, $actual);
+ self::assertContains($country, $actual);
}
}
- /**
- * @param float $expected
- * @param float $actual
- * @param float $delta
- *
- * @return void
- */
public static function assertRate(float $expected, float $actual, float $delta = 10): void
{
$min = $expected - ($expected / 100 * $delta);
$max = $expected + ($expected / 100 * $delta);
- static::assertTrue(
+ self::assertTrue(
$actual >= $min && $actual <= $max,
"Expected rate is not in range of $min - $max (actual $actual)"
);