Skip to content

Commit

Permalink
Merge pull request #20 from pimlie/master
Browse files Browse the repository at this point in the history
Added tests, removed html output when in console, added env variables for configuration and refactored library code
Silentscripter authored Mar 13, 2018
2 parents 1da89ba + ccf3747 commit 6be8846
Showing 15 changed files with 709 additions and 317 deletions.
16 changes: 14 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -13,6 +13,11 @@
"Protechstudio\\PrestashopWebService\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Protechstudio\\PrestashopWebService\\Tests\\": "tests/"
}
},
"extra": {
"laravel": {
"providers": [
@@ -22,6 +27,13 @@
"Prestashop": "Protechstudio\\PrestashopWebService\\PrestashopWebServiceFacade"
}
}
}

},
"require-dev": {
"squizlabs/php_codesniffer": "^3.2",
"Orchestra/Testbench": "^3.5"
},
"scripts": {
"test": "vendor/bin/phpunit",
"cs": "vendor/bin/phpcs src/*"
}
}
11 changes: 11 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<ruleset name="LaravelPrestashopWebservice">

<description>A basic coding standard.</description>

<exclude-pattern>vendor/*</exclude-pattern>

<rule ref="PSR1" />
<rule ref="PSR2" />

</ruleset>
5 changes: 4 additions & 1 deletion phpunit.xml → phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="../../../bootstrap/autoload.php"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
@@ -18,6 +18,9 @@
<whitelist>
<directory suffix=".php">app/</directory>
</whitelist>
<blacklist>
<directory suffix=".php">./vendor</directory>
</blacklist>
</filter>
<php>
<env name="APP_ENV" value="testing"/>
10 changes: 10 additions & 0 deletions src/Exceptions/PrestashopWebServiceException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Protechstudio\PrestashopWebService\Exceptions;

use Protechstudio\PrestashopWebService\PrestaShopWebserviceException as PSWException;

class PrestashopWebServiceException extends PSWException
{

}
27 changes: 27 additions & 0 deletions src/Exceptions/PrestashopWebServiceRequestException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Protechstudio\PrestashopWebService\Exceptions;

class PrestashopWebServiceRequestException extends PrestashopWebServiceException
{
static protected $label = 'This call to PrestaShop Web Services failed and returned an HTTP status of %d. That means: %s.';

protected $response;

public function __construct($message = null, $code = null, $response = null)
{
parent::__construct(sprintf(static::$label, $code, $message), $code);

$this->response = $response;
}

public function hasResponse()
{
return isset($this->response) && !empty($this->response);
}

public function getResponse()
{
return $this->response;
}
}
2 changes: 1 addition & 1 deletion src/PrestaShopWebserviceException.php
Original file line number Diff line number Diff line change
@@ -5,4 +5,4 @@
class PrestaShopWebserviceException extends \Exception
{

}
}
48 changes: 25 additions & 23 deletions src/PrestashopWebService.php
Original file line number Diff line number Diff line change
@@ -15,31 +15,36 @@ class PrestashopWebService extends PrestashopWebServiceLibrary
* @return SimpleXMLElement
* @throws PrestaShopWebserviceException
*/
public function getSchema($resource , $schema = 'blank')
public function getSchema($resource, $schema = 'blank')
{
return $this->get(['resource' => $resource . "?schema=$schema"]);
}

