add: add users add/edit/delete api tests and openapi docs.

pull/80/head
Luciano Righetti 2022-01-10 11:58:52 +01:00
parent 6776789fdf
commit 28650fa91c
7 changed files with 287 additions and 19 deletions

View File

@ -14,7 +14,7 @@ class AuthKeysFixture extends TestFixture
public const ADMIN_API_KEY = 'd033e22ae348aeb5660fc2140aec35850c4da997';
public const SYNC_API_KEY = '6b387ced110858dcbcda36edb044dc18f91a0894';
public const ORG_ADMIN_API_KEY = '1c4685d281d478dbcebd494158024bc3539004d0';
public const USER_API_KEY = '12dea96fec20593566ab75692c9949596833adc9';
public const REGULAR_USER_API_KEY = '12dea96fec20593566ab75692c9949596833adc9';
public function init(): void
{
@ -57,9 +57,9 @@ class AuthKeysFixture extends TestFixture
],
[
'uuid' => $faker->uuid(),
'authkey' => $hasher->hash(self::USER_API_KEY),
'authkey_start' => substr(self::USER_API_KEY, 0, 4),
'authkey_end' => substr(self::USER_API_KEY, -4),
'authkey' => $hasher->hash(self::REGULAR_USER_API_KEY),
'authkey_start' => substr(self::REGULAR_USER_API_KEY, 0, 4),
'authkey_end' => substr(self::REGULAR_USER_API_KEY, -4),
'expiration' => 0,
'user_id' => UsersFixture::USER_REGULAR_USER_ID,
'comment' => '',

View File

@ -65,7 +65,7 @@ trait ApiTestTrait
* @param string $method The HTTP method used to call the endpoint
* @return void
*/
public function validateRequest(string $endpoint, string $method = 'get'): void
public function assertRequestMatchesOpenApiSpec(string $endpoint, string $method = 'get'): void
{
// TODO: find a workaround to create a PSR-7 request object for validation
throw NotImplementedException("Unfortunately cakephp does not save the PSR-7 request object in the test context");
@ -78,9 +78,49 @@ trait ApiTestTrait
* @param string $method The HTTP method used to call the endpoint
* @return void
*/
public function validateResponse(string $endpoint, string $method = 'get'): void
public function assertResponseMatchesOpenApiSpec(string $endpoint, string $method = 'get'): void
{
$address = new OperationAddress($endpoint, $method);
$this->responseValidator->validate($address, $this->_response);
}
/**
* Validates a record exists in the database
*
* @param string $table The table name
* @param array $conditions The conditions to check
* @return void
* @throws \Exception
* @throws \Cake\Datasource\Exception\RecordNotFoundException
*
* @see https://book.cakephp.org/4/en/orm-query-builder.html
*/
public function assertDbRecordExists(string $table, array $conditions): void
{
$record = $this->getTableLocator()->get($table)->find()->where($conditions)->first();
if (!$record) {
throw new \PHPUnit\Framework\AssertionFailedError("Record not found in table '$table' with conditions: " . json_encode($conditions));
}
$this->assertNotEmpty($record);
}
/**
* Validates a record do notexists in the database
*
* @param string $table The table name
* @param array $conditions The conditions to check
* @return void
* @throws \Exception
* @throws \Cake\Datasource\Exception\RecordNotFoundException
*
* @see https://book.cakephp.org/4/en/orm-query-builder.html
*/
public function assertDbRecordNotExists(string $table, array $conditions): void
{
$record = $this->getTableLocator()->get($table)->find()->where($conditions)->first();
if ($record) {
throw new \PHPUnit\Framework\AssertionFailedError("Record found in table '$table' with conditions: " . json_encode($conditions));
}
$this->assertEmpty($record);
}
}

View File

@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
namespace App\Test\TestCase\Api\Users;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;
use App\Test\Fixture\AuthKeysFixture;
use App\Test\Fixture\UsersFixture;
use App\Test\Fixture\OrganisationsFixture;
use App\Test\Fixture\RolesFixture;
use App\Test\Helper\ApiTestTrait;
class AddUserApiTest extends TestCase
{
use IntegrationTestTrait;
use ApiTestTrait;
protected const ENDPOINT = '/api/v1/users/add';
protected $fixtures = [
'app.Individuals',
'app.Roles',
'app.Users',
'app.AuthKeys'
];
public function setUp(): void
{
parent::setUp();
$this->initializeValidator(APP . '../webroot/docs/openapi.yaml');
}
public function testAddUser(): void
{
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
$this->post(
self::ENDPOINT,
[
'individual_id' => UsersFixture::USER_REGULAR_USER_ID,
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
'role_id' => RolesFixture::ROLE_REGULAR_USER_ID,
'disabled' => false,
'username' => 'test',
'password' => 'Password123456!',
]
);
$this->assertResponseOk();
$this->assertResponseContains('"username": "test"');
$this->assertDbRecordExists('Users', ['username' => 'test']);
//TODO: $this->assertRequestMatchesOpenApiSpec();
$this->assertResponseMatchesOpenApiSpec(self::ENDPOINT, 'post');
}
public function testAddUserNotAllowedToRegularUser(): void
{
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
$this->post(
self::ENDPOINT,
[
'individual_id' => UsersFixture::USER_REGULAR_USER_ID,
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
'role_id' => RolesFixture::ROLE_REGULAR_USER_ID,
'disabled' => false,
'username' => 'test',
'password' => 'Password123456!'
]
);
$this->assertResponseCode(405);
$this->assertDbRecordNotExists('Users', ['username' => 'test']);
//TODO: $this->assertRequestMatchesOpenApiSpec();
$this->assertResponseMatchesOpenApiSpec(self::ENDPOINT, 'post');
}
}

View File

@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace App\Test\TestCase\Api\Users;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;
use App\Test\Fixture\AuthKeysFixture;
use App\Test\Fixture\UsersFixture;
use App\Test\Fixture\OrganisationsFixture;
use App\Test\Fixture\RolesFixture;
use App\Test\Helper\ApiTestTrait;
class DeleteUserApiTest extends TestCase
{
use IntegrationTestTrait;
use ApiTestTrait;
protected const ENDPOINT = '/api/v1/users/delete';
protected $fixtures = [
'app.Individuals',
'app.Roles',
'app.Users',
'app.AuthKeys'
];
public function setUp(): void
{
parent::setUp();
$this->initializeValidator(APP . '../webroot/docs/openapi.yaml');
}
public function testDeleteUser(): void
{
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
$url = sprintf('%s/%d', self::ENDPOINT, UsersFixture::USER_REGULAR_USER_ID);
$this->delete($url);
$this->assertResponseOk();
$this->assertDbRecordNotExists('Users', ['id' => UsersFixture::USER_REGULAR_USER_ID]);
//TODO: $this->assertRequestMatchesOpenApiSpec();
$this->assertResponseMatchesOpenApiSpec($url, 'delete');
$this->addWarning('TODO: CRUDComponent::delete() sets some view variables, does not take into account `isRest()`, fix it.');
}
public function testDeleteUserNotAllowedToRegularUser(): void
{
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
$url = sprintf('%s/%d', self::ENDPOINT, UsersFixture::USER_ORG_ADMIN_ID);
$this->delete($url);
$this->assertResponseCode(405);
$this->assertDbRecordExists('Users', ['id' => UsersFixture::USER_ORG_ADMIN_ID]);
//TODO: $this->assertRequestMatchesOpenApiSpec();
$this->assertResponseMatchesOpenApiSpec($url, 'delete');
$this->addWarning('TODO: CRUDComponent::delete() sets some view variables, does not take into account `isRest()`, fix it.');
}
}

View File

@ -0,0 +1,91 @@
<?php
declare(strict_types=1);
namespace App\Test\TestCase\Api\Users;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;
use App\Test\Fixture\AuthKeysFixture;
use App\Test\Fixture\UsersFixture;
use App\Test\Fixture\OrganisationsFixture;
use App\Test\Fixture\RolesFixture;
use App\Test\Helper\ApiTestTrait;
class EditUserApiTest extends TestCase
{
use IntegrationTestTrait;
use ApiTestTrait;
protected const ENDPOINT = '/api/v1/users/edit';
protected $fixtures = [
'app.Individuals',
'app.Roles',
'app.Users',
'app.AuthKeys'
];
public function setUp(): void
{
parent::setUp();
$this->initializeValidator(APP . '../webroot/docs/openapi.yaml');
}
public function testEditUser(): void
{
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
$url = sprintf('%s/%d', self::ENDPOINT, UsersFixture::USER_REGULAR_USER_ID);
$this->put(
$url,
[
'id' => UsersFixture::USER_REGULAR_USER_ID,
'role_id' => RolesFixture::ROLE_ORG_ADMIN_ID,
]
);
$this->assertResponseOk();
$this->assertDbRecordExists('Users', [
'id' => UsersFixture::USER_REGULAR_USER_ID,
'role_id' => RolesFixture::ROLE_ORG_ADMIN_ID
]);
//TODO: $this->assertRequestMatchesOpenApiSpec();
$this->assertResponseMatchesOpenApiSpec($url, 'put');
}
public function testEditRoleNotAllowedToRegularUser(): void
{
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
$this->put(
self::ENDPOINT,
[
'role_id' => RolesFixture::ROLE_ADMIN_ID,
]
);
$this->assertDbRecordNotExists('Users', [
'id' => UsersFixture::USER_REGULAR_USER_ID,
'role_id' => RolesFixture::ROLE_ADMIN_ID
]);
//TODO: $this->assertRequestMatchesOpenApiSpec();
$this->assertResponseMatchesOpenApiSpec(self::ENDPOINT, 'put');
}
public function testEditSelfUser(): void
{
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
$this->put(
self::ENDPOINT,
[
'username' => 'test',
]
);
$this->assertDbRecordExists('Users', [
'id' => UsersFixture::USER_REGULAR_USER_ID,
'username' => 'test'
]);
//TODO: $this->assertRequestMatchesOpenApiSpec();
$this->assertResponseMatchesOpenApiSpec(self::ENDPOINT, 'put');
}
}

View File

@ -30,14 +30,14 @@ class IndexUsersApiTest extends TestCase
$this->initializeValidator(APP . '../webroot/docs/openapi.yaml');
}
public function testIndex(): void
public function testIndexUsers(): void
{
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
$this->get(self::ENDPOINT);
$this->assertResponseOk();
$this->assertResponseContains(sprintf('"username": "%s"', UsersFixture::USER_ADMIN_USERNAME));
// TODO: $this->validateRequest()
$this->validateResponse(self::ENDPOINT);
// TODO: $this->assertRequestMatchesOpenApiSpec();
$this->assertResponseMatchesOpenApiSpec(self::ENDPOINT);
}
}

