Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Desafio-apiki #168

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion codeception.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ paths:

settings:
shuffle: false
lint: true
lint: true
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Desafio para candidatos a back-end.",
"type": "project",
"require": {
"php": ">= 7.4"
"php": ">= 8.2"
},
"require-dev": {
"squizlabs/php_codesniffer": "^3.4",
Expand Down
44 changes: 44 additions & 0 deletions src/CurrencyConverter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace App;

/**
* Class CurrencyConverter
*
* Classe responsável por converter valores entre diferentes moedas.
*
* @package App
*/
class CurrencyConverter
{
const CURRENCY_BRL = 'BRL';
const CURRENCY_USD = 'USD';
const CURRENCY_EUR = 'EUR';

/**
* Converte o valor de uma moeda para outra com base na taxa de conversão.
*
* @param float $amount Valor a ser convertido.
* @param string $fromCurrency Moeda de origem.
* @param string $toCurrency Moeda de destino.
* @param float $rate Taxa de conversão.
*
* @return float Valor convertido.
* @throws \InvalidArgumentException
*/
public function convert(float $amount, string $fromCurrency, string $toCurrency, float $rate): float
{
if ($amount <= 0 || $rate <= 0) {
throw new \InvalidArgumentException("Invalid amount or rate.");
}

if (!in_array($fromCurrency, [self::CURRENCY_BRL, self::CURRENCY_USD, self::CURRENCY_EUR], true) ||
!in_array($toCurrency, [self::CURRENCY_BRL, self::CURRENCY_USD, self::CURRENCY_EUR], true)) {
throw new \InvalidArgumentException("Invalid currency.");
}

$convertedAmount = $amount * $rate;

return round($convertedAmount, 2);
}
}
54 changes: 54 additions & 0 deletions src/Router.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace App;

/**
* Class Router
*
* Classe responsável por realizar o roteamento da URL da requisição.
*
* @package App
*/
class Router
{
/**
* Realiza o roteamento da URL da requisição.
*
* @param string $url URL da requisição.
*
* @return array Dados da requisição roteada (amount, fromCurrency, toCurrency, rate).
* @throws \InvalidArgumentException Caso a ação seja inválida, o número de parâmetros seja inválido,
* ou o valor ou taxa sejam inválidos.
*/
public function route(string $url): array
{
$urlParts = explode('/', trim($url, '/'));
$action = array_shift($urlParts);

if ($action !== 'exchange') {
throw new \InvalidArgumentException("Invalid action.");
}

if (count($urlParts) !== 4) {
throw new \InvalidArgumentException("Invalid number of parameters.");
}

list($amount, $fromCurrency, $toCurrency, $rate) = $urlParts;

if (!is_numeric($amount) || !is_numeric($rate)) {
throw new \InvalidArgumentException("Invalid amount or rate.");
}

// Optionally validate currencies here if needed
// Example: if (!in_array($fromCurrency, ['BRL', 'USD', 'EUR']) || !in_array($toCurrency, ['BRL', 'USD', 'EUR'])) {
// throw new \InvalidArgumentException("Invalid currency.");
// }

return [
'amount' => (float) $amount,
'fromCurrency' => strtoupper($fromCurrency),
'toCurrency' => strtoupper($toCurrency),
'rate' => (float) $rate,
];
}
}
40 changes: 36 additions & 4 deletions src/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,49 @@
/**
* Back-end Challenge.
*
* PHP version 7.4
*
* Este será o arquivo chamado na execução dos testes automátizados.
* PHP version 8.2
*
* @category Challenge
* @package Back-end
* @author Seu Nome <seu-email@seu-provedor.com>
* @author Guilherme Pontes <jgmarinhopontes@hotmail.com>
* @license http://opensource.org/licenses/MIT MIT
* @link https://github.com/apiki/back-end-challenge
*/
declare(strict_types=1);

namespace App;

require __DIR__ . '/../vendor/autoload.php';

$router = new Router();
$currencyConverter = new CurrencyConverter();

try {
$requestData = $router->route($_SERVER['REQUEST_URI']);

// Validação adicional pode ser adicionada aqui, se necessário
if (!isset($requestData['amount'], $requestData['fromCurrency'], $requestData['toCurrency'], $requestData['rate'])) {
throw new \InvalidArgumentException("Missing required parameters.");
}

$convertedAmount = $currencyConverter->convert(
$requestData['amount'],
$requestData['fromCurrency'],
$requestData['toCurrency'],
$requestData['rate']
);

$response = [
'valorConvertido' => $convertedAmount,
'simboloMoeda' =>
$requestData['toCurrency'] === CurrencyConverter::CURRENCY_USD
? '$'
: 'R$',
];

header('Content-Type: application/json');
echo json_encode($response);
} catch (\InvalidArgumentException $e) {
header("HTTP/1.1 400 Bad Request");
echo json_encode(['error' => $e->getMessage()]);
}
17 changes: 16 additions & 1 deletion tests/ApiCest.php
Original file line number Diff line number Diff line change
@@ -1,76 +1,88 @@
<?php

class ApiCest
{
// Testa a API sem fornecer o valor
public function tryApiWithoutValue(ApiTester $I)
{
$I->sendGET('/');
$I->seeResponseCodeIs(400);
$I->seeResponseIsJson();
}

// Testa a API sem fornecer a moeda de origem
public function tryApiWithoutFrom(ApiTester $I)
{
$I->sendGET('/10');
$I->seeResponseCodeIs(400);
$I->seeResponseIsJson();
}

// Testa a API sem fornecer a moeda de destino
public function tryApiWithoutTo(ApiTester $I)
{
$I->sendGET('/10/EUR');
$I->seeResponseCodeIs(400);
$I->seeResponseIsJson();
}

// Testa a API sem fornecer a taxa de conversão
public function tryApiWithoutRate(ApiTester $I)
{
$I->sendGET('/10/EUR/USD');
$I->seeResponseCodeIs(400);
$I->seeResponseIsJson();
}

// Testa a API com valor inválido
public function tryApiInvalidValue(ApiTester $I)
{
$I->sendGET('/a/EUR/USD/0.5');
$I->seeResponseCodeIs(400);
$I->seeResponseIsJson();
}

// Testa a API com valor negativo
public function tryApiNegativeValue(ApiTester $I)
{
$I->sendGET('/-10/EUR/USD/0.5');
$I->seeResponseCodeIs(400);
$I->seeResponseIsJson();
}

// Testa a API com moeda de origem inválida
public function tryApiInvalidFrom(ApiTester $I)
{
$I->sendGET('/10/eur/USD/0.5');
$I->seeResponseCodeIs(400);
$I->seeResponseIsJson();
}

// Testa a API com moeda de destino inválida
public function tryApiInvalidTo(ApiTester $I)
{
$I->sendGET('/10/EUR/usd/0.5');
$I->seeResponseCodeIs(400);
$I->seeResponseIsJson();
}

// Testa a API com taxa de conversão inválida
public function tryApiInvalidRate(ApiTester $I)
{
$I->sendGET('/10/EUR/USD/a');
$I->seeResponseCodeIs(400);
$I->seeResponseIsJson();
}

// Testa a API com taxa de conversão negativa
public function tryApiNegativeRate(ApiTester $I)
{
$I->sendGET('/10/EUR/USD/-0.5');
$I->seeResponseCodeIs(400);
$I->seeResponseIsJson();
}

// Testa a conversão de BRL para USD
public function tryApiBrlToUsd(ApiTester $I)
{
$I->sendGET('/7.8/BRL/USD/0.5');
Expand All @@ -82,6 +94,7 @@ public function tryApiBrlToUsd(ApiTester $I)
]);
}

// Testa a conversão de USD para BRL
public function tryApiUsdToBrl(ApiTester $I)
{
$I->sendGET('/7/USD/BRL/0.5');
Expand All @@ -93,6 +106,7 @@ public function tryApiUsdToBrl(ApiTester $I)
]);
}

// Testa a conversão de BRL para EUR
public function tryApiBrlToEur(ApiTester $I)
{
$I->sendGET('/7/BRL/EUR/5');
Expand All @@ -104,6 +118,7 @@ public function tryApiBrlToEur(ApiTester $I)
]);
}

// Testa a conversão de EUR para BRL
public function tryApiEurToBrl(ApiTester $I)
{
$I->sendGET('/7/EUR/BRL/5');
Expand All @@ -114,4 +129,4 @@ public function tryApiEurToBrl(ApiTester $I)
'simboloMoeda' => 'R$',
]);
}
}
}
Loading