Add phpUnit testing and update test file.

Test file does not run any tests automatically but they need to be
triggered with the _GET parameters.

A full phpunit test has been added for the full functionality
This commit is contained in:
2022-06-13 19:53:00 +09:00
parent d69781a709
commit 96b24f9424
6 changed files with 1145 additions and 26 deletions

View File

@@ -26,6 +26,7 @@
},
"require-dev": {
"phpunit/phpunit": "^9",
"gullevek/dotenv": "dev-master"
"gullevek/dotenv": "dev-master",
"dg/bypass-finals": "dev-master"
}
}

View File

@@ -2,4 +2,8 @@
colors="true"
verbose="true"
>
<!-- Below removes final from classes for mock tests -->
<extensions>
<extension class="test\phpUnit\Hook\BypassFinalHook" file="test/phpUnit/Hook/BypassFinalHook.php" />
</extensions>
</phpunit>

View File

@@ -0,0 +1,140 @@
# Return data from AWS as json string
## Mock tests self
Tests run in local mock tests without connection to AWS
### funds
```json
{"availableFunds":{"amount":0.0,"currencyCode":"JPY"},"status":"SUCCESS","timestamp":"20220610T085450Z"}
```
### buy
```json
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a309167e7a4","gcClaimCode":"LJ49-AKDUV6-UYCP","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5535125272070255","status":"SUCCESS"}
```
### cancel
```json
{"creationRequestId":"EG3bd_62a309167e7a4","gcId":"5535125272070255","status":"SUCCESS"}
```
### buy other 1
```json
{"cardInfo":{"cardNumber":null,"cardStatus":"RefundedToPurchaser","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a309167e7a4","gcClaimCode":"LJ49-AKDUV6-UYCP","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5535125272070255","status":"SUCCESS"}
```
### buy aother 2
```json
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a30923e9705","gcClaimCode":"UM97-FD5QKK-WKCT","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5540334324324221","status":"SUCCESS"}
```
### buy other 2 (same create request id)
```json
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":1000.0,"currencyCode":"JPY"}},"creationRequestId":"PartnerId_62a30923e9705","gcClaimCode":"UM97-FD5QKK-WKCT","gcExpirationDate":"Thu Jun 10 14:59:59 UTC 2032","gcId":"5540334324324221","status":"SUCCESS"}
```
## AWS GCOD Mocks
Mocking on AWS side, these will be returned if given request ID codes are sent.
A working test account must exist for this
## success
### buy gift card F0000
```json
{"cardInfo":{"cardNumber":null,"cardStatus":"Fulfilled","expirationDate":null,"value":{"amount":500.0,"currencyCode":"JPY"}},"creationRequestId":"F0000","gcClaimCode":"ZYXW-VUTS-RQPO","gcExpirationDate":null,"gcId":"ABC123ZYX987","status":"SUCCESS"}
```
## errors
### F1000 -> F100
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F100","errorType":"GeneralError","message":"General Error"}
```
### F2003 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"InvalidAmountInput","message":"Amount can't be null"}
```
### F2004 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"InvalidAmountValue","message":"Amount must be larger than 0"}
```
### F2005 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"InvalidCurrencyCodeInput","message":"Currency Code can't be null or empty"}
```
### F2010 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"CardAlreadyActivatedWithDifferentRequestId","message":"The card was already activated with a different request id"}
```
### F2015 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"MaxAmountExceeded","message":"Max Amount Exceeded"}
```
### F2016 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"CurrencyCodeMismatch","message":"Currency Code Mismatch"}
```
### F2017 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"FractionalAmountNotAllowed","message":"Fractional Amount Not Allowed"}
```
### F2047 -> F200
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F200","errorType":"CancelRequestArrivedAfterTimeLimit","message":"Cancellation cannot be processed as too much time has elapsed since creation"}
```
### F3003 -> F300
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F300","errorType":"InsufficientFunds","message":"Insufficient Funds"}
```
### F3005 -> F300
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F300","errorType":"GeneralError","message":"General Error"}
```
### F3010 -> F300
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F300","errorType":"CustomerSurpassedDailyVelocityLimit","message":"Customer has exceeded daily velocity limit"}
```
### F4000 -> F400
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"RESEND"},"errorCode":"F400","errorType":"SystemTemporarilyUnavailable","message":"System Temporarily Unavailable"}
```
### F5000 -> F500
```json
{"agcodResponse":{"__type":"CreateGiftCardResponse:http://internal.amazon.com/coral/com.amazonaws.agcod/","cardInfo":null,"creationRequestId":null,"gcClaimCode":null,"gcExpirationDate":null,"gcId":null,"status":"FAILURE"},"errorCode":"F500","errorType":"GeneralError","message":"General Error"}
```

View File

@@ -59,6 +59,7 @@ $loader->addPsr4('gullevek\\', __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_
// print "LOADER: <pre>" . print_r($loader, true) . "</pre>";
use gullevek\AmazonIncentives\AmazonIncentives;
use gullevek\AmazonIncentives\Exceptions\AmazonErrors;
use gullevek\dotEnv\DotEnv;
// load env data with dotenv
@@ -75,30 +76,34 @@ print "<h1>Amazon Gift Card Incentives</h1><br>";
// optional
// debug: AWS_DEBUG (if not set: off)
// run info test (prints ENV vars)
$run_info_test = !empty($_GET['info']) ? true : false;
// run test to get funds info
$run_fund_test = !empty($_GET['fund']) ? true : false;
// run the normal get/cancel gift card tests
$run_gift_tests = !empty($_GET['gift']) ? true : false;
// run mock error check tests
$run_mocks = !empty($_GET['mocks']) ? true : false;
// should we print debug info
$debug_print = !empty($_GET['debug']) ? true : false;
// how long to wait between each call
$debug_wait = 2;
// if set to true will print all the debug logs too
$mock_debug = !empty($_GET['debug_mock']) ? true : false;
// wait in seconds between mock tests
$mock_wait = 2;
if (empty($_GET)) {
print "<b>Use _GET parameters to start tests</b>";
}
// open debug file output
$fp = fopen('log/debug.' . date('YmdHis') . '.log', 'w');
if (!is_resource($fp)) {
die("Cannot open log debug file");
}
// run info test (prints ENV vars)
$run_info_test = false;
// run test to get funds info
$run_fund_test = true;
// run the normal get/cancel gift card tests
$run_gift_tests = true;
// run mock error check tests
$run_mocks = true;
// should we print debug info
$debug_print = false;
// how long to wait between each call
$debug_wait = 2;
// if set to true will print all the debug logs too
$mock_debug = false;
// wait in seconds between mock tests
$mock_wait = 2;
if ($run_info_test === true) {
$aws = new AmazonIncentives();
$aws_check_me = $aws->checkMe();
@@ -120,7 +125,7 @@ if ($run_fund_test === true) {
}
fwrite($fp, writeLog((array)$aws_test));
} catch (Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
printException('getAvailableFunds', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error));
};
@@ -152,7 +157,7 @@ if ($run_gift_tests === true) {
}
fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error));
}
@@ -169,7 +174,7 @@ if ($run_gift_tests === true) {
}
fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
print "AWS: cancelGiftCard: " . $error['status']
. " [" . $e->getCode() . "]: "
. $error['code'] . " | " . $error['type']
@@ -197,7 +202,7 @@ if ($run_gift_tests === true) {
}
fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error));
}
@@ -221,7 +226,7 @@ if ($run_gift_tests === true) {
}
fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
printException('cancelGiftCard', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error));
}
@@ -242,7 +247,7 @@ if ($run_gift_tests === true) {
}
fwrite($fp, writeLog((array)$aws_test));
} catch (\Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
printException('buyGiftCard', $e->getCode(), $error, $debug_print);
fwrite($fp, writeLog($error));
}
@@ -295,7 +300,7 @@ if ($run_mocks === true) {
}
fwrite($fp, writeLog((array)$aws_test));
} catch (Exception $e) {
$error = AmazonIncentives::decodeExceptionMessage($e->getMessage());
$error = AmazonErrors::decodeExceptionMessage($e->getMessage());
print "AWS: MOCK: " . $creation_id . ": buyGiftCard: " . $error['status']
. " [" . $e->getCode() . "]: "
. $error['code'] . " | " . $error['type']

View File

@@ -0,0 +1,948 @@
<?php
declare(strict_types=1);
namespace test\phpUnit;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
use gullevek\AmazonIncentives;
use gullevek\dotEnv\DotEnv;
/**
* Test class for ACL\Login
* @coversDefaultClass \gullevek\AmazonIncentives
* @testdox \gullevek\AmazonIncentives full flow test
*/
final class AmazonIncentivesTest extends TestCase
{
/** @var int wait tme in seconds between AWS side mock calls */
private $mock_wait = 1;
/**
* Client curl exception testing
*
* @testdox AWS Incentives curl exception handling
*
* @return void
*/
public function testAwsIncentivesCurlException(): void
{
// this is the exceptio we want
$this->expectException(AmazonIncentives\Exceptions\AmazonErrors::class);
// we don't need a class here, we just need client
$client = new AmazonIncentives\Client\Client();
// produce any error
$client->request('invalid', [], '');
}
/**
* curl/connection error checks
*
* @return array
*/
public function amazonIncentivesProviderErrors(): array
{
// parameter data only for this
// 0: url
// 1: expected status
// 2: expected code
// 3: expected type
return [
// C001
'C002 error' => [
'url' => 'invalid',
'expected_status' => 'FAILURE',
'expected_error' => 'C002',
'expected_type' => 'CurlError'
],
// T001 timeout
// 'T001 error' => [
// 'url' => 'https://timeout.teq.jp',
// 'expected_status' => 'RESEND',
// 'expected_error' => 'T001',
// 'expected_type' => 'RateExceeded'
// ],
// other error
'E999 error' => [
'url' => 'https://www.yahoo.co.jp',
'expected_status' => 'FAILURE',
'expected_error' => 'E999',
'expected_type' => 'OtherUnknownError'
]
];
}
/**
* Test errors thrown in Client class
*
* @dataProvider amazonIncentivesProviderErrors
* @testdox AWS Incentives error handling [$_dataName]
*
* @param string $url
* @return void
*/
public function testAwsIncentivesCurlErrors(
string $url,
string $expected_status,
string $expected_error,
string $expected_type
): void {
// HANDLE:
// * Init error
// - C001/Curl init error
// * Client errors (C002)/false:
// - CURLE_COULDNT_CONNECT
// - CURLE_COULDNT_RESOLVE_HOST
// - CURLE_OPERATION_TIMEOUTED
// - CURLE_SSL_PEER_CERTIFICATE
// - 0/OTHER
// * Client errors other
// - T001/Rate exceeded
// - E999/Other error
// try/catch
// -decodeExceptionMessage (static)
// we don't need the full interface here, we just need client class
$client = new AmazonIncentives\Client\Client();
try {
// set expected throw error
$result = $client->request($url, [], '');
print "R: " . $result . "\n";
} catch (AmazonIncentives\Exceptions\AmazonErrors $e) {
$curl_error = AmazonIncentives\Exceptions\AmazonErrors::decodeExceptionMessage($e->getMessage());
// print "E-B: " . print_r($curl_error, true) . "\n";
$this->assertEquals(
$expected_status,
$curl_error['status'],
'Assert error status'
);
$this->assertEquals(
$expected_error,
$curl_error['code'],
'Assert error code'
);
$this->assertEquals(
$expected_type,
$curl_error['type'],
'Assert error type'
);
}
}
/**
* init amazon incentive interface
*
* @param array $connect
* @param bool $mock
* @param array|null $mock_response
* @return AmazonIncentives\AmazonIncentives
*/
private function awsIncentivesStartUp(
array $connect,
bool $mock,
?array $mock_response,
): AmazonIncentives\AmazonIncentives {
$env_folder = $connect['env_folder'] ?? '';
$env_file = $connect['env_file'] ?? '';
$parameters = $connect['parameters'] ?? [];
// reset _ENV always
$_ENV = [];
// env file read status
$status = null;
if (!empty($env_folder)) {
if (!empty($env_file)) {
$status = DotEnv::readEnvFile($env_folder, $env_file);
} else {
$status = DotEnv::readEnvFile($env_folder);
}
}
// ENV must match _ENV vars if set
if (!empty($env_folder) && $status != 0) {
// abort with error
$this->markTestSkipped(
'Cannot read .env file needed for AWS tests: ' . $status
);
}
// MOCK:
// - for all buyGiftCard|cancelGiftCard|getAvailableFunds
// WHAT:
// \AWS->getCode|cancelCode|getBalance
// -> \AWS->makeReqeust
// -> NEW Client->request <= MOCK this
// NOT MOCK:
// any error calls in Client->request or exceptions
if ($mock === true) {
// create a new config with or without parameters
$agcod_config = new AmazonIncentives\Config\Config(
$parameters['key'] ?? null,
$parameters['secret'] ?? null,
$parameters['partner'] ?? null,
$parameters['endpoint'] ?? null,
$parameters['currency'] ?? null,
$parameters['debug'] ?? null
);
// MOCK CLIENT
// Master mock the Client class for request call
// If we wan't to get errors thrown
/** @var AmazonIncentives\Client\Client&MockObject */
$client_mock = $this->createPartialMock(AmazonIncentives\Client\Client::class, ['request']);
// set the needed return here
$client_mock->method('request')->willReturn(json_encode($mock_response));
// MOCK AWS and attache above class in client return
/** @var AmazonIncentives\AWS\AWS&MockObject */
$aws_mock = $this->getMockBuilder(AmazonIncentives\AWS\AWS::class)
->setConstructorArgs([$agcod_config])
->onlyMethods(['newClient'])
->getMock();
// attach mocked client
$aws_mock->method('newClient')->willReturn($client_mock);
// MOCK AMAZONINCENTIVES
/** @var AmazonIncentives\AmazonIncentives&MockObject */
$agcod = $this->getMockBuilder(AmazonIncentives\AmazonIncentives::class)
->setConstructorArgs([
$parameters['key'] ?? null,
$parameters['secret'] ?? null,
$parameters['partner'] ?? null,
$parameters['endpoint'] ?? null,
$parameters['currency'] ?? null,
$parameters['debug'] ?? null
])
->onlyMethods(['newAWS'])
->getMock();
// attach mocked AWS class
$agcod->method('newAWS')->willReturn($aws_mock);
} else {
// if we mock, we mock the Client->request
$agcod = new AmazonIncentives\AmazonIncentives(
$parameters['key'] ?? null,
$parameters['secret'] ?? null,
$parameters['partner'] ?? null,
$parameters['endpoint'] ?? null,
$parameters['currency'] ?? null,
$parameters['debug'] ?? null
);
}
return $agcod;
}
/**
* Holds the configs for loading data from .env for parameter
*
* @return array
*/
public function awsIncentivesProvider(): array
{
// 0: .env file folder
// 1: .env file name (if not set use .env)
// 2: parameters that override _ENV variables
return [
// this is with real test account data
'env_test' => [
'env_folder' => __DIR__ . DIRECTORY_SEPARATOR . '..',
'env_file' => null,
'parameters' => null
],
// this is for mocking only
'parameter_dummy' => [
'env_folder' => null,
'env_file' => null,
'parameters' => [
null,
null,
null,
'http://i.dont.exist.at.all',
'JPY'
]
],
];
}
/**
* Undocumented function
*
* @return array
*/
public function amazonIncentivesProviderGetFunds(): array
{
// remove final keyword
// BypassFinals::enable();
// get connectors
$connectors = $this->awsIncentivesProvider();
// 0: connect array (env file, env folder, parameters array)
// 1: mock or normal call
// 2: if mock connect response must be defined here
// 3: exepcted response array
return [
'non mock test data' => [
'connect' => $connectors['env_test'],
'mock' => false,
'mock_response' => null,
'expected' => [
//
]
],
'mock data test' => [
'connect' => $connectors['parameter_dummy'],
'mock' => true,
'mock_response' => [
'availableFunds' => [
'amount' => 0.0,
'currencyCode' => 'JPY',
],
'status' => 'SUCCESS',
'timestamp' => '20220610T085450Z',
],
],
];
}
/**
* Undocumented function
*
* @dataProvider amazonIncentivesProviderGetFunds
* @testdox AWS Incentives get available funds [$_dataName]
*
* @param array $connect
* @param bool $mock
* @param array|null $mock_response
* @return void
*/
public function testAwsIncentivesGetAvailableFunds(
array $connect,
bool $mock,
?array $mock_response
): void {
// load class
$agcod = $this->awsIncentivesStartUp(
$connect,
$mock,
$mock_response,
);
// - getAvailableFunds: get available fund
// - getStatus
// - getAmount
// - getCurrency
// - getTimestamp
$funds = $agcod->getAvailableFunds();
// if not mock do type check
// if mock do matching check from mcok
if ($mock === false) {
$this->assertEquals(
'SUCCESS',
$funds->getStatus(),
'Assert status is success'
);
// numeric number
$this->assertIsNumeric(
$funds->getAmount(),
'Assert amoount is numerc'
);
// USD, JPY, etc
$this->assertIsString(
$funds->getCurrency(),
'Assert currency is string'
);
// 20220610T085450Z
$this->assertMatchesRegularExpression(
"/^\d{8}T\d{6}Z$/",
$funds->getTimestamp(),
'Assert timestamp matches regex'
);
} else {
$this->assertEquals(
$mock_response['status'],
$funds->getStatus(),
'Assert mock status'
);
$this->assertEquals(
$mock_response['availableFunds']['amount'],
$funds->getAmount(),
'Assert mock amount'
);
$this->assertEquals(
$mock_response['availableFunds']['currencyCode'],
$funds->getCurrency(),
'Assert mock currency code'
);
$this->assertEquals(
$mock_response['timestamp'],
$funds->getTimestamp(),
'Assert mock timestamp'
);
}
}
/**
* Undocumented function
*
* @return array
*/
public function amazonIncentivesProviderBuy(): array
{
// get connectors
$connectors = $this->awsIncentivesProvider();
// 0: connect array (env file, env folder, parameters array)
// 1: mock or normal call
// 2: if mock connect response must be defined here
// 3: exepcted response array
// 4: value in float
return [
'non mock test data' => [
'connect' => $connectors['env_test'],
'mock' => false,
'mock_response' => null,
'amount' => 500.0,
],
'mock data test' => [
'connect' => $connectors['parameter_dummy'],
'mock' => true,
'mock_response' => [
'cardInfo' => [
'cardNumber' => null,
'cardStatus' => 'Fulfilled',
'expirationDate' => null,
'value' => [
'amount' => 1000.0,
'currencyCode' => 'JPY',
],
],
'creationRequestId' => 'PartnerId_62a309167e7a4',
'gcClaimCode' => 'LJ49-AKDUV6-UYCP',
'gcExpirationDate' => 'Thu Jun 10 14:59:59 UTC 2032',
'gcId' => '5535125272070255',
'status' => 'SUCCESS',
],
'amount' => 1000.0,
],
];
}
/**
* Undocumented function
*
* @dataProvider amazonIncentivesProviderBuy
* @testdox AWS Incentives buy gift card [$_dataName]
*
* @param array $connect
* @param bool $mock
* @param array|null $mock_response
* @param float $amount
* @return void
*/
public function testAwsIncentivesBuyGiftCard(
array $connect,
bool $mock,
?array $mock_response,
float $amount
): void {
// - init plain
// * via ::make()
// - buyGiftCard: buy gift card
// - getCreationRequestId
// - getId
// - getClaimCode
// - getExpirationDate
// - getStatus
// load class
$agcod = $this->awsIncentivesStartUp(
$connect,
$mock,
$mock_response,
);
$response = $agcod->buyGiftCard($amount);
if ($mock === false) {
// type check
$this->assertEquals(
'SUCCESS',
$response->getStatus(),
'Assert status'
);
// creation request id must start with partner id
$this->assertStringStartsWith(
$agcod->checkMe()['CONFIG']->getPartner(),
$response->getCreationRequestId(),
'Assert creation request id starts with partner id'
);
// gift card id is number
$this->assertIsNumeric(
$response->getId(),
'Assert gift card id is numeric'
);
// claim code is 4-6-4 alphanumeric
$this->assertIsString(
$response->getClaimCode(),
'Assert claim code is string'
);
// only for requests outside US/Australia cards
// expiration date: Thu Jun 10 14:59:59 UTC 2032
} else {
// value match to mock response
$this->assertEquals(
$mock_response['status'],
$response->getStatus(),
'Assert mock status'
);
$this->assertEquals(
$mock_response['creationRequestId'],
$response->getCreationRequestId(),
'Assert mock creation request id'
);
$this->assertEquals(
$mock_response['gcId'],
$response->getId(),
'Assert mock gift card id'
);
$this->assertEquals(
$mock_response['gcClaimCode'],
$response->getClaimCode(),
'Assert mock claim code'
);
$this->assertEquals(
$mock_response['gcExpirationDate'],
$response->getExpirationDate(),
'Assert mock expiration date'
);
}
}
/**
* Buy a gift card and use same creation request id to get another gift card
* has to return same data ggain
*
* @dataProvider amazonIncentivesProviderBuy
* @testdox AWS Incentives buy gift card and again with same creation request id [$_dataName]
*
* @param array $connect
* @param bool $mock
* @param array|null $mock_response
* @param float $amount
* @return void
*/
public function testAwsIncentivesSameBuyGiftCard(
array $connect,
bool $mock,
?array $mock_response,
float $amount
): void {
// load class
$agcod = $this->awsIncentivesStartUp(
$connect,
$mock,
$mock_response,
);
// get one
$response_a = $agcod->buyGiftCard($amount);
// get one again with same code
$response_b = $agcod->buyGiftCard($amount, $response_a->getCreationRequestId());
// a and b must be equalt
$this->assertEquals(
$response_a->getStatus(),
$response_b->getStatus(),
'Assert status'
);
$this->assertEquals(
$response_a->getCreationRequestId(),
$response_b->getCreationRequestId(),
'Assert creation request id'
);
$this->assertEquals(
$response_a->getId(),
$response_b->getId(),
'Assert gift card id'
);
$this->assertEquals(
$response_a->getClaimCode(),
$response_b->getClaimCode(),
'Assert claim code'
);
$this->assertEquals(
$response_a->getExpirationDate(),
$response_b->getExpirationDate(),
'Assert expiration date'
);
}
/**
* Undocumented function
*
* @return array
*/
public function amazonIncentivesProviderCancel(): array
{
// get connectors
$connectors = $this->awsIncentivesProvider();
// 0: connect array (env file, env folder, parameters array)
// 1: mock or normal call
// 2: if mock connect response must be defined here
// 3: exepcted response array
return [
'non mock test data' => [
'connect' => $connectors['env_test'],
'mock' => false,
'mock_response' => null,
],
'mock data test' => [
'connect' => $connectors['parameter_dummy'],
'mock' => true,
'mock_response' => [
'creationRequestId' => 'PartnerId_62a309167e7a4',
'gcId' => '5535125272070255',
'status' => 'SUCCESS',
],
],
];
}
/**
* Undocumented function
*
* @dataProvider amazonIncentivesProviderCancel
* @testdox AWS Incentives cancel gift card [$_dataName]
*
* @param array $connect
* @param bool $mock
* @param array|null $mock_response
* @return void
*/
public function testAwsIncentivesCancelGiftCard(
array $connect,
bool $mock,
?array $mock_response
): void {
// - cancelGiftCard: cancel gift card
// load class
$agcod = $this->awsIncentivesStartUp(
$connect,
$mock,
$mock_response,
);
if ($mock === false) {
// get a gift card, then cancel it
$purchase = $agcod->buyGiftCard(500.0);
$response = $agcod->cancelGiftCard(
$purchase->getCreationRequestId(),
$purchase->getId()
);
$this->assertEquals(
'SUCCESS',
$response->getStatus(),
'Assert mock status'
);
// creation request id must start with partner id
$this->assertStringStartsWith(
$agcod->checkMe()['CONFIG']->getPartner(),
$response->getCreationRequestId(),
'Assert creation request id starts with partner id'
);
// gift card id is number
$this->assertIsNumeric(
$response->getId(),
'Assert gift card id is numeric'
);
} else {
$response = $agcod->cancelGiftCard(
$mock_response['creationRequestId'],
$mock_response['gcId']
);
$this->assertEquals(
$mock_response['status'],
$response->getStatus(),
'Assert mock status'
);
$this->assertEquals(
$mock_response['creationRequestId'],
$response->getCreationRequestId(),
'Assert mock creation request id'
);
$this->assertEquals(
$mock_response['gcId'],
$response->getId(),
'Assert mock gift card id'
);
}
}
/**
* list of AWS mock codes for AWS side mock testing
*
* @return array
*/
public function awsIncentivesMockProvider(): array
{
return [
'successMock' => [
'creation_request_id' => 'F0000',
'return_code' => '',
'status' => 'SUCCESS'
],
'SimpleAmountIsNull' => [
'creation_request_id' => 'F1000',
'return_code' => 'F100',
'status' => 'FAILURE'
],
'InvalidAmountInput' => [
'creation_request_id' => 'F2003',
'return_code' => 'F200',
'status' => 'FAILURE'
],
'InvalidAmountValue' => [
'creation_request_id' => 'F2004',
'return_code' => 'F200',
'status' => 'FAILURE'
],
'InvalidCurrencyCodeInput' => [
'creation_request_id' => 'F2005',
'return_code' => 'F200',
'status' => 'FAILURE'
],
'CardActivatedWithDifferentRequestId' => [
'creation_request_id' => 'F2010',
'return_code' => 'F200',
'status' => 'FAILURE'
],
'MaxAmountExceeded' => [
'creation_request_id' => 'F2015',
'return_code' => 'F200',
'status' => 'FAILURE'
],
'CurrencyCodeMismatch' => [
'creation_request_id' => 'F2016',
'return_code' => 'F200',
'status' => 'FAILURE'
],
'FractionalAmountNotAllowed' => [
'creation_request_id' => 'F2017',
'return_code' => 'F200',
'status' => 'FAILURE'
],
'CancelRequestArrivedAfterTimeLimit' => [
'creation_request_id' => 'F2047',
'return_code' => 'F200',
'status' => 'FAILURE'
],
'InsufficientFunds' => [
'creation_request_id' => 'F3003',
'return_code' => 'F300',
'status' => 'FAILURE'
],
'AccountHasProblems' => [
'creation_request_id' => 'F3005',
'return_code' => 'F300',
'status' => 'FAILURE'
],
'CustomerSurpassedDailyVelocityLimit' => [
'creation_request_id' => 'F3010',
'return_code' => 'F300',
'status' => 'FAILURE'
],
'SystemTemporarilyUnavailable' => [
'creation_request_id' => 'F4000',
'return_code' => 'F400',
'status' => 'RESEND'
],
'UnknownError' => [
'creation_request_id' => 'F5000',
'return_code' => 'F500',
'status' => 'FAILURE'
],
];
}
/**
* NOTE: Must have a valid test user connection setup
* This only works with a valid server connection.
* Runs through AWS Incentives mock values and checks the return code and status
*
* @dataProvider awsIncentivesMockProvider
* @testdox AWS Incentives Mock $creation_request_id will be $expected_status with $expected_code [$_dataName]
*
* @return void
*/
public function testAwsIncentivesWithMocks(
string $creation_request_id,
string $expected_code,
string $expected_status,
): void {
// reset _ENV for reading
$_ENV = [];
// read the .env file
$status = DotEnv::readEnvFile(__DIR__ . DIRECTORY_SEPARATOR . '..');
// if loading failed, abort
if ($status != 0) {
// abort with error
$this->markTestSkipped(
'Cannot read .env file needed for AWS mock tests: ' . $status
);
}
// if no value set, set to 500
$value = $_ENV['AWS_MOCK_VALUE'] ?? 500;
// run tests
try {
$aws_gcod = AmazonIncentives\AmazonIncentives::make()->buyGiftCard(
(float)$value,
$creation_request_id
);
$this->assertEquals(
$expected_status,
$aws_gcod->getStatus(),
'Assert status ok in AWS GCOD mocks'
);
} catch (\Exception $e) {
$error = AmazonIncentives\Exceptions\AmazonErrors::decodeExceptionMessage($e->getMessage());
$this->assertEquals(
[
'code' => $expected_code,
'status' => $expected_status,
],
[
'code' => $error['code'],
'status' => $error['status'],
],
'Assert status failed in AWS GCOD mocks'
);
}
// wait a moment between tests
sleep($this->mock_wait);
}
/**
* Undocumented function
*
* @return array
*/
public function checkMeProvider(): array
{
// 0: .env file folder
// 1: .env file name (if not set use .env)
// 2: parameters that override _ENV variables
return [
'default all empty' => [
'use_env' => null,
'env_file' => null,
'parameters' => null,
],
'set parameters' => [
'env_folder' => null,
'env_file' => null,
'parameters' => [
'key' => 'key',
'secret' => 'secret',
'partner' => 'partner id',
'endpoint' => 'https://endpoint.test.com',
'currency' => 'currency',
'debug' => true,
],
'expected' => [],
],
'load from env' => [
'env_folder' => __DIR__ . DIRECTORY_SEPARATOR . '..',
'env_file' => null,
'parameters' => null,
],
'load from env, but override parameter' => [
'env_folder' => __DIR__ . DIRECTORY_SEPARATOR . '..',
'env_file' => null,
'parameters' => [
'key' => 'key',
'secret' => 'secret',
'partner' => 'partner id',
'endpoint' => 'https://endpoint.test.com',
'currency' => 'currency',
]
]
// test missing parameter, set vie _ENV
];
}
/**
* Check the checkMe function that will work with or without any settings
* passed on.
* This also tests basic loading
* - parseing for endoint as url
* - override check for _ENV vs parameter
*
* @cover ::checkMe
* @dataProvider checkMeProvider
* @testdox AmazonIncentives tests [$_dataName]
*
* @param string|null $env_folder
* @param string|null $env_file
* @param array|null $parameters
* @return void
*/
public function testCheckMe(?string $env_folder, ?string $env_file, ?array $parameters): void
{
// reset _ENV before each run to avoid nothing to load errors
$_ENV = [];
// env load status
$status = null;
if (!empty($env_folder)) {
if (!empty($env_file)) {
$status = DotEnv::readEnvFile($env_folder, $env_file);
} else {
$status = DotEnv::readEnvFile($env_folder);
}
}
if (!empty($parameters)) {
$aws = new AmazonIncentives\AmazonIncentives(
$parameters['key'],
$parameters['secret'],
$parameters['partner'],
$parameters['endpoint'],
$parameters['currency'],
$parameters['debug'] ?? null,
);
} else {
$aws = new AmazonIncentives\AmazonIncentives();
}
$aws_check_me = $aws->checkMe();
// ENV must match _ENV vars if set
if (!empty($env_folder) && $status != 0) {
// abort with error
$this->markTestSkipped(
'Cannot read .env file needed: ' . $status
);
} elseif (!empty($env_folder)) {
$this->assertEquals(
$_ENV,
$aws_check_me['ENV'],
'Assert _ENV set equal'
);
}
// compare that data matches
// print "CM: " . print_r($aws_check_me, true) . "\n";
// CONFIG must match to parameters or ENV, parsed host name check
$this->assertEquals(
// parameter > _ENV -> empty
!empty($parameters['partner']) ?
$parameters['partner'] :
$_ENV['AWS_GIFT_CARD_PARTNER_ID'] ?? '',
$aws_check_me['CONFIG']->getPartner(),
'Assert config matching input'
);
// KEY must match access_key/AWS_GIFT_CARD_KEY
$this->assertEquals(
$aws_check_me['CONFIG']->getAccessKey(),
$aws_check_me['KEY'],
'Assert access key m'
);
}
}
// __END__

View File

@@ -0,0 +1,21 @@
<?php
// strip the final name from a to be mocked class
declare(strict_types=1);
namespace test\phpUnit\Hook;
use DG\BypassFinals;
use PHPUnit\Runner\BeforeFirstTestHook;
// only works if it is the FIRST load and not before EACH test
final class BypassFinalHook implements BeforeFirstTestHook
{
public function executeBeforeFirstTest(): void
{
BypassFinals::enable();
}
}
// __END__