/**
* Fill the provided schema with an associative array data, also remove the useless XML nodes if the corresponding flag is true
* Fill the provided schema with an associative array data, also remove the useless XML nodes if
* the corresponding flag is true
*
* @param SimpleXMLElement $xmlSchema
* @param array $data
* @param bool $removeUselessNodes set true if you want to remove nodes that are not present in the data array
* @param array $removeSpecificNodes If $removeUselessNodes is false you may add here the first level nodes that you want to remove
* @param array $removeSpecificNodes If $removeUselessNodes is false you may add here the first level nodes that
* you want to remove
* @return SimpleXMLElement
*/
public function fillSchema(SimpleXMLElement $xmlSchema, $data, $removeUselessNodes = true, $removeSpecificNodes=array())
{
public function fillSchema(
SimpleXMLElement $xmlSchema,
$data,
$removeUselessNodes = true,
$removeSpecificNodes = array()
) {
$resource = $xmlSchema->children()->children();
foreach ($data as $key => $value) {
$this->processNode($resource, $key, $value);
}
if ($removeUselessNodes) {
$this->checkForUselessNodes($resource, $data);
}
else{
$this->removeSpecificNodes($resource,$removeSpecificNodes);
} else {
$this->removeSpecificNodes($resource, $removeSpecificNodes);
}
return $xmlSchema;
}
@@ -80,13 +85,12 @@ private function fillLanguageNode($node, $data)
*/
private function processNode(SimpleXMLElement $node, $dataKey, $dataValue)
{
if(is_int($dataKey)){
if($dataKey===0){
if (is_int($dataKey)) {
if ($dataKey===0) {
$this->emptyNode($node);
}
$this->createNode($node,$dataValue);
}
elseif (property_exists($node->$dataKey, 'language')) {
$this->createNode($node, $dataValue);
} elseif (property_exists($node->$dataKey, 'language')) {
$this->fillLanguageNode($node->$dataKey, $dataValue);
} elseif (is_array($dataValue)) {
foreach ($dataValue as $key => $value) {
@@ -134,17 +138,15 @@ private function removeSpecificNodes($resource, $removeSpecificNodes)
private function createNode(SimpleXMLElement $node, $dataValue)
{
foreach ($dataValue as $key => $value) {
if(is_array($value)){
if(is_int($key)){
$this->createNode($node,$value);
}
else{
if (is_array($value)) {
if (is_int($key)) {
$this->createNode($node, $value);
} else {
$childNode=$node->addChild($key);
$this->createNode($childNode,$value);
$this->createNode($childNode, $value);
}
}
else{
$node->addChild($key,$value);
} else {
$node->addChild($key, $value);
}
}
}
@@ -162,4 +164,4 @@ private function emptyNode(SimpleXMLElement $node)
unset($node->$nodeName);
}
}
}
}
4 changes: 1 addition & 3 deletions src/PrestashopWebServiceFacade.php
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@

namespace Protechstudio\PrestashopWebService;


use Illuminate\Support\Facades\Facade;

class PrestashopWebServiceFacade extends Facade
@@ -12,5 +11,4 @@ protected static function getFacadeAccessor()
{
return PrestashopWebService::class;
}

}
}
643 changes: 371 additions & 272 deletions src/PrestashopWebServiceLibrary.php

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions src/PrestashopWebServiceProvider.php
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@

use Illuminate\Support\ServiceProvider;


class PrestashopWebServiceProvider extends ServiceProvider
{

@@ -30,8 +29,11 @@ public function register()
$this->registerConfig();

$this->app->singleton(PrestashopWebService::class, function () {
return new PrestashopWebService(config('prestashop-webservice.url'),
config('prestashop-webservice.token'), config('prestashop-webservice.debug'));
return new PrestashopWebService(
config('prestashop-webservice.url'),
config('prestashop-webservice.token'),
config('prestashop-webservice.debug')
);
});
}

@@ -45,7 +47,6 @@ private function publish()
$this->publishes([
__DIR__ . '/config.php' => config_path('prestashop-webservice.php'),
], 'config');

}

private function registerConfig()
8 changes: 4 additions & 4 deletions src/config.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

return [
'url' => 'http://domain.com',
'token' => '',
'debug' => env('APP_DEBUG', false)
];
'url' => env('PRESTASHOP_URL', 'http://domain.com'),
'token' => env('PRESTASHOP_TOKEN', ''),
'debug' => env('PRESTASHOP_DEBUG', env('APP_DEBUG', false))
];
145 changes: 138 additions & 7 deletions tests/PrestashopWebServiceTest.php
Original file line number Diff line number Diff line change
@@ -1,18 +1,149 @@
<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
namespace Protechstudio\PrestashopWebService\Tests;

use Protechstudio\PrestashopWebService\PrestashopWebService;
use Protechstudio\PrestashopWebService\Exceptions\PrestashopWebServiceException;
use Protechstudio\PrestashopWebService\Exceptions\PrestashopWebServiceRequestException;
use Protechstudio\PrestashopWebService\PrestashopWebServiceLibrary;
use Prestashop;

class PrestashopWebServiceTest extends TestCase
{

/**
* @test
*/
/** @test */
public function it_is_correctly_installed()
{
$this->assertInstanceOf(PrestashopWebService::class, Prestashop::getFacadeRoot());
}

/** @test */
public function test_request_is_correct()
{
$requestResponseStub = require(__DIR__.'/requests/category-schema.php');

list($header, $body) = explode("\n\n", $requestResponseStub[0], 2);
$header_size = strlen($header) + 2;

$this->assertEquals($header_size, $requestResponseStub[1]['header_size']);
}

/** @test */
public function it_can_perform_a_get_request()
{
$requestResponseStub = require(__DIR__.'/requests/category-schema.php');
$ps = $this->getMockedLibrary('executeCurl', $requestResponseStub);

$xml = $ps->get(['resource' => 'categories']);

$this->assertEquals('prestashop', $xml->getName());
$this->assertEquals('category', $xml->children()[0]->getName());
}

/** @test */
public function it_throws_exception_on_404()
{
$ps = $this->getMockedLibrary('executeRequest', [
'status_code' => 404,
'response' => '<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<errors>
<error>
<code><![CDATA[1]]></code>
<message><![CDATA[Invalid ID]]></message>
</error>
</errors>
</prestashop>',
'header' => ''
]);

try {
$xml = $ps->get(['resource' => 'categories']);
} catch (PrestashopWebServiceRequestException $exception) {
$this->assertEquals(404, $exception->getCode());
$this->assertTrue($exception->hasResponse());
$this->assertEquals('Invalid ID', (string)$exception->getResponse()->errors->error->message);
}
}

/** @test */
public function it_throws_exception_on_unknown_http_status()
{
$ps = $this->getMockedLibrary('executeRequest', [
'status_code' => 999,
'response' => '<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
</prestashop>',
'header' => ''
]);

$this->expectExceptionMessage('unexpected HTTP status of: 999', PrestashopWebServiceException::class);
$xml = $ps->get(['resource' => 'categories']);
}

/** @test */
public function it_throws_exception_on_empty_response()
{
$ps = $this->getMockedLibrary('executeRequest', [
'status_code' => 200,
'response' => '',
'header' => ''
]);

$this->expectExceptionMessage('HTTP response is empty', PrestashopWebServiceException::class);
$xml = $ps->get(['resource' => 'categories']);
}

/** @test */
public function it_throws_exception_on_malformed_xml()
{
$ps = $this->getMockedLibrary('executeRequest', [
'status_code' => 200,
'response' => '<malformed>',
'header' => ''
]);

$this->expectExceptionMessage('HTTP XML response is not parsable', PrestashopWebServiceException::class);
$xml = $ps->get(['resource' => 'categories']);
}

/** @test */
public function it_throws_exception_on_unsupported_version()
{
$this->expectExceptionMessage('This library is not compatible with this version of PrestaShop', PrestashopWebServiceException::class);
Prestashop::isPrestashopVersionSupported('0.0.0.0');
Prestashop::isPrestashopVersionSupported('99.99.99.9999');
}

/** @test */
public function it_throws_exception_on_unsupported_version_from_request()
{
$requestResponseStub = require(__DIR__.'/requests/category-schema.php');
$requestResponseStub[0] = preg_replace('/^PSWS-Version:(.+?)$/im', 'PSWS-Version: 99.99.99.9999', $requestResponseStub[0]);
$ps = $this->getMockedLibrary('executeCurl', $requestResponseStub);

$this->expectExceptionMessage('This library is not compatible with this version of PrestaShop', PrestashopWebServiceException::class);
$xml = $ps->get(['resource' => 'categories']);
}

protected function getMockedLibrary($method = null, $returns = null)
{
$ps = $this->getMockBuilder(PrestashopWebServiceLibrary::class)
->setConstructorArgs([
env('prestashop-webservice.url'),
env('prestashop-webservice.key'),
env('prestashop-webservice.debug'),
]);

if (!$method) {
return $ps->getMock();
} else {
$ps = $ps->setMethods([$method])->getMock();

$ps->expects($this->once())
->method($method)
->willReturn($returns);
return $ps;
}
}
}