View File

@ -30,26 +30,26 @@ class ViewUserApiTest extends TestCase
$this->initializeValidator(APP . '../webroot/docs/openapi.yaml');
}
public function testViewMe(): void
public function testViewMyUser(): void
{
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
$this->get(self::ENDPOINT);
$this->assertResponseOk();
$this->assertResponseContains(sprintf('"username": "%s"', UsersFixture::USER_ADMIN_USERNAME));
// TODO: $this->validateRequest()
$this->validateResponse(self::ENDPOINT);
// TODO: $this->assertRequestMatchesOpenApiSpec();
$this->assertResponseMatchesOpenApiSpec(self::ENDPOINT);
}
public function testViewById(): void
public function testViewUserById(): void
{
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
$url = sprintf('%s/%d', self::ENDPOINT, UsersFixture::USER_ADMIN_ID);
$url = sprintf('%s/%d', self::ENDPOINT, UsersFixture::USER_REGULAR_USER_ID);
$this->get($url);
$this->assertResponseOk();
$this->assertResponseContains(sprintf('"username": "%s"', UsersFixture::USER_ADMIN_USERNAME));
// TODO: $this->validateRequest()
$this->validateResponse($url);
$this->assertResponseContains(sprintf('"username": "%s"', UsersFixture::USER_REGULAR_USER_USERNAME));
// TODO: $this->assertRequestMatchesOpenApiSpec();
$this->assertResponseMatchesOpenApiSpec($url);
}
}