diff --git a/dev/setup/phpunit/PHPUNIT.BAT b/dev/setup/phpunit/PHPUNIT.BAT index b931a081528..cd36711f8b0 100644 --- a/dev/setup/phpunit/PHPUNIT.BAT +++ b/dev/setup/phpunit/PHPUNIT.BAT @@ -1,9 +1,4 @@ -@ECHO OFF -REM SAMPLE WINDOWS SCRIPT TO START TESTS -REM -REM CURRENTLY THIS SCRIPT MUST BE LOCATED AT THE ROOT OF THE PROJECT. -REM A copy of phpunit-9.5.phar is required - +REM @ECHO OFF SET OPEN_BASEDIR=%~dp0 SET DD_TRACE_CLI_ENABLED=1 @@ -17,8 +12,10 @@ REM REM The DOMAIN/Port value should be the same as in htdocs/conf/conf.php REM (This is only needed if did not set up another server locally REM for your test installation database). -SET PHPSERVER_DOMAIN_PORT=127.0.0.1:80 +SET PHPSERVER_DOMAIN_PORT=127.0.0.1:8080 SET PHPSERVER_LOG=%~dp0/php_serv.log + +echo if (class_exists('PHPUnit\Framework\TestSuite')) { $dolibarr_main_url_root='http://%PHPSERVER_DOMAIN_PORT%'; } >> %~dp0\htdocs\conf\conf.php GOTO :START REM The error handler @@ -37,7 +34,7 @@ for /F "tokens=2 delims=," %%i in ('tasklist /FI "IMAGENAME eq php.exe" /FO CSV :FOUND_PID echo "Server PID: %php_pid%" -curl "http://%PHPSERVER_DOMAIN_PORT%" +REM curl "http://%PHPSERVER_DOMAIN_PORT%" SET MEMOPT=-d memory-limit=-1 diff --git a/test/phpunit/AbstractRestAPITest.php b/test/phpunit/AbstractRestAPITest.php new file mode 100644 index 00000000000..fa1cb867283 --- /dev/null +++ b/test/phpunit/AbstractRestAPITest.php @@ -0,0 +1,107 @@ + + * Copyright (C) 2023 Alexandre Janniaux + * Copyright (C) 2024 MDW + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file test/phpunit/AbstractRestAPITest.php + * \ingroup test + * \brief Abstract Class for Rest API Tests + */ + +global $conf,$user,$langs,$db; +//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver +//require_once 'PHPUnit/Autoload.php'; +require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; +require_once dirname(__FILE__).'/../../htdocs/core/lib/date.lib.php'; +require_once dirname(__FILE__).'/../../htdocs/core/lib/geturl.lib.php'; +require_once dirname(__FILE__).'/CommonClassTest.class.php'; + +if (empty($user->id)) { + print "Load permissions for admin user nb 1\n"; + $user->fetch(1); + $user->getrights(); +} +$conf->global->MAIN_DISABLE_ALL_MAILS = 1; +$conf->global->MAIN_UMASK = '0666'; + + +/** + * Class for PHPUnit tests + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + */ +abstract class AbstractRestAPITest extends CommonClassTest +{ + protected $api_url; + protected $api_key; + + /** + * setUpBeforeClass + * + * @return void + */ + public static function setUpBeforeClass(): void + { + parent::setUpBeforeClass(); + + self::assertTrue(isModEnabled('api'), " module api must be enabled."); + } + + /** + * Init phpunit tests + * + * @return void + */ + protected function setUp(): void + { + parent::setUp(); + + global $conf,$user,$langs,$db; + $conf = $this->savconf; + $user = $this->savuser; + $langs = $this->savlangs; + $db = $this->savdb; + + $this->api_url = DOL_MAIN_URL_ROOT.'/api/index.php'; + $addheaders = array('Content-Type: application/json', 'Accept: application/json'); + + $method = get_called_class()."::".__FUNCTION__; + $test = "API Test Setup - "; + $login = 'admin'; + $password = 'admin'; + $url = $this->api_url.'/login?login='.$login.'&password='.$password; + // Call the API login method to save api_key for this test class. + // At first call, if token is not defined a random value is generated and returned. + $result = getURLContent($url, 'GET', '', 1, $addheaders, array('http', 'https'), 2); + print "$method result = ".var_export($result, true)."\n"; + print "$method curl_error_no: ".$result['curl_error_no']."\n"; + $this->assertEquals('', $result['curl_error_no'], "$test Should not have a curl error"); + $object = json_decode($result['content'], true); // If success content is just an id, if not an array + + $this->assertNotNull($object, "$test Parsing of JSON result must not be null"); + $this->assertNotEquals(500, (empty($object['error']['code']) ? 0 : $object['error']['code']), "$test Error".(empty($object['error']['message']) ? '' : ' '.$object['error']['message'])); + $this->assertEquals('200', $object['success']['code']); + + $this->api_key = $object['success']['token']; + + print "$method api_key: $this->api_key \n"; + } +} diff --git a/test/phpunit/RestAPIMosTest.php b/test/phpunit/RestAPIMosTest.php new file mode 100644 index 00000000000..d16640fffd3 --- /dev/null +++ b/test/phpunit/RestAPIMosTest.php @@ -0,0 +1,173 @@ + + * Copyright (C) 2023 Alexandre Janniaux + * Copyright (C) 2024 MDW + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file test/phpunit/RestAPIUserTest.php + * \ingroup test + * \brief PHPUnit test + * \remarks To run this script as CLI: phpunit filename.php + */ + +//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver +//require_once 'PHPUnit/Autoload.php'; +require_once __DIR__."/AbstractRestAPITest.php"; + +/** + * Class for PHPUnit tests + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + */ +class RestAPIMosTest extends AbstractRestAPITest +{ + /** + * + * @param string $endpoint Endpoint - "user/id" + * @param string $test_title Text to be added to output + * @param 'POST'|'GET' $method Call Method + * @param mixed $data Data that will be JSON encoded + * @param int $expected_error Expected error code + * + * @return mixed Decodes JSON value returned by the service + * + */ + private function getUrl($endpoint, $test_title = "", $method = "GET", $data = null, $expected_error = 0) + { + + // Encode parameters in JSON body when POST, as URL query key/values otherwise. + $params = ''; + $body = null; + if ($method === 'POST') { + $body = json_encode($data); + } elseif (!empty($data)) { + $params = '?'.http_build_query($data); + } + + + $addheaders = array( + 'Content-Type: application/json','Accept: application/json', "DOLAPIKEY: {$this->api_key}"); + + // $url = $this->api_url.'/'.$endpoint.'?'.http_build_query(['api_key'=>$this->api_key]); + // + $url = $this->api_url.'/'.$endpoint.$params; + + // getURLContent($url, $postorget, $param, $followlocation, $addheaders, $allowedschemes, $localurl, $ssl_verifypeer) + + $result = getURLContent($url, $method, $body, 1, $addheaders, array('http', 'https'), 2); + + $this->assertEquals('', $result['curl_error_no'], "{$test_title}Should not have a curl error"); + + $object = json_decode($result['content'], true); + + $dbg_info = PHP_EOL.json_encode($result, JSON_PRETTY_PRINT); + + $this->assertNotNull($object, "{$test_title}Parsing of JSON result must not be null$dbg_info"); + + $result['content'] = $object; + $dbg_info = PHP_EOL.json_encode($result, JSON_PRETTY_PRINT); + + $this->assertEquals($expected_error, (empty($object['error']['code']) ? 0 : $object['error']['code']), "{$test_title}Error code is not $expected_error$dbg_info"); + + return $result; + } + + /** + * testRestMoCreate + * + * @return int + */ + public function testRestMoCreate() + { + + $test = "Create MO "; + $data = [ + 'ref' => 'Try1', + 'mrptype' => 0, + 'fk_product' => 1, + 'qty' => 1, + 'status' => 1, // 0=Draft,1=Validated,2=InProgress,3=Produced,9=Canceled + ]; + $result = $this->getUrl('mos', $test, 'POST', $data); + + print json_encode($result, JSON_PRETTY_PRINT); + $this->assertTrue(is_int($result['content']), "$test Result data is expected to be integer"); + + /// return $object['id']; + return $result['content']; + } + + + /** + * testRestMoProduceAndConsumete + * + * @depends testRestMoCreate + * + * @param int $mos_id Id of MO that was created + * @return void + */ + public function testRestMoList($mos_id) + { + + $test = "Produce MO "; + + //$data = ['ref' => 'Try1', 'mrptype' => 0, 'fk_product' => 1, 'qty' => 1, 'status' => 0, ]; + $data = null; + $result = $this->getUrl("mos", $test, 'GET', ['sortfield' => 't.rowid', 'sortorder' => 'DESC', 'limit' => 100]); + + // print json_encode($result, JSON_PRETTY_PRINT); + + $this->assertEquals($mos_id, $result['content'][0]['id'] ?? null, "{$test}First item in reversed list should be new item"); + } + + /** + * testRestMoProduceAndConsume + * + * @depends testRestMoCreate + * + * @param int $mos_id Id of MO that was created + * @return int + */ + public function testRestMoProduceAndConsume($mos_id) + { + + $test = "Produce and Consume MO "; + + $mos_state_id = 1; // $depends; + + + + $data + = [ + "inventorylabel" => "Produce and consume using API", + "inventorycode" => "PRODUCEAPI-YY-MM-DD", + "autoclose" => 1, + "arraytoconsume" => [], + "arraytoproduce" => [$mod_id] ]; + + $result = $this->getUrl("mos/{$mos_state_id}/produceandconsume", $test, 'POST', $data); + + print json_encode($result, JSON_PRETTY_PRINT); + $this->assertTrue(is_int($result['content']), "{$test}Result data is expected to be integer"); + + /// return $object['id']; + return $result['content']; + } +} diff --git a/test/phpunit/RestAPIUserTest.php b/test/phpunit/RestAPIUserTest.php index 851a26abec4..1d95870abc9 100644 --- a/test/phpunit/RestAPIUserTest.php +++ b/test/phpunit/RestAPIUserTest.php @@ -25,22 +25,10 @@ * \remarks To run this script as CLI: phpunit filename.php */ -global $conf,$user,$langs,$db; //define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver //require_once 'PHPUnit/Autoload.php'; -require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; -require_once dirname(__FILE__).'/../../htdocs/core/lib/date.lib.php'; -require_once dirname(__FILE__).'/../../htdocs/core/lib/geturl.lib.php'; -require_once dirname(__FILE__).'/CommonClassTest.class.php'; - -if (empty($user->id)) { - print "Load permissions for admin user nb 1\n"; - $user->fetch(1); - $user->getrights(); -} -$conf->global->MAIN_DISABLE_ALL_MAILS = 1; -$conf->global->MAIN_UMASK = '0666'; +require_once __DIR__."/AbstractRestAPITest.php"; /** * Class for PHPUnit tests @@ -49,66 +37,8 @@ $conf->global->MAIN_UMASK = '0666'; * @backupStaticAttributes enabled * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. */ -class RestAPIUserTest extends CommonClassTest +class RestAPIUserTest extends AbstractRestAPITest { - protected $api_url; - protected $api_key; - - /** - * setUpBeforeClass - * - * @return void - */ - public static function setUpBeforeClass(): void - { - global $conf,$user,$langs,$db; - $db->begin(); // This is to have all actions inside a transaction even if test launched without suite. - - if (!isModEnabled('api')) { - print __METHOD__." module api must be enabled.\n"; - die(1); - } - - print __METHOD__."\n"; - } - - /** - * Init phpunit tests - * - * @return void - */ - protected function setUp(): void - { - global $conf,$user,$langs,$db; - $conf = $this->savconf; - $user = $this->savuser; - $langs = $this->savlangs; - $db = $this->savdb; - - $this->api_url = DOL_MAIN_URL_ROOT.'/api/index.php'; - - $test = "API Test Setup - "; - $login = 'admin'; - $password = 'admin'; - $url = $this->api_url.'/login?login='.$login.'&password='.$password; - // Call the API login method to save api_key for this test class. - // At first call, if token is not defined a random value is generated and returned. - $result = getURLContent($url, 'GET', '', 1, array(), array('http', 'https'), 2); - print __METHOD__." result = ".var_export($result, true)."\n"; - print __METHOD__." curl_error_no: ".$result['curl_error_no']."\n"; - $this->assertEquals('', $result['curl_error_no'], "$test Should not have a curl error"); - $object = json_decode($result['content'], true); // If success content is just an id, if not an array - - $this->assertNotNull($object, "$test Parsing of JSON result must not be null"); - $this->assertNotEquals(500, (empty($object['error']['code']) ? 0 : $object['error']['code']), "$test Error".(empty($object['error']['message']) ? '' : ' '.$object['error']['message'])); - $this->assertEquals('200', $object['success']['code']); - - $this->api_key = $object['success']['token']; - - print __METHOD__." api_key: $this->api_key \n"; - } - - /** * testRestGetUser *