37 changes: 37 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Protechstudio\PrestashopWebService\Tests;

abstract class TestCase extends \Orchestra\Testbench\TestCase
{
/**
* Get package providers.
*
* @param \Illuminate\Foundation\Application $app
* @return array
*/
protected function getPackageProviders($app)
{
return [
\Protechstudio\PrestashopWebService\PrestashopWebServiceProvider::class,
];
}
/**
* Define environment setup.
*
* @param Illuminate\Foundation\Application $app
* @return void
*/
protected function getEnvironmentSetUp($app)
{
$app['config']->set('app.debug', true);
$app['config']->set('prestashop-webservice', require('config/prestashop-webservice.php'));
}

protected function getPackageAliases($app)
{
return [
'Prestashop' => \Protechstudio\PrestashopWebService\PrestashopWebServiceFacade::class,
];
}
}
7 changes: 7 additions & 0 deletions tests/config/prestashop-webservice.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

return [
'url' => 'http://example.com',
'token' => '1234',
'debug' => true
];
54 changes: 54 additions & 0 deletions tests/requests/category-schema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

return [
'HTTP/1.1 200 OK
Server: nginx
Date: Fri, 26 Jan 2018 20:38:53 GMT
Content-Type: text/xml;charset=utf-8
Content-Length: 825
Connection: keep-alive
Vary: Accept-Encoding
Access-Time: 1516999133
X-Powered-By: PrestaShop Webservice
PSWS-Version: 1.7.2.4
Execution-Time: 0.006
Content-Sha1: 1234
Set-Cookie: PrestaShop-1234; expires=Thu, 15-Feb-2018 20:38:53 GMT; Max-Age=1728000; path=/; domain=example.com; HttpOnly
Vary: Accept-Encoding
<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<category>
<id></id>
<id_parent></id_parent>
<active></active>
<id_shop_default></id_shop_default>
<is_root_category></is_root_category>
<position></position>
<date_add></date_add>
<date_upd></date_upd>
<name><language id="1"></language></name>
<link_rewrite><language id="1"></language></link_rewrite>
<description><language id="1"></language></description>
<meta_title><language id="1"></language></meta_title>
<meta_description><language id="1"></language></meta_description>
<meta_keywords><language id="1"></language></meta_keywords>
<associations>
<categories>
<category>
<id></id>
</category>
</categories>
<products>
<product>
<id></id>
</product>
</products>
</associations>
</category>
</prestashop>',

json_decode('{"url":"http:\/\/example.com\/api\/categories?schema=blank","content_type":"text\/xml;charset=utf-8","http_code":200,"header_size":436,"request_size":155,"filetime":-1,"ssl_verify_result":0,"redirect_count":0,"total_time":0.149629,"namelookup_time":0.004162,"connect_time":0.025428,"pretransfer_time":0.025453,"size_upload":0,"size_download":825,"speed_download":5513,"speed_upload":0,"download_content_length":825,"upload_content_length":-1,"starttransfer_time":0.149337,"redirect_time":0,"redirect_url":"","primary_ip":"1.2.3.4","certinfo":[],"primary_port":80,"local_ip":"192.168.1.1","local_port":56568,"request_header":"GET \/api\/categories?schema=blank HTTP\/1.1\r\nHost: example.com\r\nAuthorization: Basic XXX\r\nAccept: *\/*\r\n\r\n"}', true),

false
];

0 comments on commit 6be8846

Please sign in to comment.