[kahlan:api/core/Request] tests + fixed Request
This commit is contained in:
parent
7943e57054
commit
8916ced031
|
@ -12,7 +12,7 @@
|
||||||
class Request{
|
class Request{
|
||||||
|
|
||||||
// Constantes
|
// Constantes
|
||||||
private static function config_path(){ return __ROOT__.'/config/modules.json'; }
|
public static function config_path(){ return __ROOT__.'/config/modules.json'; }
|
||||||
private static $default_options = [
|
private static $default_options = [
|
||||||
'download' => false
|
'download' => false
|
||||||
];
|
];
|
||||||
|
@ -40,67 +40,90 @@
|
||||||
* @path<String> Chemin de delegation ("module/methode")
|
* @path<String> Chemin de delegation ("module/methode")
|
||||||
* @param<Array> Tableau associatif contenant les parametres utiles au traitement
|
* @param<Array> Tableau associatif contenant les parametres utiles au traitement
|
||||||
*
|
*
|
||||||
* @return status<Boolean> Retourne si oui ou non tout s'est bien passe
|
* @return instance<Request> Instance crée
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function __construct($path=null, $params=null){
|
public function __construct($path=null, $params=null){
|
||||||
|
|
||||||
|
return $this->buildRequestObject($path, $params);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* CONSTRUCTEUR D'UNE REQUETE DE MODULE (DELEGATION)
|
||||||
|
*
|
||||||
|
* @path<String> Chemin de delegation ("module/methode")
|
||||||
|
* @param<Array> Tableau associatif contenant les parametres utiles au traitement
|
||||||
|
*
|
||||||
|
* @return status<Boolean> Retourne si oui ou non tout s'est bien passe
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function buildRequestObject($path=null, $params=null){
|
||||||
/* [1] Initialisation
|
/* [1] Initialisation
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
/* (1) Erreur par défaut */
|
/* (1) Erreur par défaut */
|
||||||
$this->error = new Error(Err::Success);
|
$this->error = new Error(Err::Success);
|
||||||
|
|
||||||
/* (2) Si pas parametre manquant, on quitte */
|
/* (2) Si pas parametre manquant, on quitte */
|
||||||
if( $path == null ){
|
if( $path == null )
|
||||||
$this->error->set(Err::MissingPath);
|
return $this->error->set(Err::MissingPath);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* [2] On met a jour la configuration
|
/* [2] On met a jour la configuration
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
/* (1) Section Title */
|
/* (1) Vérification existence fichier config */
|
||||||
$this->modules = json_decode( file_get_contents(self::config_path()), true );
|
if( !file_exists(self::config_path()) )
|
||||||
|
return $this->error->set(Err::UnreachableResource);
|
||||||
|
|
||||||
/* (2) Gestion de l'erreur de parsage */
|
/* (2) Lecture fichier config */
|
||||||
if( $this->modules == null ){
|
$conf = @file_get_contents(self::config_path());
|
||||||
$this->error->set(Err::ParsingFailed, 'json');
|
|
||||||
return false;
|
/* (3) Si erreur lecture */
|
||||||
}
|
if( $conf === false )
|
||||||
|
return $this->error->set(Err::UnreachableResource);
|
||||||
|
|
||||||
|
/* (4) Parsage json */
|
||||||
|
$this->modules = json_decode( $conf, true );
|
||||||
|
|
||||||
|
/* (5) Gestion de l'erreur de parsage */
|
||||||
|
if( $this->modules == null )
|
||||||
|
return $this->error->set(Err::ParsingFailed, 'json');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* [3] Verification des types des parametres
|
/* [3] Verification des types des parametres
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
/* (1) Section Title */
|
/* (1) Si path est une <string> */
|
||||||
if( !is_string($path) ){ // Si le type est incorrect
|
if( !is_string($path) ) // Si le type est incorrect
|
||||||
$this->error->set(Err::WrongPathModule);
|
return $this->error->set(Err::WrongPathModule);
|
||||||
return false; // On retourne FALSE, si erreur
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (2) Section Title */
|
/* (2) Formattage @params en tableau */
|
||||||
$params = (is_array($params)) ? $params : [];
|
$params = (is_array($params)) ? $params : [];
|
||||||
|
|
||||||
/* (3) On définit en constante la méthode HTTP */
|
/* (3) On définit en constante la méthode HTTP */
|
||||||
|
if( !isset($_SERVER['REQUEST_METHOD']) )
|
||||||
|
return $this->error->set(Err::UnknownHttpMethod);
|
||||||
|
|
||||||
$this->http_method = strtoupper($_SERVER['REQUEST_METHOD']);
|
$this->http_method = strtoupper($_SERVER['REQUEST_METHOD']);
|
||||||
|
|
||||||
|
|
||||||
/* [4] Verification du chemin (existence module+methode)
|
/* [4] Verification du chemin (existence module+methode)
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
if( !$this->checkPath($path) ) // Verification de la coherence du chemin + attribution
|
if( !$this->checkPath($path) ) // Verification de la coherence du chemin + attribution
|
||||||
return false;
|
return false; // checkPath() sets the error itself
|
||||||
|
|
||||||
|
|
||||||
/* [5] Verification des droits
|
/* [5] Verification des droits
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
if( !$this->checkPermission() ) // Si on a pas les droits
|
if( !$this->checkPermission() ) // Si on a pas les droits
|
||||||
return false;
|
return false; // checkPermission() sets the error itself
|
||||||
|
|
||||||
|
|
||||||
/* [6] Verification des parametres (si @type est defini)
|
/* [6] Verification des parametres (si @type est defini)
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
if( !$this->checkParams($params) ) // Verification de tous les types
|
if( !$this->checkParams($params) ) // Verification de tous les types
|
||||||
return false;
|
return false; // checkParams() sets the error itself
|
||||||
|
|
||||||
|
|
||||||
/* [7] Récupèration des options
|
/* [7] Récupèration des options
|
||||||
|
@ -115,7 +138,6 @@
|
||||||
$this->error->set(Err::Success);
|
$this->error->set(Err::Success);
|
||||||
|
|
||||||
return true; // On retourne que tout s'est bien passe
|
return true; // On retourne que tout s'est bien passe
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -401,10 +423,8 @@
|
||||||
private function checkPath($path){
|
private function checkPath($path){
|
||||||
/* [1] Verification format general
|
/* [1] Verification format general
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
if( !preg_match('#^([\w_-]+)/([\w_-]+)$#i', $path, $matches) ){ // Si mauvais format
|
if( !preg_match('@^([\w_-]+)/([\w_-]+)$@i', $path, $matches) ) // Si mauvais format
|
||||||
$this->error->set(Err::WrongPathModule);
|
return $this->error->set(Err::WrongPathModule);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// On recupere les données de la regex
|
// On recupere les données de la regex
|
||||||
$module = $matches[1];
|
$module = $matches[1];
|
||||||
|
@ -413,18 +433,14 @@
|
||||||
|
|
||||||
/* [2] Verification de l'existence du module (conf)
|
/* [2] Verification de l'existence du module (conf)
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
if( !array_key_exists($module, $this->modules) ){ // Si le module n'est pas specifie dans la conf
|
if( !array_key_exists($module, $this->modules) ) // Si le module n'est pas specifie dans la conf
|
||||||
$this->error->set(Err::UnknownModule, $module);
|
return $this->error->set(Err::UnknownModule, $module);
|
||||||
return false; // On retourne FALSE, si erreur
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* [3] Verification de l'existence de la methode (conf)
|
/* [3] Verification de l'existence de la methode (conf)
|
||||||
=========================================================*/
|
=========================================================*/
|
||||||
if( array_key_exists($method, $this->modules[$module]) === false ){ // Si la methode n'est pas specifie dans la conf
|
if( array_key_exists($method, $this->modules[$module]) === false ) // Si la methode n'est pas specifie dans la conf
|
||||||
$this->error->set(Err::UnknownMethod, preg_replace('/\w+::/i', '', $method) );
|
return $this->error->set(Err::UnknownMethod, preg_replace('/\w+::/i', '', $method) );
|
||||||
return false; // On retourne FALSE, si erreur
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,281 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Kahlan\Plugin\Stub;
|
||||||
|
use Kahlan\Plugin\Monkey;
|
||||||
|
|
||||||
|
use api\core\Request;
|
||||||
|
use error\core\Error;
|
||||||
|
use error\core\Err;
|
||||||
|
|
||||||
|
describe('api/core/Request', function(){
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
$_SERVER = [
|
||||||
|
'REQUEST_METHOD' => 'POST'
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('[check] config file', function(){
|
||||||
|
|
||||||
|
it('pass when config file exists', function(){
|
||||||
|
|
||||||
|
expect( file_exists(Request::config_path()) )->toBeTruthy();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pass when we can read the config file', function(){
|
||||||
|
|
||||||
|
expect( @file_get_contents(Request::config_path()) )->not->toBe(false);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pass when the config file is valid json', function(){
|
||||||
|
|
||||||
|
$read = @file_get_contents(Request::config_path());
|
||||||
|
expect($read)->not->toBe(false);
|
||||||
|
expect( json_decode($read, true) )->not->toBeNull();
|
||||||
|
expect( json_decode($read, true) )->toBeA('array');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('__construct(@path, @params)', function(){
|
||||||
|
|
||||||
|
context('with argument combinations', function(){
|
||||||
|
|
||||||
|
it('fail if @path is missing', function(){
|
||||||
|
|
||||||
|
$req = new Request();
|
||||||
|
|
||||||
|
expect($req->error->get())->toBe(Err::MissingPath);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fail if @path is not a string', function(){
|
||||||
|
|
||||||
|
expect('is_string')->toBeCalled();
|
||||||
|
$req = new Request(1);
|
||||||
|
|
||||||
|
expect($req->error->get())->toBe(Err::WrongPathModule);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pass if @params is an array', function(){
|
||||||
|
|
||||||
|
unset($_SERVER);
|
||||||
|
expect('is_array')->toBeCalled();
|
||||||
|
|
||||||
|
$req = new Request('someString', ['a', 'b']);
|
||||||
|
|
||||||
|
expect($req->error->get())->toBe(Err::UnknownHttpMethod);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pass if @params is not an array (default: [])', function(){
|
||||||
|
|
||||||
|
unset($_SERVER);
|
||||||
|
|
||||||
|
expect('is_array')->toBeCalled();
|
||||||
|
|
||||||
|
$types = [true, false, null, 1, 2.3, -1.2, 0, 'blabla'];
|
||||||
|
|
||||||
|
foreach($types as $type){
|
||||||
|
|
||||||
|
$req = new Request('someString', true);
|
||||||
|
expect($req->error->get())->toBe(Err::UnknownHttpMethod);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
context('with config errors', function(){
|
||||||
|
|
||||||
|
it('fail if the config file exists', function(){
|
||||||
|
|
||||||
|
// Request::config_path -> 'aa'
|
||||||
|
allow(Request::class)->toReceive('::config_path')->andReturn('invalid_fname');
|
||||||
|
expect(Request::config_path())->toBe('invalid_fname');
|
||||||
|
|
||||||
|
// file_exists -> false
|
||||||
|
allow('file_exists')->toBeCalled()->andReturn(false);
|
||||||
|
expect('file_exists')->toBeCalled();
|
||||||
|
|
||||||
|
$req = new Request('a/b');
|
||||||
|
|
||||||
|
expect($req->error->get())->toBe(Err::UnreachableResource);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fail if the config file cannot be read', function(){
|
||||||
|
|
||||||
|
// file_get_contents -> false
|
||||||
|
allow('file_get_contents')->toBeCalled()->andReturn(false);
|
||||||
|
expect('file_get_contents')->toBeCalled();
|
||||||
|
|
||||||
|
$req = new Request('a/b');
|
||||||
|
|
||||||
|
expect($req->error->get())->toBe(Err::UnreachableResource);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fail if the json format is not valid', function(){
|
||||||
|
|
||||||
|
// file_exists -> true
|
||||||
|
allow('file_exists')->toBeCalled()->andReturn(true);
|
||||||
|
expect('file_exists')->toBeCalled();
|
||||||
|
|
||||||
|
// file_get_contents -> false
|
||||||
|
allow('file_get_contents')->toBeCalled()->andReturn('{incorrect_json');
|
||||||
|
expect('file_get_contents')->toBeCalled();
|
||||||
|
|
||||||
|
// json_decode -> called
|
||||||
|
expect('json_decode')->toBeCalled();
|
||||||
|
|
||||||
|
$req = new Request('a/b');
|
||||||
|
|
||||||
|
expect($req->error->get())->toBe(Err::ParsingFailed);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
context('with checks errors', function(){
|
||||||
|
|
||||||
|
it('fail with checkPath() fails', function(){
|
||||||
|
|
||||||
|
allow(Request::class)->toReceive('checkPath')->andRun(function(){
|
||||||
|
$this->error->set(Err::UnknownError);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$req = new Request('a/b');
|
||||||
|
|
||||||
|
expect($req->error->get())->toBe(Err::UnknownError);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fail with checkPermission() fails', function(){
|
||||||
|
|
||||||
|
// bypass checkPath();
|
||||||
|
allow(Request::class)->toReceive('checkPath')->andReturn(true);
|
||||||
|
|
||||||
|
allow(Request::class)->toReceive('checkPermission')->andRun(function(){
|
||||||
|
$this->error->set(Err::UnknownError);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$req = new Request('a/b');
|
||||||
|
|
||||||
|
expect($req->error->get())->toBe(Err::UnknownError);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fail with checkParams() fails', function(){
|
||||||
|
|
||||||
|
// bypass checkPath(); + checkPermission();
|
||||||
|
allow(Request::class)->toReceive('checkPath')->andReturn(true);
|
||||||
|
allow(Request::class)->toReceive('checkPermission')->andReturn(true);
|
||||||
|
|
||||||
|
allow(Request::class)->toReceive('checkParams')->andRun(function(){
|
||||||
|
$this->error->set(Err::UnknownError);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$req = new Request('a/b');
|
||||||
|
|
||||||
|
expect($req->error->get())->toBe(Err::UnknownError);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pass with all checks ok', function(){
|
||||||
|
|
||||||
|
// bypass all checks
|
||||||
|
allow(Request::class)->toReceive('checkPath')->andReturn(true);
|
||||||
|
allow(Request::class)->toReceive('checkPermission')->andReturn(true);
|
||||||
|
allow(Request::class)->toReceive('checkParams')->andReturn(true);
|
||||||
|
|
||||||
|
// bypass buildOptions();
|
||||||
|
allow(Request::class)->toReceive('buildOptions')->andReturn(true);
|
||||||
|
|
||||||
|
$req = new Request('a/b');
|
||||||
|
|
||||||
|
expect($req->error->get())->toBe(Err::Success);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('checkPath(@path)', function(){
|
||||||
|
|
||||||
|
it('fail when wrong path format: \'module/method\'', function(){
|
||||||
|
|
||||||
|
$values = ['a-b', 'a /b', 'a/b '];
|
||||||
|
|
||||||
|
foreach($values as $value){
|
||||||
|
|
||||||
|
$req = new Request($value);
|
||||||
|
expect($req->error->get())->toBe(Err::WrongPathModule);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pass when valid path format: letter/number/-/_', function(){
|
||||||
|
|
||||||
|
$values = ['a_b-c/d-e_f', 'abc/def', '_a_/_b_'];
|
||||||
|
|
||||||
|
foreach($values as $value){
|
||||||
|
|
||||||
|
$req = new Request($value);
|
||||||
|
expect($req->error->get())->not->toBe(Err::WrongPathModule);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fail when unknown module', function(){
|
||||||
|
|
||||||
|
allow('json_decode')->toBeCalled()->andReturn([
|
||||||
|
'mo-du_leA' => [],
|
||||||
|
'moduleB' => []
|
||||||
|
]);
|
||||||
|
|
||||||
|
$values = ['modulea/method', 'MODULEA/method', 'moduleC/method'];
|
||||||
|
|
||||||
|
foreach($values as $value){
|
||||||
|
|
||||||
|
$req = new Request($value);
|
||||||
|
expect($req->error->get())->toBe(Err::UnknownModule);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fail when unknown method', function(){
|
||||||
|
|
||||||
|
allow('json_decode')->toBeCalled()->andReturn([
|
||||||
|
'mo-du_leA' => [ 'POST::me-th_odA' => [] ],
|
||||||
|
'moduleB' => []
|
||||||
|
]);
|
||||||
|
|
||||||
|
$values = ['mo-du_leA/me-thodA', 'mo-du_leA/meth_odA', 'mo-du_leA/me-th_oda'];
|
||||||
|
|
||||||
|
foreach($values as $value){
|
||||||
|
|
||||||
|
$req = new Request($value);
|
||||||
|
expect($req->error->get())->toBe(Err::UnknownMethod);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue