From 65786517aebfff6411d0d00158eed872ddfff460 Mon Sep 17 00:00:00 2001 From: ksdev Date: Sun, 5 Jul 2015 19:49:11 +0200 Subject: [PATCH] Rewrite cache and exchange rate tables functionality --- README.md | 14 +- src/CurrencyConverter.php | 71 +++++ src/ExRatesDayTable.php | 61 +++++ src/ExRatesDayTableFactory.php | 18 ++ src/ExRatesDayTableFinder.php | 217 +++++++++++++++ src/NBPCurrencyConverter.php | 175 ------------- tests/CurrencyConverterTest.php | 242 +++++++++++++++++ tests/NBPCurrencyConverterTest.php | 169 ------------ tests/test_dir.txt | 408 +++++++++++++++++++++++++++++ 9 files changed, 1028 insertions(+), 347 deletions(-) create mode 100644 src/CurrencyConverter.php create mode 100644 src/ExRatesDayTable.php create mode 100644 src/ExRatesDayTableFactory.php create mode 100644 src/ExRatesDayTableFinder.php delete mode 100644 src/NBPCurrencyConverter.php create mode 100644 tests/CurrencyConverterTest.php delete mode 100644 tests/NBPCurrencyConverterTest.php create mode 100644 tests/test_dir.txt diff --git a/README.md b/README.md index ed39b07..36d8ed7 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,17 @@ $ composer require ksdev/nbp-currency-converter ## Usage ``` php -$converter = new Ksdev\NBPCurrencyConverter( - new GuzzleHttp\Client(), - 'path/to/cache/folder' +use Ksdev\NBPCurrencyConverter\CurrencyConverter; +use Ksdev\NBPCurrencyConverter\ExRatesDayTableFinder; +use Ksdev\NBPCurrencyConverter\ExRatesDayTableFactory; +use GuzzleHttp\Client; + +$converter = new CurrencyConverter( + new ExRatesDayTableFinder( + new Client(), + new ExRatesDayTableFactory(), + 'path/to/cache/folder' + ) ); try { $result = $converter->convert('123.4567', 'PLN', 'USD') diff --git a/src/CurrencyConverter.php b/src/CurrencyConverter.php new file mode 100644 index 0000000..9eb2de5 --- /dev/null +++ b/src/CurrencyConverter.php @@ -0,0 +1,71 @@ +ratesTableFinder = $ratesTableFinder; + } + + /** + * Get the average exchange rates + * + * @param \DateTime $pubDate Optional rates table publication date + * + * @return array + * + * @throws \Exception + */ + public function averageExchangeRates(\DateTime $pubDate = null) + { + $file = $this->ratesTableFinder->getExRatesDayTable($pubDate); + return $file->parsedContent; + } + + /** + * Convert amount from one currency to another + * + * @param string $fromAmount Amount with four digits after decimal point, e.g. '123.0000' + * @param string $fromCurrency E.g. 'USD' or 'EUR' + * @param string $toCurrency E.g. 'USD' or 'EUR' + * @param \DateTime $pubDate Optional rates table publication date + * + * @return array + * + * @throws \Exception + */ + public function convert($fromAmount, $fromCurrency, $toCurrency, \DateTime $pubDate = null) + { + if (!preg_match('/^\d+\.(\d{4})$/', $fromAmount)) { + throw new \Exception('Invalid format of amount'); + } + + $rates = $this->averageExchangeRates($pubDate); + + $fromCurrency = strtoupper($fromCurrency); + $toCurrency = strtoupper($toCurrency); + if (!isset($rates['waluty'][$fromCurrency]) || !isset($rates['waluty'][$toCurrency])) { + throw new \Exception('Invalid currency code'); + } + + $fromMultiplier = str_replace(',', '.', $rates['waluty'][$fromCurrency]['przelicznik']); + $fromAverageRate = str_replace(',', '.', $rates['waluty'][$fromCurrency]['kurs_sredni']); + $toMultiplier = str_replace(',', '.', $rates['waluty'][$toCurrency]['przelicznik']); + $toAverageRate = str_replace(',', '.', $rates['waluty'][$toCurrency]['kurs_sredni']); + + bcscale(6); + $plnAmount = bcdiv(bcmul($fromAmount, $fromAverageRate), $fromMultiplier); + $resultAmount = bcdiv(bcmul($plnAmount, $toMultiplier), $toAverageRate); + $roundedResult = BCMathHelper::bcround($resultAmount, 4); + + return [ + 'publication_date' => $rates['data_publikacji'], + 'amount' => $roundedResult, + 'currency' => $toCurrency + ]; + } +} diff --git a/src/ExRatesDayTable.php b/src/ExRatesDayTable.php new file mode 100644 index 0000000..d286ef5 --- /dev/null +++ b/src/ExRatesDayTable.php @@ -0,0 +1,61 @@ +rawContent = $rawContent; + $this->parsedContent = $this->parseXml($rawContent); + } + + /** + * Transform the raw xml content into an array + * + * @param string $rawContent + * + * @return array + * + * @throws \Exception + */ + private function parseXml($rawContent) + { + $xml = new \SimpleXMLElement($rawContent); + if (empty($xml->numer_tabeli) || empty($xml->data_publikacji) || empty($xml->pozycja)) { + throw new \Exception('Invalid xml response content'); + } + $rates = [ + 'numer_tabeli' => (string)$xml->numer_tabeli, + 'data_publikacji' => (string)$xml->data_publikacji, + 'waluty' => [ + 'PLN' => [ + 'nazwa_waluty' => 'złoty polski', + 'przelicznik' => '1', + 'kurs_sredni' => '1' + ] + ] + ]; + foreach ($xml->pozycja as $pozycja) { + $rates['waluty'] += [ + (string)$pozycja->kod_waluty => [ + 'nazwa_waluty' => (string)$pozycja->nazwa_waluty, + 'przelicznik' => (string)$pozycja->przelicznik, + 'kurs_sredni' => (string)$pozycja->kurs_sredni + ] + ]; + } + return $rates; + } +} diff --git a/src/ExRatesDayTableFactory.php b/src/ExRatesDayTableFactory.php new file mode 100644 index 0000000..2ced3e7 --- /dev/null +++ b/src/ExRatesDayTableFactory.php @@ -0,0 +1,18 @@ +guzzle = $guzzle; + $this->ratesTableFactory = $ratesTableFactory; + if ($cachePath) { + if (!is_dir($cachePath)) { + throw new \Exception('Invalid cache path'); + } + $this->cachePath = rtrim((string)$cachePath, '/') . '/'; + } + } + + /** + * Get the ExRatesDayTable instance + * + * @param \DateTime $pubDate Optional rates table publication date + * + * @return ExRatesDayTable + * + * @throws \Exception + */ + public function getExRatesDayTable(\DateTime $pubDate = null) + { + $this->setSoughtPubDate($pubDate); + + $i = 0; + do { + // Limit the number of times the loop repeats + if ($i === self::MAX_ONE_TIME_API_REQ) { + throw new \Exception('Max request to api limit has been reached'); + } + + // If user doesn't want a specific date, try to get the rates from the last working day + if (!$pubDate) { + $this->soughtPubDate = $this->soughtPubDate->sub(new \DateInterval('P1D')); + } + + // Try to find the file in cache, otherwise download it + if ($this->cachePath && ($cachedXml = $this->getCachedXml())) { + $rawContent = $cachedXml; + } else { + $rawContent = $this->downloadXml(); + } + + // If a specific date is sought then break, otherwise continue + if ($pubDate) { + break; + } + + $i++; + } while (!$rawContent); + + if (!$rawContent) { + throw new \Exception('Exchange rates file not found'); + } + + return $this->ratesTableFactory->getInstance($rawContent); + } + + /** + * Set the sought publication date necessary for finder operation + * + * @param \DateTime|null $pubDate + * + * @throws \Exception + */ + private function setSoughtPubDate($pubDate) + { + if ($pubDate instanceof \DateTime) { + if (!($pubDate >= new \DateTime('2002-01-02') && $pubDate <= new \DateTime())) { + throw new \Exception('Invalid publication date'); + } + } else { + $pubDate = new \DateTime(); + } + $this->soughtPubDate = $pubDate; + } + + /** + * Get the raw xml content from a cache file + * + * @return string|int Content string or 0 if the file doesn't exist + */ + private function getCachedXml() + { + $filesArray = scandir($this->cachePath); + $filename = $this->matchFilename($filesArray); + + if ($filename) { + $rawContent = file_get_contents($this->cachePath . $filename); + return $rawContent; + } + + return 0; + } + + /** + * Get the raw xml content from the NBP api + * + * @return string|int Content string or 0 if the file doesn't exist + * + * @throws \Exception + */ + private function downloadXml() + { + $filename = $this->findFileInRatesDir(); + if ($filename) { + $response = $this->guzzle->get(self::NBP_XML_URL . $filename); + if ($response->getStatusCode() === 200) { + $rawContent = (string)$response->getBody(); + if ($this->cachePath) { + file_put_contents($this->cachePath . $filename, $rawContent); + } + return $rawContent; + } else { + throw new \Exception( + "Invalid response status code: {$response->getStatusCode()} {$response->getReasonPhrase()}" + ); + } + } else { + return 0; + } + } + + /** + * Find the file related to the publication date + * + * @return string|int Filename or 0 if the file was not found + * + * @throws \Exception + */ + private function findFileInRatesDir() + { + $dirname = $this->constructDirname(); + + $response = $this->guzzle->get(self::NBP_XML_URL . $dirname); + if ($response->getStatusCode() === 200) { + $rawContent = (string)$response->getBody(); + } else { + throw new \Exception( + "Invalid response status code: {$response->getStatusCode()} {$response->getReasonPhrase()}" + ); + } + + $filesArray = explode("\r\n", $rawContent); + $filename = $this->matchFilename($filesArray); + + return $filename; + } + + /** + * Construct the name of directory containing the files + * + * @return string + */ + private function constructDirname() + { + if ($this->soughtPubDate->format('Y') !== (new \DateTime())->format('Y')) { + $dirname = "dir{$this->soughtPubDate->format('Y')}.txt"; + } else { + $dirname = 'dir.txt'; + } + return $dirname; + } + + /** + * Searches files array for a match to the publication date + * + * @todo Optimize to avoid unnecessary regex + * + * @param array $filesArray + * + * @return string|int Filename or 0 if the file was not found + */ + private function matchFilename(array $filesArray) + { + foreach ($filesArray as $filename) { + if (preg_match('/(a\d{3}z' . $this->soughtPubDate->format('ymd') . ')/', $filename, $matches)) { + $filename = "{$matches[1]}.xml"; + return $filename; + } + } + + return 0; + } +} diff --git a/src/NBPCurrencyConverter.php b/src/NBPCurrencyConverter.php deleted file mode 100644 index 9e97376..0000000 --- a/src/NBPCurrencyConverter.php +++ /dev/null @@ -1,175 +0,0 @@ -guzzle = $guzzle; - $this->cacheTime = (int)$cacheTime; - if ($this->cacheTime && !is_dir($cachePath)) { - throw new \Exception('Invalid cache path'); - } - $this->cachePath = rtrim((string)$cachePath, '/') . '/'; - } - - /** - * Get the average exchange rates - * - * @return array - * - * @throws \Exception - */ - public function averageExchangeRates() - { - if ($this->cacheTime && ($cachedXml = $this->cachedXml())) { - $rawContent = $cachedXml; - } else { - $rawContent = $this->downloadedXml(); - } - return $this->parseXml($rawContent); - } - - /** - * Convert amount from one currency to another - * - * @param string $fromAmount Amount with four digits after decimal point, e.g. '123.0000' - * @param string $fromCurrency E.g. 'USD' or 'EUR' - * @param string $toCurrency E.g. 'USD' or 'EUR' - * - * @return array - * - * @throws \Exception - */ - public function convert($fromAmount, $fromCurrency, $toCurrency) - { - if (!preg_match('/^\d+\.(\d{4})$/', $fromAmount)) { - throw new \Exception('Invalid format of amount'); - } - - $rates = $this->averageExchangeRates(); - - $fromCurrency = strtoupper($fromCurrency); - $toCurrency = strtoupper($toCurrency); - if (!isset($rates['waluty'][$fromCurrency]) || !isset($rates['waluty'][$toCurrency])) { - throw new \Exception('Invalid currency code'); - } - - $fromMultiplier = str_replace(',', '.', $rates['waluty'][$fromCurrency]['przelicznik']); - $fromAverageRate = str_replace(',', '.', $rates['waluty'][$fromCurrency]['kurs_sredni']); - $toMultiplier = str_replace(',', '.', $rates['waluty'][$toCurrency]['przelicznik']); - $toAverageRate = str_replace(',', '.', $rates['waluty'][$toCurrency]['kurs_sredni']); - - bcscale(6); - $plnAmount = bcdiv(bcmul($fromAmount, $fromAverageRate), $fromMultiplier); - $resultAmount = bcdiv(bcmul($plnAmount, $toMultiplier), $toAverageRate); - $roundedResult = BCMathHelper::bcround($resultAmount, 4); - - return [ - 'publication_date' => $rates['data_publikacji'], - 'amount' => $roundedResult, - 'currency' => $toCurrency - ]; - } - - /** - * Get the raw xml content from a cache file - * - * @return string|int Content string or 0 if the file doesn't exist or is obsolete - */ - private function cachedXml() - { - try { - $cache = new \SplFileObject($this->cachePath . self::CACHE_FILENAME); - } catch (\Exception $e) { - $cache = null; - } - if (($cache instanceof \SplFileObject) && ($cache->getMTime() > strtotime("-{$this->cacheTime} minutes"))) { - return $cache->fread($cache->getSize()); - } else { - return 0; - } - } - - /** - * Get the raw xml content from the NBP api - * - * @return string - * - * @throws \Exception - */ - private function downloadedXml() - { - $response = $this->guzzle->get(self::NBP_XML_URL); - if ($response->getStatusCode() === 200) { - $rawContent = (string)$response->getBody(); - if ($this->cacheTime) { - file_put_contents($this->cachePath . self::CACHE_FILENAME, $rawContent); - } - return $rawContent; - } else { - throw new \Exception( - "Invalid response status code: {$response->getStatusCode()} {$response->getReasonPhrase()}" - ); - } - } - - /** - * Transform the raw xml content into an array - * - * @param string $rawContent - * - * @return array - * - * @throws \Exception - */ - private function parseXml($rawContent) - { - $xml = new \SimpleXMLElement($rawContent); - if (empty($xml->numer_tabeli) || empty($xml->data_publikacji) || empty($xml->pozycja)) { - throw new \Exception('Invalid xml response content'); - } - $rates = [ - 'numer_tabeli' => (string)$xml->numer_tabeli, - 'data_publikacji' => (string)$xml->data_publikacji, - 'waluty' => [ - 'PLN' => [ - 'nazwa_waluty' => 'złoty polski', - 'przelicznik' => '1', - 'kurs_sredni' => '1' - ] - ] - ]; - foreach ($xml->pozycja as $pozycja) { - $rates['waluty'] += [ - (string)$pozycja->kod_waluty => [ - 'nazwa_waluty' => (string)$pozycja->nazwa_waluty, - 'przelicznik' => (string)$pozycja->przelicznik, - 'kurs_sredni' => (string)$pozycja->kurs_sredni - ] - ]; - } - return $rates; - } -} diff --git a/tests/CurrencyConverterTest.php b/tests/CurrencyConverterTest.php new file mode 100644 index 0000000..d56834a --- /dev/null +++ b/tests/CurrencyConverterTest.php @@ -0,0 +1,242 @@ +shouldReceive('getStatusCode') + ->andReturn(200) + ->shouldReceive('getBody') + ->andReturn($ratesContent) + ->mock(); + $dirMock = Mockery::mock('GuzzleHttp\Client') + ->shouldReceive('getStatusCode') + ->andReturn(200) + ->shouldReceive('getBody') + ->andReturn($dirContent) + ->mock(); + $guzzleMock = Mockery::mock('GuzzleHttp\Client') + ->shouldReceive('get') + ->with('http://www.nbp.pl/kursy/xml/a127z150703.xml') + ->andReturn($ratesMock) + ->shouldReceive('get') + ->with('http://www.nbp.pl/kursy/xml/dir.txt') + ->andReturn($dirMock) + ->mock(); + + return $guzzleMock; + } + + public function testConvert() + { + $converter = new CurrencyConverter(new ExRatesDayTableFinder($this->guzzleMock(), new ExRatesDayTableFactory())); + $pubDate = new \DateTime('2015-07-03'); + + $this->assertEquals('0.2651', $converter->convert('1.0000', 'PLN', 'USD', $pubDate)['amount']); + $this->assertEquals('3.7726', $converter->convert('1.0000', 'USD', 'PLN', $pubDate)['amount']); + $this->assertEquals('123.4567', $converter->convert('123.4567', 'PLN', 'PLN', $pubDate)['amount']); + $this->assertEquals('32.7246', $converter->convert('123.4567', 'PLN', 'USD', $pubDate)['amount']); + $this->assertEquals('465.7527', $converter->convert('123.4567', 'USD', 'PLN', $pubDate)['amount']); + $this->assertEquals('9265.0432', $converter->convert('123.4567', 'PLN', 'HUF', $pubDate)['amount']); + $this->assertEquals('1.6451', $converter->convert('123.4567', 'HUF', 'PLN', $pubDate)['amount']); + $this->assertEquals('137.1028', $converter->convert('123.4567', 'EUR', 'USD', $pubDate)['amount']); + $this->assertEquals('111.1688', $converter->convert('123.4567', 'USD', 'EUR', $pubDate)['amount']); + $this->assertEquals('34953.3018', $converter->convert('123.4567', 'USD', 'HUF', $pubDate)['amount']); + $this->assertEquals('0.4361', $converter->convert('123.4567', 'HUF', 'USD', $pubDate)['amount']); + $this->assertEquals('284.0662', $converter->convert('123.4567', 'JPY', 'HUF', $pubDate)['amount']); + $this->assertEquals('53.6549', $converter->convert('123.4567', 'HUF', 'JPY', $pubDate)['amount']); + $this->assertEquals('123.4567', $converter->convert('123.4567', 'JPY', 'JPY', $pubDate)['amount']); + $this->assertEquals('53654981.1634', $converter->convert('123456789.6789', 'HUF', 'JPY', $pubDate)['amount']); + $this->assertEquals('284066429.3850', $converter->convert('123456789.6789', 'JPY', 'HUF', $pubDate)['amount']); + $this->assertEquals('32724590.3830', $converter->convert('123456789.6789', 'PLN', 'USD', $pubDate)['amount']); + $this->assertEquals('465753084.7426', $converter->convert('123456789.6789', 'USD', 'PLN', $pubDate)['amount']); + } + + public function testInvalidPublicationDate() + { + $converter = new CurrencyConverter(new ExRatesDayTableFinder($this->guzzleMock(), new ExRatesDayTableFactory())); + + $numExceptions = 0; + try { + $pubDate = new \DateTime('2002-01-01'); + $converter->convert('123.4567', 'PLN', 'USD', $pubDate); + } catch (\Exception $e) { + $this->assertEquals('Invalid publication date', $e->getMessage()); + $numExceptions++; + } + try { + $pubDate = new \DateTime('2115-01-01'); + $converter->convert('123.4567', 'PLN', 'USD', $pubDate); + } catch (\Exception $e) { + $this->assertEquals('Invalid publication date', $e->getMessage()); + $numExceptions++; + } + + $this->assertEquals(2, $numExceptions); + } + + public function testInvalidFormatOfAmount() + { + $converter = new CurrencyConverter(new ExRatesDayTableFinder($this->guzzleMock(), new ExRatesDayTableFactory())); + $pubDate = new \DateTime('2015-07-03'); + + $numExceptions = 0; + try { + $converter->convert('123.45', 'PLN', 'USD', $pubDate); + } catch (\Exception $e) { + $this->assertEquals('Invalid format of amount', $e->getMessage()); + $numExceptions++; + } + try { + $converter->convert('123,4567', 'PLN', 'USD', $pubDate); + } catch (\Exception $e) { + $this->assertEquals('Invalid format of amount', $e->getMessage()); + $numExceptions++; + } + try { + $converter->convert('.4567', 'PLN', 'USD', $pubDate); + } catch (\Exception $e) { + $this->assertEquals('Invalid format of amount', $e->getMessage()); + $numExceptions++; + } + try { + $converter->convert('1234567', 'PLN', 'USD', $pubDate); + } catch (\Exception $e) { + $this->assertEquals('Invalid format of amount', $e->getMessage()); + $numExceptions++; + } + + $this->assertEquals(4, $numExceptions); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Invalid currency code + */ + public function testInvalidCurrencyCode() + { + $converter = new CurrencyConverter(new ExRatesDayTableFinder($this->guzzleMock(), new ExRatesDayTableFactory())); + $pubDate = new \DateTime('2015-07-03'); + + $converter->convert('123.4567', 'ABC', 'USD', $pubDate); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Invalid cache path + */ + public function testInvalidCachePath() + { + new CurrencyConverter(new ExRatesDayTableFinder($this->guzzleMock(), new ExRatesDayTableFactory(), '/this/folder/doesnotexist')); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage String could not be parsed as XML + */ + public function testInvalidXml() + { + $dirContent = file_get_contents(__DIR__ . '/test_dir.txt'); + $ratesMock = Mockery::mock('GuzzleHttp\Client') + ->shouldReceive('getStatusCode') + ->andReturn(200) + ->shouldReceive('getBody') + ->andReturn('Hello! I\'m XML') + ->mock(); + $dirMock = Mockery::mock('GuzzleHttp\Client') + ->shouldReceive('getStatusCode') + ->andReturn(200) + ->shouldReceive('getBody') + ->andReturn($dirContent) + ->mock(); + $guzzleMock = Mockery::mock('GuzzleHttp\Client') + ->shouldReceive('get') + ->with('http://www.nbp.pl/kursy/xml/a127z150703.xml') + ->andReturn($ratesMock) + ->shouldReceive('get') + ->with('http://www.nbp.pl/kursy/xml/dir.txt') + ->andReturn($dirMock) + ->mock(); + + $converter = new CurrencyConverter(new ExRatesDayTableFinder($guzzleMock, new ExRatesDayTableFactory())); + $pubDate = new \DateTime('2015-07-03'); + $converter->convert('123.4567', 'PLN', 'USD', $pubDate); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Invalid response status code: 500 A good reason + */ + public function testInvalidResponseStatusCode() + { + $guzzleMock = Mockery::mock('GuzzleHttp\Client') + ->shouldReceive('get') + ->andReturn(Mockery::self()) + ->shouldReceive('getStatusCode') + ->andReturn(500) + ->shouldReceive('getReasonPhrase') + ->andReturn('A good reason') + ->mock(); + + $converter = new CurrencyConverter(new ExRatesDayTableFinder($guzzleMock, new ExRatesDayTableFactory())); + $converter->convert('123.4567', 'PLN', 'USD'); + } + + public function testCache() + { + $ratesContent = file_get_contents(__DIR__ . '/test_rates.xml'); + $dirContent = file_get_contents(__DIR__ . '/test_dir.txt'); + $ratesMock = Mockery::mock('GuzzleHttp\Client') + ->shouldReceive('getStatusCode') + ->once() + ->andReturn(200) + ->shouldReceive('getBody') + ->once() + ->andReturn($ratesContent) + ->mock(); + $dirMock = Mockery::mock('GuzzleHttp\Client') + ->shouldReceive('getStatusCode') + ->once() + ->andReturn(200) + ->shouldReceive('getBody') + ->once() + ->andReturn($dirContent) + ->mock(); + $guzzleMock = Mockery::mock('GuzzleHttp\Client') + ->shouldReceive('get') + ->once() + ->with('http://www.nbp.pl/kursy/xml/a127z150703.xml') + ->andReturn($ratesMock) + ->shouldReceive('get') + ->once() + ->with('http://www.nbp.pl/kursy/xml/dir.txt') + ->andReturn($dirMock) + ->mock(); + + $converter = new CurrencyConverter(new ExRatesDayTableFinder($guzzleMock, new ExRatesDayTableFactory(), __DIR__)); + $pubDate = new \DateTime('2015-07-03'); + $converter->convert('123.4567', 'PLN', 'USD', $pubDate); + + $pathToFile = __DIR__ . '/a127z150703.xml'; + $this->assertFileExists($pathToFile); + + $converter->convert('123.4567', 'PLN', 'USD', $pubDate); + + unlink($pathToFile); + } + + public function tearDown() + { + Mockery::close(); + } +} diff --git a/tests/NBPCurrencyConverterTest.php b/tests/NBPCurrencyConverterTest.php deleted file mode 100644 index e27593b..0000000 --- a/tests/NBPCurrencyConverterTest.php +++ /dev/null @@ -1,169 +0,0 @@ -shouldReceive('get') - ->andReturn(Mockery::self()) - ->shouldReceive('getStatusCode') - ->andReturn(200) - ->shouldReceive('getBody') - ->andReturn($rawContent) - ->mock(); - - return $guzzleMock; - } - - public function testConvert() - { - $converter = new NBPCurrencyConverter($this->guzzleMock(), null, 0); - - $this->assertEquals('0.2651', $converter->convert('1.0000', 'PLN', 'USD')['amount']); - $this->assertEquals('3.7726', $converter->convert('1.0000', 'USD', 'PLN')['amount']); - $this->assertEquals('123.4567', $converter->convert('123.4567', 'PLN', 'PLN')['amount']); - $this->assertEquals('32.7246', $converter->convert('123.4567', 'PLN', 'USD')['amount']); - $this->assertEquals('465.7527', $converter->convert('123.4567', 'USD', 'PLN')['amount']); - $this->assertEquals('9265.0432', $converter->convert('123.4567', 'PLN', 'HUF')['amount']); - $this->assertEquals('1.6451', $converter->convert('123.4567', 'HUF', 'PLN')['amount']); - $this->assertEquals('137.1028', $converter->convert('123.4567', 'EUR', 'USD')['amount']); - $this->assertEquals('111.1688', $converter->convert('123.4567', 'USD', 'EUR')['amount']); - $this->assertEquals('34953.3018', $converter->convert('123.4567', 'USD', 'HUF')['amount']); - $this->assertEquals('0.4361', $converter->convert('123.4567', 'HUF', 'USD')['amount']); - $this->assertEquals('284.0662', $converter->convert('123.4567', 'JPY', 'HUF')['amount']); - $this->assertEquals('53.6549', $converter->convert('123.4567', 'HUF', 'JPY')['amount']); - $this->assertEquals('123.4567', $converter->convert('123.4567', 'JPY', 'JPY')['amount']); - $this->assertEquals('53654981.1634', $converter->convert('123456789.6789', 'HUF', 'JPY')['amount']); - $this->assertEquals('284066429.3850', $converter->convert('123456789.6789', 'JPY', 'HUF')['amount']); - $this->assertEquals('32724590.3830', $converter->convert('123456789.6789', 'PLN', 'USD')['amount']); - $this->assertEquals('465753084.7426', $converter->convert('123456789.6789', 'USD', 'PLN')['amount']); - } - - public function testInvalidFormatOfAmount() - { - $converter = new NBPCurrencyConverter($this->guzzleMock(), null, 0); - - $numExceptions = 0; - try { - $converter->convert('123.45', 'PLN', 'USD'); - } catch (\Exception $e) { - $this->assertEquals('Invalid format of amount', $e->getMessage()); - $numExceptions++; - } - try { - $converter->convert('123,4567', 'PLN', 'USD'); - } catch (\Exception $e) { - $this->assertEquals('Invalid format of amount', $e->getMessage()); - $numExceptions++; - } - try { - $converter->convert('.4567', 'PLN', 'USD'); - } catch (\Exception $e) { - $this->assertEquals('Invalid format of amount', $e->getMessage()); - $numExceptions++; - } - try { - $converter->convert('1234567', 'PLN', 'USD'); - } catch (\Exception $e) { - $this->assertEquals('Invalid format of amount', $e->getMessage()); - $numExceptions++; - } - - $this->assertEquals(4, $numExceptions); - } - - /** - * @expectedException \Exception - * @expectedExceptionMessage Invalid currency code - */ - public function testInvalidCurrencyCode() - { - $converter = new NBPCurrencyConverter($this->guzzleMock(), null, 0); - $converter->convert('123.4567', 'ABC', 'USD'); - } - - /** - * @expectedException \Exception - * @expectedExceptionMessage Invalid cache path - */ - public function testInvalidCachePath() - { - new NBPCurrencyConverter($this->guzzleMock(), '/this/folder/doesnotexist'); - } - - /** - * @expectedException \Exception - * @expectedExceptionMessage String could not be parsed as XML - */ - public function testInvalidXml() - { - $guzzleMock = Mockery::mock('GuzzleHttp\Client') - ->shouldReceive('get') - ->andReturn(Mockery::self()) - ->shouldReceive('getStatusCode') - ->andReturn(200) - ->shouldReceive('getBody') - ->andReturn('Hello! I\'m XML') - ->mock(); - - $converter = new NBPCurrencyConverter($guzzleMock, null, 0); - $converter->convert('123.4567', 'PLN', 'USD'); - } - - /** - * @expectedException \Exception - * @expectedExceptionMessage Invalid response status code: 500 A good reason - */ - public function testInvalidResponseStatusCode() - { - $guzzleMock = Mockery::mock('GuzzleHttp\Client') - ->shouldReceive('get') - ->andReturn(Mockery::self()) - ->shouldReceive('getStatusCode') - ->andReturn(500) - ->shouldReceive('getReasonPhrase') - ->andReturn('A good reason') - ->mock(); - - $converter = new NBPCurrencyConverter($guzzleMock, null, 0); - $converter->convert('123.4567', 'PLN', 'USD'); - } - - public function testCache() - { - $rawContent = file_get_contents(__DIR__ . '/test_rates.xml'); - $guzzleMock = Mockery::mock('GuzzleHttp\Client') - ->shouldReceive('get') - ->once() - ->andReturn(Mockery::self()) - ->shouldReceive('getStatusCode') - ->once() - ->andReturn(200) - ->shouldReceive('getBody') - ->once() - ->andReturn($rawContent) - ->mock(); - - $converter = new NBPCurrencyConverter($guzzleMock, __DIR__); - $converter->convert('123.4567', 'PLN', 'USD'); - - $pathToFile = __DIR__ . '/exchange_rates.xml'; - $this->assertFileExists($pathToFile); - - $converter->convert('123.4567', 'PLN', 'USD'); - - unlink($pathToFile); - } - - public function tearDown() - { - Mockery::close(); - } -} diff --git a/tests/test_dir.txt b/tests/test_dir.txt new file mode 100644 index 0000000..e51a03d --- /dev/null +++ b/tests/test_dir.txt @@ -0,0 +1,408 @@ + +c001z150102 +h001z150102 +a001z150102 +c002z150105 +h002z150105 +a002z150105 +c003z150107 +h003z150107 +a003z150107 +b001z150107 +c004z150108 +h004z150108 +a004z150108 +c005z150109 +h005z150109 +a005z150109 +c006z150112 +h006z150112 +a006z150112 +c007z150113 +h007z150113 +a007z150113 +c008z150114 +h008z150114 +a008z150114 +b002z150114 +c009z150115 +h009z150115 +a009z150115 +c010z150116 +h010z150116 +a010z150116 +c011z150119 +h011z150119 +a011z150119 +c012z150120 +h012z150120 +a012z150120 +c013z150121 +h013z150121 +a013z150121 +b003z150121 +c014z150122 +h014z150122 +a014z150122 +c015z150123 +h015z150123 +a015z150123 +c016z150126 +h016z150126 +a016z150126 +c017z150127 +h017z150127 +a017z150127 +c018z150128 +h018z150128 +a018z150128 +b004z150128 +c019z150129 +h019z150129 +a019z150129 +c020z150130 +h020z150130 +a020z150130 +c021z150202 +h021z150202 +a021z150202 +c022z150203 +h022z150203 +a022z150203 +c023z150204 +h023z150204 +a023z150204 +b005z150204 +c024z150205 +h024z150205 +a024z150205 +c025z150206 +h025z150206 +a025z150206 +c026z150209 +h026z150209 +a026z150209 +c027z150210 +h027z150210 +a027z150210 +c028z150211 +h028z150211 +a028z150211 +b006z150211 +c029z150212 +h029z150212 +a029z150212 +c030z150213 +h030z150213 +a030z150213 +c031z150216 +h031z150216 +a031z150216 +c032z150217 +h032z150217 +a032z150217 +c033z150218 +h033z150218 +a033z150218 +b007z150218 +c034z150219 +h034z150219 +a034z150219 +c035z150220 +h035z150220 +a035z150220 +c036z150223 +h036z150223 +a036z150223 +c037z150224 +h037z150224 +a037z150224 +c038z150225 +h038z150225 +a038z150225 +b008z150225 +c039z150226 +h039z150226 +a039z150226 +c040z150227 +h040z150227 +a040z150227 +c041z150302 +h041z150302 +a041z150302 +c042z150303 +h042z150303 +a042z150303 +c043z150304 +h043z150304 +a043z150304 +b009z150304 +c044z150305 +h044z150305 +a044z150305 +c045z150306 +h045z150306 +a045z150306 +c046z150309 +h046z150309 +a046z150309 +c047z150310 +h047z150310 +a047z150310 +c048z150311 +h048z150311 +a048z150311 +b010z150311 +c049z150312 +h049z150312 +a049z150312 +c050z150313 +h050z150313 +a050z150313 +c051z150316 +h051z150316 +a051z150316 +c052z150317 +h052z150317 +a052z150317 +c053z150318 +h053z150318 +a053z150318 +b011z150318 +c054z150319 +h054z150319 +a054z150319 +c055z150320 +h055z150320 +a055z150320 +c056z150323 +h056z150323 +a056z150323 +c057z150324 +h057z150324 +a057z150324 +h058z150325 +c058z150325 +a058z150325 +b012z150325 +c059z150326 +h059z150326 +a059z150326 +c060z150327 +h060z150327 +a060z150327 +c061z150330 +h061z150330 +a061z150330 +c062z150331 +h062z150331 +a062z150331 +c063z150401 +h063z150401 +a063z150401 +b013z150401 +c064z150402 +h064z150402 +a064z150402 +c065z150403 +h065z150403 +a065z150403 +c066z150407 +h066z150407 +a066z150407 +c067z150408 +h067z150408 +a067z150408 +b014z150408 +c068z150409 +h068z150409 +a068z150409 +c069z150410 +h069z150410 +a069z150410 +c070z150413 +h070z150413 +a070z150413 +c071z150414 +h071z150414 +a071z150414 +c072z150415 +h072z150415 +a072z150415 +b015z150415 +c073z150416 +h073z150416 +a073z150416 +c074z150417 +h074z150417 +a074z150417 +c075z150420 +h075z150420 +a075z150420 +c076z150421 +h076z150421 +a076z150421 +c077z150422 +h077z150422 +a077z150422 +b016z150422 +c078z150423 +h078z150423 +a078z150423 +c079z150424 +h079z150424 +a079z150424 +c080z150427 +h080z150427 +a080z150427 +c081z150428 +h081z150428 +a081z150428 +c082z150429 +h082z150429 +a082z150429 +b017z150429 +c083z150430 +h083z150430 +a083z150430 +c084z150504 +h084z150504 +a084z150504 +c085z150505 +h085z150505 +a085z150505 +c086z150506 +h086z150506 +a086z150506 +b018z150506 +c087z150507 +h087z150507 +a087z150507 +c088z150508 +h088z150508 +a088z150508 +c089z150511 +h089z150511 +a089z150511 +c090z150512 +h090z150512 +a090z150512 +c091z150513 +h091z150513 +a091z150513 +b019z150513 +c092z150514 +h092z150514 +a092z150514 +c093z150515 +h093z150515 +a093z150515 +c094z150518 +h094z150518 +a094z150518 +c095z150519 +h095z150519 +a095z150519 +c096z150520 +h096z150520 +a096z150520 +b020z150520 +c097z150521 +h097z150521 +a097z150521 +c098z150522 +h098z150522 +a098z150522 +c099z150525 +h099z150525 +a099z150525 +c100z150526 +h100z150526 +a100z150526 +c101z150527 +h101z150527 +a101z150527 +b021z150527 +c102z150528 +h102z150528 +a102z150528 +c103z150529 +h103z150529 +a103z150529 +c104z150601 +h104z150601 +a104z150601 +c105z150602 +h105z150602 +a105z150602 +c106z150603 +h106z150603 +a106z150603 +b022z150603 +c107z150605 +h107z150605 +a107z150605 +c108z150608 +h108z150608 +a108z150608 +c109z150609 +h109z150609 +a109z150609 +c110z150610 +h110z150610 +a110z150610 +b023z150610 +c111z150611 +h111z150611 +a111z150611 +c112z150612 +h112z150612 +a112z150612 +c113z150615 +h113z150615 +a113z150615 +c114z150616 +h114z150616 +a114z150616 +c115z150617 +h115z150617 +a115z150617 +b024z150617 +c116z150618 +h116z150618 +a116z150618 +c117z150619 +h117z150619 +a117z150619 +c118z150622 +h118z150622 +a118z150622 +c119z150623 +h119z150623 +a119z150623 +c120z150624 +h120z150624 +a120z150624 +b025z150624 +c121z150625 +h121z150625 +a121z150625 +c122z150626 +h122z150626 +a122z150626 +c123z150629 +h123z150629 +a123z150629 +c124z150630 +h124z150630 +a124z150630 +c125z150701 +h125z150701 +a125z150701 +b026z150701 +c126z150702 +h126z150702 +a126z150702 +c127z150703 +h127z150703 +a127z150703