new: add /api/v1/users/index api test
parent
c14b84fcc0
commit
6776789fdf
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Test\Helper;
|
namespace App\Test\Helper;
|
||||||
|
|
||||||
|
use Cake\Http\Exception\NotImplementedException;
|
||||||
use \League\OpenAPIValidation\PSR7\ValidatorBuilder;
|
use \League\OpenAPIValidation\PSR7\ValidatorBuilder;
|
||||||
use \League\OpenAPIValidation\PSR7\RequestValidator;
|
use \League\OpenAPIValidation\PSR7\RequestValidator;
|
||||||
use \League\OpenAPIValidation\PSR7\ResponseValidator;
|
use \League\OpenAPIValidation\PSR7\ResponseValidator;
|
||||||
|
@ -38,6 +39,12 @@ trait ApiTestTrait
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function assertResponseContainsArray(array $expected): void
|
||||||
|
{
|
||||||
|
$responseArray = json_decode((string)$this->_response->getBody(), true);
|
||||||
|
throw new NotImplementedException('TODO: see codeception seeResponseContainsJson()');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the OpenAPI specification and create a validator
|
* Parse the OpenAPI specification and create a validator
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Testing
|
# Testing
|
||||||
|
## Configuration
|
||||||
1. Add a `cerebrate_test` database to the db:
|
1. Add a `cerebrate_test` database to the db:
|
||||||
```mysql
|
```mysql
|
||||||
CREATE DATABASE cerebrate_test;
|
CREATE DATABASE cerebrate_test;
|
||||||
|
@ -55,3 +55,14 @@ By default the database is re-generated before running the test suite, to skip t
|
||||||
```
|
```
|
||||||
$ vendor/bin/phpunit -d skip-migrations
|
$ vendor/bin/phpunit -d skip-migrations
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Coverage
|
||||||
|
HTML:
|
||||||
|
```
|
||||||
|
$ vendor/bin/phpunit --coverage-html tmp/coverage
|
||||||
|
```
|
||||||
|
|
||||||
|
XML:
|
||||||
|
```
|
||||||
|
$ vendor/bin/phpunit --verbose --coverage-clover=coverage.xml
|
||||||
|
```
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
<?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\Helper\ApiTestTrait;
|
|
||||||
|
|
||||||
class UsersApiTest extends TestCase
|
|
||||||
{
|
|
||||||
use IntegrationTestTrait;
|
|
||||||
use ApiTestTrait;
|
|
||||||
|
|
||||||
protected const ENDPOINT = '/api/v1/users/view';
|
|
||||||
|
|
||||||
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 testViewMe(): 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testViewById(): void
|
|
||||||
{
|
|
||||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
|
||||||
$url = sprintf('%s/%d', self::ENDPOINT, UsersFixture::USER_ADMIN_ID);
|
|
||||||
$this->get($url);
|
|
||||||
|
|
||||||
$this->assertResponseOk();
|
|
||||||
$this->assertResponseContains(sprintf('"username": "%s"', UsersFixture::USER_ADMIN_USERNAME));
|
|
||||||
// TODO: $this->validateRequest()
|
|
||||||
$this->validateResponse($url);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,9 +11,25 @@ servers:
|
||||||
|
|
||||||
tags:
|
tags:
|
||||||
- name: Users
|
- name: Users
|
||||||
description: "TODO: users resource descriptions"
|
description: "Users enrolled in this Cerebrate instance."
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
|
/api/v1/users/index:
|
||||||
|
get:
|
||||||
|
summary: "Get users list"
|
||||||
|
operationId: getUsers
|
||||||
|
tags:
|
||||||
|
- Users
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
$ref: "#/components/responses/GetUsersResponse"
|
||||||
|
"403":
|
||||||
|
$ref: "#/components/responses/UnauthorizedApiErrorResponse"
|
||||||
|
"405":
|
||||||
|
$ref: "#/components/responses/MethodNotAllowedApiErrorResponse"
|
||||||
|
default:
|
||||||
|
$ref: "#/components/responses/ApiErrorResponse"
|
||||||
|
|
||||||
/api/v1/users/view:
|
/api/v1/users/view:
|
||||||
get:
|
get:
|
||||||
summary: "Get information about the current user"
|
summary: "Get information about the current user"
|
||||||
|
@ -22,7 +38,7 @@ paths:
|
||||||
- Users
|
- Users
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
$ref: "#/components/responses/ViewUserResponse"
|
$ref: "#/components/responses/GetUserResponse"
|
||||||
"403":
|
"403":
|
||||||
$ref: "#/components/responses/UnauthorizedApiErrorResponse"
|
$ref: "#/components/responses/UnauthorizedApiErrorResponse"
|
||||||
default:
|
default:
|
||||||
|
@ -38,7 +54,7 @@ paths:
|
||||||
- $ref: "#/components/parameters/userId"
|
- $ref: "#/components/parameters/userId"
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
$ref: "#/components/responses/ViewUserResponse"
|
$ref: "#/components/responses/GetUserResponse"
|
||||||
"403":
|
"403":
|
||||||
$ref: "#/components/responses/UnauthorizedApiErrorResponse"
|
$ref: "#/components/responses/UnauthorizedApiErrorResponse"
|
||||||
default:
|
default:
|
||||||
|
@ -90,6 +106,11 @@ components:
|
||||||
organisation_id:
|
organisation_id:
|
||||||
$ref: "#/components/schemas/ID"
|
$ref: "#/components/schemas/ID"
|
||||||
|
|
||||||
|
UserList:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/User"
|
||||||
|
|
||||||
# Individuals
|
# Individuals
|
||||||
|
|
||||||
# Organisations
|
# Organisations
|
||||||
|
@ -120,51 +141,69 @@ components:
|
||||||
ApiError:
|
ApiError:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- name
|
|
||||||
- message
|
- message
|
||||||
- url
|
- url
|
||||||
|
- code
|
||||||
properties:
|
properties:
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
example: "/users"
|
example: "/api/v1/users"
|
||||||
|
code:
|
||||||
|
type: integer
|
||||||
|
example: 500
|
||||||
|
|
||||||
UnauthorizedApiError:
|
UnauthorizedApiError:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- name
|
|
||||||
- message
|
- message
|
||||||
- url
|
- url
|
||||||
|
- code
|
||||||
properties:
|
properties:
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
example: "Authentication failed. Please make sure you pass the API key of an API enabled user along in the Authorization header."
|
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
example: "Authentication failed. Please make sure you pass the API key of an API enabled user along in the Authorization header."
|
example: "Authentication failed. Please make sure you pass the API key of an API enabled user along in the Authorization header."
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
example: "/users"
|
example: "/api/v1/users"
|
||||||
|
code:
|
||||||
|
type: integer
|
||||||
|
example: 403
|
||||||
|
|
||||||
|
MethodNotAllowedApiError:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- message
|
||||||
|
- url
|
||||||
|
- code
|
||||||
|
properties:
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
example: "You do not have permission to use this functionality."
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
example: "/api/v1/users/index"
|
||||||
|
code:
|
||||||
|
type: integer
|
||||||
|
example: 405
|
||||||
|
|
||||||
NotFoundApiError:
|
NotFoundApiError:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- name
|
|
||||||
- message
|
- message
|
||||||
- url
|
- url
|
||||||
|
- code
|
||||||
properties:
|
properties:
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
example: "Invalid user"
|
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
example: "Invalid user"
|
example: "Invalid user"
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
example: "/users/1234"
|
example: "/api/v1/users/users/view/1234"
|
||||||
|
code:
|
||||||
|
type: integer
|
||||||
|
example: 404
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
userId:
|
userId:
|
||||||
|
@ -189,13 +228,20 @@ components:
|
||||||
|
|
||||||
responses:
|
responses:
|
||||||
# User
|
# User
|
||||||
ViewUserResponse:
|
GetUserResponse:
|
||||||
description: "User response"
|
description: "User response"
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/User"
|
$ref: "#/components/schemas/User"
|
||||||
|
|
||||||
|
GetUsersResponse:
|
||||||
|
description: "User response"
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/UserList"
|
||||||
|
|
||||||
# Errors
|
# Errors
|
||||||
ApiErrorResponse:
|
ApiErrorResponse:
|
||||||
description: "Unexpected API error"
|
description: "Unexpected API error"
|
||||||
|
@ -211,5 +257,12 @@ components:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/UnauthorizedApiError"
|
$ref: "#/components/schemas/UnauthorizedApiError"
|
||||||
|
|
||||||
|
MethodNotAllowedApiErrorResponse:
|
||||||
|
description: "Method not allowed. Your User Role is not allowed to access this resource."
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/MethodNotAllowedApiError"
|
||||||
|
|
||||||
security:
|
security:
|
||||||
- ApiKeyAuth: []
|
- ApiKeyAuth: []
|
||||||
|
|
Loading…
Reference in New Issue