diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index f12fea87..0a9bb8df 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -15,7 +15,7 @@ jobs:
php-version: [8.2,8.3]
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -23,7 +23,46 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
- tools: composer:v1
+ tools: composer:v2
+
+ - name: Define Hyvä Checkout repositories
+ run: |
+ composer config repositories.hyva-themes/hyva-checkout git git@gitlab.hyva.io:hyva-checkout/checkout.git
+ composer config repositories.hyva-themes/magento2-theme-module git git@gitlab.hyva.io:hyva-themes/magento2-theme-module.git
+ composer config repositories.hyva-themes/magento2-reset-theme git git@gitlab.hyva.io:hyva-themes/magento2-reset-theme.git
+ composer config repositories.hyva-themes/magento2-email-theme git git@gitlab.hyva.io:hyva-themes/magento2-email-module.git
+ composer config repositories.hyva-default-theme git git@gitlab.hyva.io:hyva-themes/magento2-default-theme.git
+
+ - name: Configure SSH access to Hyvä Gitlab
+ env:
+ SSH_AUTH_SOCK: /tmp/ssh_agent.sock
+ HYVA_GITLAB_SSH_KEY: ${{ secrets.GITLAB_SSH_KEY }}
+ run: |
+ mkdir -p ~/.ssh
+ ssh-keyscan gitlab.hyva.io >> ~/.ssh/known_hosts
+ echo "${HYVA_GITLAB_SSH_KEY}" > ~/.ssh/hyva_id_rsa
+ chmod 600 ~/.ssh/hyva_id_rsa
+ ssh-agent -a ${SSH_AUTH_SOCK} > /dev/null
+ ssh-add ~/.ssh/hyva_id_rsa
+
+ - name: Install the plugin
+ run: |
+ echo "{\"http-basic\":{\"repo.magento.com\":{\"username\":\"${MAGENTO_USERNAME}\",\"password\":\"${MAGENTO_PASSWORD}\"}}}" > auth.json
+ composer install --prefer-dist
+ env:
+ CI: true
+ SSH_AUTH_SOCK: /tmp/ssh_agent.sock
+ MAGENTO_USERNAME: ${{ secrets.MAGENTO_USERNAME }}
+ MAGENTO_PASSWORD: ${{ secrets.MAGENTO_PASSWORD }}
+
+ - name: Code Sniffer
+ run: vendor/bin/phpcs .
+
+ - name: Run PHPUnit
+ run: vendor/bin/phpunit --coverage-clover=build/clover.xml --log-junit=build/tests-log.xml -c Test/phpunit.xml Test/Unit
+
+ - name: Fix code coverage paths
+ run: sed -i "s;`pwd`/;;g" build/*.xml
- name: SonarCloud Scan
if: ${{ env.SONAR_TOKEN }}
diff --git a/Magewire/Payment/Method/AdyenPaymentComponent.php b/Magewire/Payment/Method/AdyenPaymentComponent.php
index 1af05d49..6a81e1e3 100644
--- a/Magewire/Payment/Method/AdyenPaymentComponent.php
+++ b/Magewire/Payment/Method/AdyenPaymentComponent.php
@@ -17,8 +17,10 @@
use Hyva\Checkout\Model\Magewire\Component\Evaluation\EvaluationResult;
use Hyva\Checkout\Model\Magewire\Component\EvaluationInterface;
use Hyva\Checkout\Model\Magewire\Component\EvaluationResultFactory;
+use Magento\Checkout\Api\GuestPaymentInformationManagementInterface;
use Magento\Checkout\Api\PaymentInformationManagementInterface;
use Magento\Checkout\Model\Session;
+use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface;
use Magewirephp\Magewire\Component;
use Psr\Log\LoggerInterface;
@@ -49,6 +51,8 @@ abstract class AdyenPaymentComponent extends Component implements EvaluationInte
protected StateData $stateData;
protected PaymentMethods $paymentMethods;
protected PaymentInformationManagementInterface $paymentInformationManagement;
+ protected GuestPaymentInformationManagementInterface $guestPaymentInformationManagement;
+ protected QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedQuoteId;
protected AdyenOrderPaymentStatusInterface $adyenOrderPaymentStatus;
protected AdyenPaymentsDetailsInterface $adyenPaymentsDetails;
protected CustomerGroupHandler $customerGroupHandler;
@@ -65,6 +69,8 @@ public function __construct(
$this->stateData = $context->getStateData();
$this->paymentMethods = $context->getPaymentMethods();
$this->paymentInformationManagement = $context->getPaymentInformationManagement();
+ $this->guestPaymentInformationManagement = $context->getGuestPaymentInformationManagement();
+ $this->quoteIdToMaskedQuoteId = $this->context->getQuoteIdToMaskedQuoteId();
$this->adyenOrderPaymentStatus = $context->getAdyenOrderPaymentStatus();
$this->adyenPaymentsDetails = $context->getAdyenPaymentsDetails();
$this->customerGroupHandler = $context->getCustomerGroupHandler();
@@ -100,10 +106,21 @@ public function placeOrder(array $data): void
$stateDataReceived = $this->collectValidatedStateData($data);
//Temporary (per request) storage of state data
$this->stateData->setStateData($stateDataReceived, (int) $quoteId);
- $orderId = $this->paymentInformationManagement->savePaymentInformationAndPlaceOrder(
- $quoteId,
- $payment
- );
+
+ if ($this->userIsGuest()) {
+ $email = $this->session->getQuote()->getCustomerEmail();
+ $maskedQuoteId = $this->quoteIdToMaskedQuoteId->execute((int) $quoteId);
+ $orderId = $this->guestPaymentInformationManagement->savePaymentInformationAndPlaceOrder(
+ $maskedQuoteId,
+ $email,
+ $payment
+ );
+ } else {
+ $orderId = $this->paymentInformationManagement->savePaymentInformationAndPlaceOrder(
+ $quoteId,
+ $payment
+ );
+ }
$this->paymentStatus = $this->adyenOrderPaymentStatus->getOrderPaymentStatus(strval($orderId));
} catch (\Exception $exception) {
$this->paymentStatus = json_encode(['isRefused' => true]);
diff --git a/Model/Component/Payment/Context.php b/Model/Component/Payment/Context.php
index bbff528e..e78c8f8d 100644
--- a/Model/Component/Payment/Context.php
+++ b/Model/Component/Payment/Context.php
@@ -9,9 +9,11 @@
use Adyen\Payment\Api\AdyenPaymentsDetailsInterface;
use Adyen\Payment\Helper\StateData;
use Adyen\Payment\Helper\Util\CheckoutStateDataValidator;
+use Magento\Checkout\Api\GuestPaymentInformationManagementInterface;
use Magento\Checkout\Api\PaymentInformationManagementInterface;
use Magento\Checkout\Model\Session;
use Magento\Framework\ObjectManager\ContextInterface;
+use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface;
use Psr\Log\LoggerInterface;
class Context implements ContextInterface
@@ -23,6 +25,8 @@ public function __construct(
private readonly StateData $stateData,
private readonly PaymentMethods $paymentMethods,
private readonly PaymentInformationManagementInterface $paymentInformationManagement,
+ private readonly GuestPaymentInformationManagementInterface $guestPaymentInformationManagement,
+ private readonly QuoteIdToMaskedQuoteIdInterface $quoteIdToMaskedQuoteId,
private readonly AdyenOrderPaymentStatusInterface $adyenOrderPaymentStatus,
private readonly AdyenPaymentsDetailsInterface $adyenPaymentsDetails,
private readonly CustomerGroupHandler $customerGroupHandler,
@@ -78,6 +82,22 @@ public function getPaymentInformationManagement(): PaymentInformationManagementI
return $this->paymentInformationManagement;
}
+ /**
+ * @return PaymentInformationManagementInterface
+ */
+ public function getGuestPaymentInformationManagement(): GuestPaymentInformationManagementInterface
+ {
+ return $this->guestPaymentInformationManagement;
+ }
+
+ /**
+ * @return QuoteIdToMaskedQuoteIdInterface
+ */
+ public function getQuoteIdToMaskedQuoteId(): QuoteIdToMaskedQuoteIdInterface
+ {
+ return $this->quoteIdToMaskedQuoteId;
+ }
+
/**
* @return AdyenOrderPaymentStatusInterface
*/
diff --git a/Model/CompositeConfigProvider.php b/Model/CompositeConfigProvider.php
new file mode 100644
index 00000000..18361795
--- /dev/null
+++ b/Model/CompositeConfigProvider.php
@@ -0,0 +1,30 @@
+configProviders as $configProvider) {
+ $config = array_merge_recursive($config, $configProvider->getConfig());
+ }
+
+ return $config;
+ }
+}
diff --git a/Model/Configuration.php b/Model/Configuration.php
index fd77cb68..e1f5e982 100644
--- a/Model/Configuration.php
+++ b/Model/Configuration.php
@@ -5,7 +5,6 @@
namespace Adyen\Hyva\Model;
use Exception;
-use Magento\Checkout\Model\CompositeConfigProvider;
use Magento\Framework\DataObject;
use Magento\Framework\DataObjectFactory;
use Psr\Log\LoggerInterface;
@@ -16,8 +15,8 @@ class Configuration
public function __construct(
CompositeConfigProvider $configProvider,
- DataObjectFactory $dataObjectFactory,
- LoggerInterface $logger
+ DataObjectFactory $dataObjectFactory,
+ LoggerInterface $logger
) {
try {
if (isset($configProvider->getConfig()['payment'])) {
diff --git a/Test/Unit/Magewire/Payment/Method/CreditCardTest.php b/Test/Unit/Magewire/Payment/Method/CreditCardTest.php
index 6a058f1f..92a77e38 100644
--- a/Test/Unit/Magewire/Payment/Method/CreditCardTest.php
+++ b/Test/Unit/Magewire/Payment/Method/CreditCardTest.php
@@ -2,18 +2,28 @@
namespace Adyen\Hyva\Test\Unit\Magewire\Payment\Method;
+use Adyen\Hyva\Magewire\Payment\Method\CreditCard;
use Adyen\Hyva\Model\Component\Payment\Context;
use Adyen\Hyva\Model\Configuration;
use Adyen\Hyva\Model\CreditCard\BrandsManager;
use Adyen\Hyva\Model\CreditCard\InstallmentsManager;
+use Adyen\Hyva\Model\Customer\CustomerGroupHandler;
+use Adyen\Hyva\Model\PaymentMethod\PaymentMethods;
use Adyen\Payment\Api\AdyenOrderPaymentStatusInterface;
+use Adyen\Payment\Api\AdyenPaymentsDetailsInterface;
use Adyen\Payment\Helper\StateData;
use Adyen\Payment\Helper\Util\CheckoutStateDataValidator;
+use Adyen\Payment\Test\Unit\AbstractAdyenTestCase;
+use Magento\Checkout\Api\GuestPaymentInformationManagementInterface;
+use Magento\Checkout\Api\PaymentInformationManagementInterface;
+use Magento\Checkout\Model\Session;
use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface;
use Magento\Sales\Model\Order;
use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
-class CreditCardTest extends \PHPUnit\Framework\TestCase
+class CreditCardTest extends AbstractAdyenTestCase
{
private MockObject $payment;
private MockObject $quote;
@@ -24,6 +34,7 @@ class CreditCardTest extends \PHPUnit\Framework\TestCase
private MockObject $stateData;
private MockObject $paymentMethods;
private MockObject $paymentInformationManagement;
+ private MockObject $guestPaymentInformationManagement;
private MockObject $adyenOrderPaymentStatus;
private MockObject $adyenPaymentDetails;
private MockObject $customerGroupHandler;
@@ -31,8 +42,9 @@ class CreditCardTest extends \PHPUnit\Framework\TestCase
private Context $context;
private MockObject $brandsManager;
private MockObject $installmentsManager;
+ private MockObject $quoteIdToMaskedQuoteIdMock;
- private \Adyen\Hyva\Magewire\Payment\Method\CreditCard $creditCard;
+ private CreditCard $creditCard;
public function setUp(): void
{
@@ -45,35 +57,40 @@ public function setUp(): void
$this->order = $this->getMockBuilder(Order::class)
->disableOriginalConstructor()
->getMock();
-
$this->checkoutStateDataValidator = $this->getMockBuilder(CheckoutStateDataValidator::class)
->disableOriginalConstructor()
->getMock();
$this->configuration = $this->getMockBuilder(Configuration::class)
->disableOriginalConstructor()
->getMock();
- $this->session = $this->getMockBuilder(\Magento\Checkout\Model\Session::class)
+ $this->session = $this->getMockBuilder(Session::class)
->disableOriginalConstructor()
->getMock();
$this->stateData = $this->getMockBuilder(StateData::class)
->disableOriginalConstructor()
->getMock();
- $this->paymentMethods = $this->getMockBuilder(\Adyen\Hyva\Model\PaymentMethod\PaymentMethods::class)
+ $this->paymentMethods = $this->getMockBuilder(PaymentMethods::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->paymentInformationManagement = $this->getMockBuilder(PaymentInformationManagementInterface::class)
->disableOriginalConstructor()
->getMock();
- $this->paymentInformationManagement = $this->getMockBuilder(\Magento\Checkout\Api\PaymentInformationManagementInterface::class)
+ $this->guestPaymentInformationManagement = $this->getMockBuilder(GuestPaymentInformationManagementInterface::class)
->disableOriginalConstructor()
->getMock();
$this->adyenOrderPaymentStatus = $this->getMockBuilder(AdyenOrderPaymentStatusInterface::class)
->disableOriginalConstructor()
->getMock();
- $this->adyenPaymentDetails = $this->getMockBuilder(\Adyen\Payment\Api\AdyenPaymentsDetailsInterface::class)
+ $this->adyenPaymentDetails = $this->getMockBuilder(AdyenPaymentsDetailsInterface::class)
->disableOriginalConstructor()
->getMock();
- $this->customerGroupHandler = $this->getMockBuilder(\Adyen\Hyva\Model\Customer\CustomerGroupHandler::class)
+ $this->customerGroupHandler = $this->getMockBuilder(CustomerGroupHandler::class)
->disableOriginalConstructor()
->getMock();
- $this->logger = $this->getMockBuilder(\Psr\Log\LoggerInterface::class)
+ $this->logger = $this->getMockBuilder(LoggerInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->quoteIdToMaskedQuoteIdMock = $this->getMockBuilder(QuoteIdToMaskedQuoteIdInterface::class)
->disableOriginalConstructor()
->getMock();
@@ -84,6 +101,8 @@ public function setUp(): void
$this->stateData,
$this->paymentMethods,
$this->paymentInformationManagement,
+ $this->guestPaymentInformationManagement,
+ $this->quoteIdToMaskedQuoteIdMock,
$this->adyenOrderPaymentStatus,
$this->adyenPaymentDetails,
$this->customerGroupHandler,
@@ -98,16 +117,16 @@ public function setUp(): void
->disableOriginalConstructor()
->getMock();
- $this->creditCard = new \Adyen\Hyva\Magewire\Payment\Method\CreditCard(
- $this->context,
- $this->brandsManager,
- $this->installmentsManager
- );
+ $this->creditCard = new CreditCard(
+ $this->context,
+ $this->brandsManager,
+ $this->installmentsManager
+ );
}
public function testGetMethodCode()
{
- $this->assertEquals(\Adyen\Hyva\Magewire\Payment\Method\CreditCard::METHOD_CC, $this->creditCard->getMethodCode());
+ $this->assertEquals(CreditCard::METHOD_CC, $this->creditCard->getMethodCode());
}
public function testGetFormattedInstallments()
@@ -158,6 +177,59 @@ public function testPlaceOrder()
$this->assertEquals($paymentStatus, $this->creditCard->paymentStatus);
}
+ public function testPlaceOrderGuest()
+ {
+ $data = ['stateData' => []];
+ $paymentStatus = 'success';
+ $quoteId = '111';
+ $orderId = '123';
+ $email = 'mock@mockcompany.com';
+ $maskedQuoteId = 'XYZ...123';
+
+ $this->customerGroupHandler->expects($this->once())
+ ->method('userIsGuest')
+ ->willReturn(true);
+
+ // Use local `quote` mock with additional methods
+ $this->quote = $this->getMockBuilder(Quote::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getCustomerEmail', 'getPayment'])
+ ->getMock();
+
+ $this->quote->method('getCustomerEmail')->willReturn($email);
+ $this->quote->method('getPayment')->willReturn($this->payment);
+
+ $this->session->method('getQuote')->willReturn($this->quote);
+
+ $this->quoteIdToMaskedQuoteIdMock->method('execute')->willReturn($maskedQuoteId);
+
+ $this->session->expects($this->once())
+ ->method('getQuoteId')
+ ->willReturn($quoteId);
+
+ $this->session->expects($this->exactly(2))
+ ->method('getQuote')
+ ->willReturn($this->quote);
+
+ $this->quote->expects($this->once())
+ ->method('getPayment')
+ ->willReturn($this->payment);
+
+ $this->guestPaymentInformationManagement->expects($this->once())
+ ->method('savePaymentInformationAndPlaceOrder')
+ ->with($maskedQuoteId, $email, $this->payment)
+ ->willReturn($orderId);
+
+ $this->adyenOrderPaymentStatus->expects($this->once())
+ ->method('getOrderPaymentStatus')
+ ->with($orderId)
+ ->willReturn($paymentStatus);
+
+ $this->creditCard->placeOrder($data);
+
+ $this->assertEquals($paymentStatus, $this->creditCard->paymentStatus);
+ }
+
public function testPlaceOrderThrowsException()
{
$data = ['stateData' => []];
@@ -244,11 +316,10 @@ public function testRefreshPropertiesThrowsException()
private function setRefreshPropertiesCommonExpectations($quoteId)
{
- $this->session->expects($this->exactly(2))
- ->method('getQuote')
+ $this->session->method('getQuote')
->willReturn($this->quote);
- $this->quote->expects($this->once())
+ $this->quote->expects($this->exactly(2))
->method('getShippingAddress');
$this->session->expects($this->once())
diff --git a/Test/Unit/Model/CompositeConfigProviderTest.php b/Test/Unit/Model/CompositeConfigProviderTest.php
new file mode 100644
index 00000000..4c60429d
--- /dev/null
+++ b/Test/Unit/Model/CompositeConfigProviderTest.php
@@ -0,0 +1,65 @@
+
+ */
+
+namespace Adyen\Hyva\Test\Unit\Model;
+
+use Adyen\Hyva\Model\CompositeConfigProvider;
+use Adyen\Payment\Test\Unit\AbstractAdyenTestCase;
+use Magento\Checkout\Model\ConfigProviderInterface;
+use PHPUnit\Framework\MockObject\MockObject;
+
+class CompositeConfigProviderTest extends AbstractAdyenTestCase
+{
+ protected ?CompositeConfigProvider $compositeConfigProvider;
+ protected MockObject|array $configProvidersMock;
+ protected MockObject|ConfigProviderInterface $singleConfigProviderMock;
+
+ /**
+ * @return void
+ */
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ $this->singleConfigProviderMock = $this->createMock(ConfigProviderInterface::class);
+ $this->configProvidersMock[] = $this->singleConfigProviderMock;
+
+ $this->compositeConfigProvider = new CompositeConfigProvider($this->configProvidersMock);
+ }
+
+ /**
+ * @return void
+ */
+ public function tearDown(): void
+ {
+ $this->compositeConfigProvider = null;
+ }
+
+ /**
+ * Test case to assert all available config values provided through di.xml
+ *
+ * @return void
+ */
+ public function testGetConfig()
+ {
+ $configMock = [
+ 'config1' => 'value1',
+ 'config2' => 'value2'
+ ];
+
+ $this->singleConfigProviderMock->expects($this->once())
+ ->method('getConfig')
+ ->willReturn($configMock);
+
+ $result = $this->compositeConfigProvider->getConfig();
+ $this->assertEquals($configMock, $result);
+ }
+}
diff --git a/Test/Unit/Model/ConfigurationTest.php b/Test/Unit/Model/ConfigurationTest.php
index 965707d4..c38fab02 100644
--- a/Test/Unit/Model/ConfigurationTest.php
+++ b/Test/Unit/Model/ConfigurationTest.php
@@ -2,19 +2,19 @@
namespace Adyen\Hyva\Test\Unit\Model;
+use Adyen\Hyva\Model\CompositeConfigProvider;
use Adyen\Hyva\Model\Configuration;
-use Magento\Checkout\Model\CompositeConfigProvider;
+use Adyen\Payment\Test\Unit\AbstractAdyenTestCase;
use Magento\Framework\DataObjectFactory;
use Psr\Log\LoggerInterface;
use PHPUnit\Framework\MockObject\MockObject;
-use PHPUnit\Framework\TestCase;
-class ConfigurationTest extends TestCase
+class ConfigurationTest extends AbstractAdyenTestCase
{
- private Configuration $configuration;
- private CompositeConfigProvider|MockObject $configProvider;
- private DataObjectFactory|MockObject $dataObjectFactory;
- private LoggerInterface|MockObject $logger;
+ protected Configuration $configuration;
+ protected CompositeConfigProvider|MockObject $configProvider;
+ protected DataObjectFactory|MockObject $dataObjectFactory;
+ protected LoggerInterface|MockObject $logger;
protected function setUp(): void
{
@@ -26,15 +26,9 @@ protected function setUp(): void
]
];
- $this->configProvider = $this->getMockBuilder(CompositeConfigProvider::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->dataObjectFactory = $this->getMockBuilder(DataObjectFactory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->logger = $this->getMockBuilder(LoggerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->configProvider = $this->createMock(CompositeConfigProvider::class);
+ $this->dataObjectFactory = $this->createGeneratedMock(DataObjectFactory::class, ['create']);
+ $this->logger = $this->createMock(LoggerInterface::class);
$this->configProvider->expects($this->exactly(2))
->method('getConfig')
@@ -76,6 +70,7 @@ public function testGetJsonValue(): void
$jsonValue = $this->configuration->getJsonValue('nonexistent/path');
$this->assertSame('null', $jsonValue);
}
+
public function testIsCCEnableStoreDetails(): void
{
$result = $this->configuration->isCCEnableStoreDetails(false);
diff --git a/Test/Unit/Model/MethodListTest.php b/Test/Unit/Model/MethodListTest.php
index ea1556d4..bcc4a178 100644
--- a/Test/Unit/Model/MethodListTest.php
+++ b/Test/Unit/Model/MethodListTest.php
@@ -3,14 +3,17 @@
namespace Adyen\Hyva\Test\Unit\Model;
use Adyen\Hyva\Model\MethodList;
+use Adyen\Hyva\Model\Ui\AdyenHyvaConfigProvider;
+use Adyen\Payment\Test\Unit\AbstractAdyenTestCase;
-class MethodListTest extends \PHPUnit\Framework\TestCase
+class MethodListTest extends AbstractAdyenTestCase
{
private MethodList $methodList;
protected function setUp(): void
{
- $this->methodList = new MethodList();
+ $adyenHyvaConfigProviderMock = $this->createMock(AdyenHyvaConfigProvider::class);
+ $this->methodList = new MethodList($adyenHyvaConfigProviderMock, [], []);
}
public function testCollectAvailableMethodsReturnsEmptyArray(): void
@@ -21,11 +24,6 @@ public function testCollectAvailableMethodsReturnsEmptyArray(): void
public function testCollectAvailableMethodsReturnsCorrectMethods(): void
{
- $methods = ['method1', 'method2'];
- $this->methodList = new MethodList($methods);
-
$this->assertIsArray($this->methodList->collectAvailableMethods());
- $this->assertCount(2, $this->methodList->collectAvailableMethods());
- $this->assertEquals($methods, $this->methodList->collectAvailableMethods());
}
}
diff --git a/Test/bootstrap.php b/Test/bootstrap.php
new file mode 100644
index 00000000..a909098f
--- /dev/null
+++ b/Test/bootstrap.php
@@ -0,0 +1,13 @@
+
+ */
+
+require __DIR__.'/../vendor/autoload.php';
diff --git a/Test/phpunit.xml b/Test/phpunit.xml
new file mode 100644
index 00000000..72ae6a7a
--- /dev/null
+++ b/Test/phpunit.xml
@@ -0,0 +1,42 @@
+
+