API improvements (#1826)
This commit is contained in:
@@ -12,6 +12,7 @@ namespace App\Tests\API;
|
||||
use App\DataFixtures\UserFixtures;
|
||||
use App\Entity\User;
|
||||
use App\Tests\Controller\ControllerBaseTest;
|
||||
use PHPUnit\Framework\Constraint\IsType;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelBrowser;
|
||||
@@ -240,7 +241,7 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
|
||||
/**
|
||||
* @param Response $response
|
||||
* @param string[] $failedFields
|
||||
* @param bool $extraFields
|
||||
* @param bool $extraFields test for the error "This form should not contain extra fields"
|
||||
*/
|
||||
protected function assertApiCallValidationError(Response $response, array $failedFields, bool $extraFields = false)
|
||||
{
|
||||
@@ -258,8 +259,366 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
|
||||
$data = $result['errors']['children'];
|
||||
|
||||
foreach ($failedFields as $fieldName) {
|
||||
self::assertArrayHasKey($fieldName, $data);
|
||||
self::assertArrayHasKey('errors', $data[$fieldName]);
|
||||
self::assertArrayHasKey($fieldName, $data, sprintf('Could not find validation error for field: %s', $fieldName));
|
||||
self::assertArrayHasKey('errors', $data[$fieldName], sprintf('Field %s has no validation problem', $fieldName));
|
||||
}
|
||||
|
||||
$foundErrors = [];
|
||||
foreach ($data as $fieldName => $field) {
|
||||
if (\array_key_exists('errors', $field) && \count($field['errors']) > 0) {
|
||||
$foundErrors[$fieldName] = \count($field['errors']);
|
||||
}
|
||||
}
|
||||
|
||||
self::assertEquals(\count($failedFields), \count($foundErrors), 'Expected and actual validation error amount differs');
|
||||
}
|
||||
|
||||
protected static function getExpectedResponseStructure(string $type): array
|
||||
{
|
||||
switch ($type) {
|
||||
case 'TagEntity':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'color' => 'string',
|
||||
];
|
||||
|
||||
// embedded meta data
|
||||
case 'CustomerMeta':
|
||||
case 'ProjectMeta':
|
||||
case 'ActivityMeta':
|
||||
case 'TimesheetMeta':
|
||||
return [
|
||||
'name' => 'string',
|
||||
'value' => 'string',
|
||||
];
|
||||
|
||||
// if a user is embedded in other objects
|
||||
case 'User':
|
||||
// if a list of users is loaded
|
||||
case 'UserCollection':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'username' => 'string',
|
||||
'enabled' => 'bool',
|
||||
'alias' => '@string',
|
||||
];
|
||||
|
||||
// if a user is loaded explicitly
|
||||
case 'UserEntity':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'username' => 'string',
|
||||
'enabled' => 'bool',
|
||||
'alias' => '@string',
|
||||
'title' => '@string',
|
||||
'avatar' => '@string',
|
||||
'teams' => ['result' => 'array', 'type' => 'Team'],
|
||||
'roles' => ['result' => 'array', 'type' => 'string'],
|
||||
'language' => 'string',
|
||||
'timezone' => 'string',
|
||||
];
|
||||
|
||||
// if a team is embedded
|
||||
case 'Team':
|
||||
// if a collection of teams is requested
|
||||
case 'TeamCollection':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
];
|
||||
|
||||
// explicitly requested team
|
||||
case 'TeamEntity':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'teamlead' => ['result' => 'object', 'type' => 'User'],
|
||||
'users' => ['result' => 'array', 'type' => 'User'],
|
||||
'customers' => ['result' => 'array', 'type' => '@Customer'],
|
||||
'projects' => ['result' => 'array', 'type' => '@Project'],
|
||||
];
|
||||
|
||||
// if a customer is embedded in other objects
|
||||
case 'Customer':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'visible' => 'bool',
|
||||
'color' => '@string',
|
||||
];
|
||||
|
||||
// if a list of customers is loaded
|
||||
case 'CustomerCollection':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'visible' => 'boolean',
|
||||
'color' => '@string',
|
||||
'metaFields' => ['result' => 'array', 'type' => 'CustomerMeta'],
|
||||
'teams' => ['result' => 'array', 'type' => 'Team'],
|
||||
'currency' => 'string', // since 1.10
|
||||
];
|
||||
|
||||
// if a customer is loaded explicitly
|
||||
case 'CustomerEntity':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'visible' => 'bool',
|
||||
'color' => '@string',
|
||||
'metaFields' => ['result' => 'array', 'type' => 'CustomerMeta'],
|
||||
'teams' => ['result' => 'array', 'type' => 'Team'],
|
||||
'homepage' => '@string',
|
||||
'number' => '@string',
|
||||
'comment' => '@string',
|
||||
'company' => '@string',
|
||||
'contact' => '@string',
|
||||
'address' => '@string',
|
||||
'country' => 'string',
|
||||
'currency' => 'string',
|
||||
'phone' => '@string',
|
||||
'fax' => '@string',
|
||||
'mobile' => '@string',
|
||||
'email' => '@string',
|
||||
'timezone' => 'string',
|
||||
'budget' => 'float',
|
||||
'timeBudget' => 'int',
|
||||
'vatId' => '@string', // since 1.10
|
||||
];
|
||||
|
||||
// if a project is embedded
|
||||
case 'Project':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'visible' => 'bool',
|
||||
'color' => '@string',
|
||||
'customer' => 'int',
|
||||
];
|
||||
|
||||
// if a project is embedded in an expanded collection (here timesheet)
|
||||
case 'ProjectExpanded':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'visible' => 'bool',
|
||||
'color' => '@string',
|
||||
'customer' => ['result' => 'object', 'type' => 'Customer'],
|
||||
];
|
||||
|
||||
// if a collection of projects is loaded
|
||||
case 'ProjectCollection':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'visible' => 'bool',
|
||||
'customer' => 'int',
|
||||
'color' => '@string',
|
||||
'metaFields' => ['result' => 'array', 'type' => 'ProjectMeta'],
|
||||
'parentTitle' => 'string',
|
||||
'start' => '@datetime',
|
||||
'end' => '@datetime',
|
||||
'teams' => ['result' => 'array', 'type' => 'Team'],
|
||||
];
|
||||
|
||||
// if a project is explicitly loaded
|
||||
case 'ProjectEntity':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'visible' => 'bool',
|
||||
'customer' => 'int',
|
||||
'color' => '@string',
|
||||
'metaFields' => ['result' => 'array', 'type' => 'ProjectMeta'],
|
||||
'parentTitle' => 'string',
|
||||
'start' => '@datetime',
|
||||
'end' => '@datetime',
|
||||
'teams' => ['result' => 'array', 'type' => 'Team'],
|
||||
'comment' => '@string',
|
||||
'budget' => 'float',
|
||||
'timeBudget' => 'int',
|
||||
'orderNumber' => '@string',
|
||||
'orderDate' => '@datetime',
|
||||
];
|
||||
|
||||
// embedded activities
|
||||
case 'Activity':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'visible' => 'bool',
|
||||
'project' => '@int',
|
||||
'color' => '@string',
|
||||
];
|
||||
|
||||
// collection of activities
|
||||
case 'ActivityCollection':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'visible' => 'bool',
|
||||
'project' => '@int',
|
||||
'color' => '@string',
|
||||
'metaFields' => ['result' => 'array', 'type' => 'ProjectMeta'],
|
||||
'parentTitle' => '@string',
|
||||
];
|
||||
|
||||
// if a activity is explicitly loaded
|
||||
case 'ActivityEntity':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'name' => 'string',
|
||||
'visible' => 'bool',
|
||||
'project' => '@int',
|
||||
'color' => '@string',
|
||||
'metaFields' => ['result' => 'array', 'type' => 'ProjectMeta'],
|
||||
'parentTitle' => '@string',
|
||||
'comment' => '@string',
|
||||
'budget' => 'float',
|
||||
'timeBudget' => 'int',
|
||||
];
|
||||
|
||||
case 'TimesheetEntity':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'begin' => 'DateTime',
|
||||
'end' => '@DateTime',
|
||||
'duration' => '@int',
|
||||
'description' => '@string',
|
||||
'rate' => 'float',
|
||||
'activity' => 'int',
|
||||
'project' => 'int',
|
||||
'tags' => ['result' => 'array', 'type' => 'string'],
|
||||
'user' => 'int',
|
||||
'metaFields' => ['result' => 'array', 'type' => 'TimesheetMeta'],
|
||||
'internalRate' => 'float',
|
||||
'exported' => 'bool',
|
||||
'fixedRate' => '@float',
|
||||
'hourlyRate' => '@float',
|
||||
// TODO new fields: billable, category
|
||||
];
|
||||
|
||||
case 'TimesheetCollection':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'begin' => 'DateTime',
|
||||
'end' => '@DateTime',
|
||||
'duration' => '@int',
|
||||
'description' => '@string',
|
||||
'rate' => 'float',
|
||||
'activity' => 'int',
|
||||
'project' => 'int',
|
||||
'tags' => ['result' => 'array', 'type' => 'string'],
|
||||
'user' => 'int',
|
||||
'metaFields' => ['result' => 'array', 'type' => 'TimesheetMeta'],
|
||||
'internalRate' => 'float',
|
||||
];
|
||||
|
||||
case 'TimesheetCollectionFull':
|
||||
return [
|
||||
'id' => 'int',
|
||||
'begin' => 'DateTime',
|
||||
'end' => '@DateTime',
|
||||
'duration' => '@int',
|
||||
'description' => '@string',
|
||||
'rate' => 'float',
|
||||
'activity' => ['result' => 'object', 'type' => 'Activity'],
|
||||
'project' => ['result' => 'object', 'type' => 'ProjectExpanded'],
|
||||
'tags' => ['result' => 'array', 'type' => 'string'],
|
||||
'user' => 'int',
|
||||
'metaFields' => ['result' => 'array', 'type' => 'TimesheetMeta'],
|
||||
'internalRate' => 'float',
|
||||
];
|
||||
|
||||
default:
|
||||
throw new \Exception(sprintf('Unknown API response type: %s', $type));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The $type is either one of the types configured in config/packages/nelmio_api_doc.yaml or the class name.
|
||||
*
|
||||
* @param string $type
|
||||
* @param array $result
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function assertApiResponseTypeStructure(string $type, array $result)
|
||||
{
|
||||
$expected = self::getExpectedResponseStructure($type);
|
||||
$expectedKeys = array_keys($expected);
|
||||
|
||||
$actual = array_keys($result);
|
||||
sort($actual);
|
||||
sort($expectedKeys);
|
||||
|
||||
self::assertEquals($expectedKeys, $actual, sprintf('Structure for API response type "%s" does not match', $type));
|
||||
|
||||
self::assertEquals(
|
||||
\count($actual),
|
||||
\count($expectedKeys),
|
||||
sprintf('Mismatch between expected and result keys for API response type "%s". Expected %s keys but found %s.', $type, \count($expected), \count($actual))
|
||||
);
|
||||
|
||||
foreach ($expected as $key => $value) {
|
||||
if (\is_array($value)) {
|
||||
switch ($value['result']) {
|
||||
case 'array':
|
||||
foreach ($result[$key] as $subResult) {
|
||||
if ($value['type'] === 'string') {
|
||||
self::assertIsString($subResult);
|
||||
} else {
|
||||
self::assertIsArray($subResult);
|
||||
|
||||
if ($value['type'][0] === '@') {
|
||||
if (empty($result[$key])) {
|
||||
continue;
|
||||
}
|
||||
$value['type'] = substr($value['type'], 1);
|
||||
}
|
||||
|
||||
self::assertApiResponseTypeStructure($value['type'], $subResult);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
self::assertIsArray($result[$key], sprintf('Key "%s" in type "%s" is not an array', $key, $type));
|
||||
|
||||
if ($value['type'][0] === '@') {
|
||||
if (empty($result[$key])) {
|
||||
break;
|
||||
}
|
||||
$value['type'] = substr($value['type'], 1);
|
||||
}
|
||||
|
||||
self::assertApiResponseTypeStructure($value['type'], $result[$key]);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \Exception(sprintf('Invalid result type "%s" for subresource given', $value['result']));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($value[0] === '@') {
|
||||
if (\is_null($result[$key])) {
|
||||
continue;
|
||||
}
|
||||
$value = substr($value, 1);
|
||||
}
|
||||
|
||||
if (strtolower($value) === 'datetime') {
|
||||
// TODO
|
||||
$value = 'string';
|
||||
}
|
||||
|
||||
static::assertThat(
|
||||
$result[$key],
|
||||
new IsType($value),
|
||||
sprintf('Found type mismatch in structure for API response type %s. Expected type "%s" for key "%s".', $type, $value, $key)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace App\Tests\API;
|
||||
|
||||
use App\DataFixtures\UserFixtures;
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\ActivityMeta;
|
||||
use App\Entity\ActivityRate;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
@@ -103,6 +104,12 @@ class ActivityControllerTest extends APIControllerBaseTest
|
||||
$em->persist($activity);
|
||||
|
||||
$activity = (new Activity())->setName('fifth one')->setComment('5')->setProject($project2);
|
||||
$meta = new ActivityMeta();
|
||||
$meta->setName('bar')->setValue('foo')->setIsVisible(false);
|
||||
$activity->setMetaField($meta);
|
||||
$meta = new ActivityMeta();
|
||||
$meta->setName('foo')->setValue('bar')->setIsVisible(true);
|
||||
$activity->setMetaField($meta);
|
||||
$em->persist($activity);
|
||||
|
||||
$activity = (new Activity())->setName('sixth one')->setComment('6')->setVisible(false);
|
||||
@@ -127,7 +134,7 @@ class ActivityControllerTest extends APIControllerBaseTest
|
||||
for ($i = 0; $i < \count($result); $i++) {
|
||||
$activity = $result[$i];
|
||||
$hasProject = $expected[$i][0];
|
||||
$this->assertStructure($activity, false);
|
||||
self::assertApiResponseTypeStructure('ActivityCollection', $activity);
|
||||
if ($hasProject) {
|
||||
$this->assertEquals($expected[$i][1], $activity['project']);
|
||||
}
|
||||
@@ -161,7 +168,7 @@ class ActivityControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(5, \count($result));
|
||||
$this->assertStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('ActivityCollection', $result[0]);
|
||||
$this->assertEquals(1, $result[4]['project']);
|
||||
$this->assertEquals(2, $result[3]['project']);
|
||||
$this->assertEquals(2, $result[2]['project']);
|
||||
@@ -174,7 +181,7 @@ class ActivityControllerTest extends APIControllerBaseTest
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result, true);
|
||||
self::assertApiResponseTypeStructure('ActivityEntity', $result);
|
||||
}
|
||||
|
||||
public function testNotFound()
|
||||
@@ -197,7 +204,7 @@ class ActivityControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('ActivityEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
}
|
||||
|
||||
@@ -212,7 +219,7 @@ class ActivityControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('ActivityEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
}
|
||||
|
||||
@@ -262,7 +269,7 @@ class ActivityControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('ActivityEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
}
|
||||
|
||||
@@ -351,23 +358,4 @@ class ActivityControllerTest extends APIControllerBaseTest
|
||||
$activity = $em->getRepository(Activity::class)->find(1);
|
||||
$this->assertEquals('another,testing,bar', $activity->getMetaField('metatestmock')->getValue());
|
||||
}
|
||||
|
||||
protected function assertStructure(array $result, $full = true)
|
||||
{
|
||||
$expectedKeys = [
|
||||
'id', 'name', 'visible', 'project', 'color', 'metaFields', 'parentTitle'
|
||||
];
|
||||
|
||||
if ($full) {
|
||||
$expectedKeys = array_merge($expectedKeys, [
|
||||
'comment', 'budget', 'timeBudget'
|
||||
]);
|
||||
}
|
||||
|
||||
$actual = array_keys($result);
|
||||
sort($actual);
|
||||
sort($expectedKeys);
|
||||
|
||||
$this->assertEquals($expectedKeys, $actual, 'Activity structure does not match');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,24 @@ class ApiDocControllerTest extends ControllerBaseTest
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$this->assertAccessIsGranted($client, '/api/doc');
|
||||
$this->assertStringContainsString('<title>Kimai 2 - API Docs</title>', $client->getResponse()->getContent());
|
||||
$result = $client->getCrawler()->filter('script#swagger-data');
|
||||
$swaggerJson = json_decode($result->text(), true);
|
||||
$tags = [];
|
||||
foreach ($swaggerJson['spec']['paths'] as $path) {
|
||||
foreach ($path as $method) {
|
||||
foreach ($method['tags'] as $tag) {
|
||||
$tags[$tag] = $tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$expectedKeys = ['Activity', 'Default', 'Customer', 'Project', 'Tag', 'Team', 'Timesheet', 'User'];
|
||||
$actual = array_keys($tags);
|
||||
|
||||
sort($actual);
|
||||
sort($expectedKeys);
|
||||
|
||||
self::assertEquals($expectedKeys, $actual, sprintf('Expected %s sections in API docs, but found %s.', \count($actual), \count($expectedKeys)));
|
||||
}
|
||||
|
||||
public function testGetJsonDocs()
|
||||
|
||||
@@ -10,8 +10,12 @@
|
||||
namespace App\Tests\API;
|
||||
|
||||
use App\DataFixtures\UserFixtures;
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\CustomerMeta;
|
||||
use App\Entity\CustomerRate;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Repository\CustomerRateRepository;
|
||||
use App\Repository\CustomerRepository;
|
||||
@@ -84,12 +88,12 @@ class CustomerControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(1, \count($result));
|
||||
$this->assertStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('CustomerCollection', $result[0]);
|
||||
}
|
||||
|
||||
public function testGetCollectionWithQuery()
|
||||
{
|
||||
$query = ['order' => 'ASC', 'orderBy' => 'name', 'visible' => 3];
|
||||
$query = ['order' => 'ASC', 'orderBy' => 'name', 'visible' => 3, 'term' => 'test'];
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$this->assertAccessIsGranted($client, '/api/customers', 'GET', $query);
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
@@ -97,7 +101,7 @@ class CustomerControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(1, \count($result));
|
||||
$this->assertStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('CustomerCollection', $result[0]);
|
||||
}
|
||||
|
||||
public function testGetEntity()
|
||||
@@ -107,7 +111,51 @@ class CustomerControllerTest extends APIControllerBaseTest
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result, true);
|
||||
self::assertApiResponseTypeStructure('CustomerEntity', $result);
|
||||
}
|
||||
|
||||
public function testGetEntityWithFullResponse()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
/** @var Customer $customer */
|
||||
$customer = $em->getRepository(Customer::class)->find(1);
|
||||
|
||||
// add meta fields
|
||||
$meta = new CustomerMeta();
|
||||
$meta->setName('bar')->setValue('foo')->setIsVisible(false);
|
||||
$customer->setMetaField($meta);
|
||||
$meta = new CustomerMeta();
|
||||
$meta->setName('foo')->setValue('bar')->setIsVisible(true);
|
||||
$customer->setMetaField($meta);
|
||||
$em->persist($customer);
|
||||
|
||||
// add a new project ...
|
||||
$project = new Project();
|
||||
$project->setName('Activity Test');
|
||||
$project->setCustomer($customer);
|
||||
$em->persist($project);
|
||||
|
||||
// ... with activity
|
||||
$activity = (new Activity())->setName('first one')->setComment('1')->setProject($project);
|
||||
$em->persist($activity);
|
||||
|
||||
// and finally a team
|
||||
$team = new Team();
|
||||
$team->setName('Testing customer 1 team');
|
||||
$team->setTeamLead($this->getUserByRole(User::ROLE_USER));
|
||||
$team->addCustomer($customer);
|
||||
$team->addProject($project);
|
||||
$team->addUser($this->getUserByRole(User::ROLE_TEAMLEAD));
|
||||
$em->persist($team);
|
||||
|
||||
$this->assertAccessIsGranted($client, '/api/customers/1');
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
self::assertApiResponseTypeStructure('CustomerEntity', $result);
|
||||
}
|
||||
|
||||
public function testNotFound()
|
||||
@@ -132,7 +180,7 @@ class CustomerControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('CustomerEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
}
|
||||
|
||||
@@ -150,7 +198,7 @@ class CustomerControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('CustomerEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
}
|
||||
|
||||
@@ -206,7 +254,7 @@ class CustomerControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('CustomerEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
}
|
||||
|
||||
@@ -252,6 +300,13 @@ class CustomerControllerTest extends APIControllerBaseTest
|
||||
$this->assertApiCallValidationError($response, ['currency']);
|
||||
}
|
||||
|
||||
public function testMetaActionNotAllowed()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$this->request($client, '/api/customers/1/meta', 'PATCH', [], json_encode(['name' => 'asdasd']));
|
||||
$this->assertApiResponseAccessDenied($client->getResponse(), 'You are not allowed to update this customer');
|
||||
}
|
||||
|
||||
public function testMetaActionThrowsNotFound()
|
||||
{
|
||||
$this->assertEntityNotFoundForPatch(User::ROLE_ADMIN, '/api/customers/42/meta', []);
|
||||
@@ -299,24 +354,4 @@ class CustomerControllerTest extends APIControllerBaseTest
|
||||
$customer = $em->getRepository(Customer::class)->find(1);
|
||||
$this->assertEquals('another,testing,bar', $customer->getMetaField('metatestmock')->getValue());
|
||||
}
|
||||
|
||||
protected function assertStructure(array $result, $full = true)
|
||||
{
|
||||
$expectedKeys = [
|
||||
'id', 'name', 'visible', 'color', 'metaFields', 'teams'
|
||||
];
|
||||
|
||||
if ($full) {
|
||||
$expectedKeys = array_merge($expectedKeys, [
|
||||
'homepage', 'number', 'comment', 'company', 'contact', 'address', 'country', 'currency',
|
||||
'phone', 'fax', 'mobile', 'email', 'timezone', 'budget', 'timeBudget'
|
||||
]);
|
||||
}
|
||||
|
||||
$actual = array_keys($result);
|
||||
sort($actual);
|
||||
sort($expectedKeys);
|
||||
|
||||
$this->assertEquals($expectedKeys, $actual, 'Customer structure does not match');
|
||||
}
|
||||
}
|
||||
|
||||
32
tests/API/Model/I18nConfigTest.php
Normal file
32
tests/API/Model/I18nConfigTest.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\API\Model;
|
||||
|
||||
use App\API\Model\I18nConfig;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\API\Model\I18nConfig
|
||||
*/
|
||||
class I18nConfigTest extends TestCase
|
||||
{
|
||||
public function testSetter()
|
||||
{
|
||||
$sut = new I18nConfig();
|
||||
|
||||
$this->assertInstanceOf(I18nConfig::class, $sut->setIs24hours(false));
|
||||
$this->assertInstanceOf(I18nConfig::class, $sut->setDuration('foo'));
|
||||
$this->assertInstanceOf(I18nConfig::class, $sut->setDate('bar'));
|
||||
$this->assertInstanceOf(I18nConfig::class, $sut->setDateTime('hello'));
|
||||
$this->assertInstanceOf(I18nConfig::class, $sut->setFormDate('world'));
|
||||
$this->assertInstanceOf(I18nConfig::class, $sut->setFormDateTime('testing'));
|
||||
$this->assertInstanceOf(I18nConfig::class, $sut->setTime('fun'));
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\API\Model;
|
||||
|
||||
use App\API\Model\I18n;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\API\Model\I18n
|
||||
*/
|
||||
class I18nTest extends TestCase
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$sut = new I18n();
|
||||
$this->assertTrue($sut->isIs24hours());
|
||||
$this->assertEquals('', $sut->getDuration());
|
||||
$this->assertEquals('', $sut->getDate());
|
||||
$this->assertEquals('', $sut->getDateTime());
|
||||
$this->assertEquals('', $sut->getFormDate());
|
||||
$this->assertEquals('', $sut->getFormDateTime());
|
||||
$this->assertEquals('', $sut->getTime());
|
||||
}
|
||||
|
||||
public function testSetter()
|
||||
{
|
||||
$sut = new I18n();
|
||||
|
||||
$this->assertInstanceOf(I18n::class, $sut->setIs24hours(false));
|
||||
$this->assertInstanceOf(I18n::class, $sut->setDuration('foo'));
|
||||
$this->assertInstanceOf(I18n::class, $sut->setDate('bar'));
|
||||
$this->assertInstanceOf(I18n::class, $sut->setDateTime('hello'));
|
||||
$this->assertInstanceOf(I18n::class, $sut->setFormDate('world'));
|
||||
$this->assertInstanceOf(I18n::class, $sut->setFormDateTime('testing'));
|
||||
$this->assertInstanceOf(I18n::class, $sut->setTime('fun'));
|
||||
|
||||
$this->assertFalse($sut->isIs24hours());
|
||||
$this->assertEquals('foo', $sut->getDuration());
|
||||
$this->assertEquals('bar', $sut->getDate());
|
||||
$this->assertEquals('hello', $sut->getDateTime());
|
||||
$this->assertEquals('world', $sut->getFormDate());
|
||||
$this->assertEquals('testing', $sut->getFormDateTime());
|
||||
$this->assertEquals('fun', $sut->getTime());
|
||||
}
|
||||
}
|
||||
@@ -17,17 +17,6 @@ use PHPUnit\Framework\TestCase;
|
||||
*/
|
||||
class TimesheetConfigTest extends TestCase
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$sut = new TimesheetConfig();
|
||||
$this->assertTrue($sut->isAllowFutureTimes());
|
||||
$this->assertTrue($sut->isAllowOverlapping());
|
||||
$this->assertEquals('now', $sut->getDefaultBeginTime());
|
||||
$this->assertEquals('default', $sut->getTrackingMode());
|
||||
$this->assertEquals(1, $sut->getActiveEntriesSoftLimit());
|
||||
$this->assertEquals(1, $sut->getActiveEntriesHardLimit());
|
||||
}
|
||||
|
||||
public function testSetter()
|
||||
{
|
||||
$sut = new TimesheetConfig();
|
||||
@@ -38,12 +27,5 @@ class TimesheetConfigTest extends TestCase
|
||||
$this->assertInstanceOf(TimesheetConfig::class, $sut->setTrackingMode('punch'));
|
||||
$this->assertInstanceOf(TimesheetConfig::class, $sut->setActiveEntriesSoftLimit(2));
|
||||
$this->assertInstanceOf(TimesheetConfig::class, $sut->setActiveEntriesHardLimit(3));
|
||||
|
||||
$this->assertFalse($sut->isAllowFutureTimes());
|
||||
$this->assertFalse($sut->isAllowOverlapping());
|
||||
$this->assertEquals('08:00', $sut->getDefaultBeginTime());
|
||||
$this->assertEquals('punch', $sut->getTrackingMode());
|
||||
$this->assertEquals(2, $sut->getActiveEntriesSoftLimit());
|
||||
$this->assertEquals(3, $sut->getActiveEntriesHardLimit());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@ namespace App\Tests\API;
|
||||
use App\DataFixtures\UserFixtures;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\ProjectMeta;
|
||||
use App\Entity\ProjectRate;
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Repository\ProjectRateRepository;
|
||||
use App\Repository\ProjectRepository;
|
||||
@@ -86,7 +88,7 @@ class ProjectControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(1, \count($result));
|
||||
$this->assertStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('ProjectCollection', $result[0]);
|
||||
}
|
||||
|
||||
protected function loadProjectTestData(HttpKernelBrowser $client)
|
||||
@@ -114,8 +116,25 @@ class ProjectControllerTest extends APIControllerBaseTest
|
||||
$em->persist($project);
|
||||
|
||||
$project = (new Project())->setName('fifth')->setVisible(true)->setCustomer($customer);
|
||||
|
||||
// add meta fields
|
||||
$meta = new ProjectMeta();
|
||||
$meta->setName('bar')->setValue('foo')->setIsVisible(false);
|
||||
$project->setMetaField($meta);
|
||||
$meta = new ProjectMeta();
|
||||
$meta->setName('foo')->setValue('bar')->setIsVisible(true);
|
||||
$project->setMetaField($meta);
|
||||
$em->persist($project);
|
||||
|
||||
// and a team
|
||||
$team = new Team();
|
||||
$team->setName('Testing project team');
|
||||
$team->setTeamLead($this->getUserByRole(User::ROLE_USER));
|
||||
$team->addCustomer($customer);
|
||||
$team->addProject($project);
|
||||
$team->addUser($this->getUserByRole(User::ROLE_TEAMLEAD));
|
||||
$em->persist($team);
|
||||
|
||||
$project = (new Project())->setName('sixth')->setVisible(false)->setCustomer($customer3);
|
||||
$em->persist($project);
|
||||
|
||||
@@ -138,7 +157,7 @@ class ProjectControllerTest extends APIControllerBaseTest
|
||||
for ($i = 0; $i < \count($expected); $i++) {
|
||||
$project = $result[$i];
|
||||
$compare = $expected[$i];
|
||||
$this->assertStructure($project, false);
|
||||
self::assertApiResponseTypeStructure('ProjectCollection', $project);
|
||||
$this->assertEquals($compare[1], $project['customer']);
|
||||
}
|
||||
}
|
||||
@@ -169,7 +188,7 @@ class ProjectControllerTest extends APIControllerBaseTest
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('ProjectEntity', $result);
|
||||
}
|
||||
|
||||
public function testNotFound()
|
||||
@@ -195,7 +214,7 @@ class ProjectControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('ProjectEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
self::assertEquals('2018-02-08T13:02:54+0000', $result['orderDate']);
|
||||
self::assertEquals('2019-02-01T19:32:17+0000', $result['start']);
|
||||
@@ -214,7 +233,7 @@ class ProjectControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('ProjectEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
self::assertEquals('foo', $result['name']);
|
||||
}
|
||||
@@ -265,7 +284,7 @@ class ProjectControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('ProjectEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
}
|
||||
|
||||
@@ -354,23 +373,4 @@ class ProjectControllerTest extends APIControllerBaseTest
|
||||
$project = $em->getRepository(Project::class)->find(1);
|
||||
$this->assertEquals('another,testing,bar', $project->getMetaField('metatestmock')->getValue());
|
||||
}
|
||||
|
||||
protected function assertStructure(array $result, $full = true)
|
||||
{
|
||||
$expectedKeys = [
|
||||
'id', 'name', 'visible', 'customer', 'color', 'metaFields', 'parentTitle', 'start', 'end', 'teams'
|
||||
];
|
||||
|
||||
if ($full) {
|
||||
$expectedKeys = array_merge($expectedKeys, [
|
||||
'comment', 'budget', 'timeBudget', 'orderNumber', 'orderDate'
|
||||
]);
|
||||
}
|
||||
|
||||
$actual = array_keys($result);
|
||||
sort($actual);
|
||||
sort($expectedKeys);
|
||||
|
||||
$this->assertEquals($expectedKeys, $actual, 'Project structure does not match');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,6 +192,15 @@ trait RateControllerTestTrait
|
||||
$this->assertNotFoundForDelete($client, $this->getRateUrl(2, 1));
|
||||
}
|
||||
|
||||
public function testDeleteNotAllowed()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$this->importTestRates(1);
|
||||
|
||||
$this->request($client, $this->getRateUrl(1, 1), 'DELETE');
|
||||
$this->assertApiResponseAccessDenied($client->getResponse(), 'Access denied.');
|
||||
}
|
||||
|
||||
protected function assertRateStructure(array $result, $user = null)
|
||||
{
|
||||
$expectedKeys = [
|
||||
|
||||
@@ -66,14 +66,30 @@ class TagControllerTest extends APIControllerBaseTest
|
||||
$this->importTagFixtures($client);
|
||||
$data = [
|
||||
'name' => 'foo',
|
||||
'color' => '#000FFF'
|
||||
];
|
||||
$this->request($client, '/api/tags', 'POST', [], json_encode($data));
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('TagEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
self::assertEquals('#000FFF', $result['color']);
|
||||
}
|
||||
|
||||
public function testPostActionWithValidationErrors()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$this->importTagFixtures($client);
|
||||
$data = [
|
||||
'name' => '1',
|
||||
'color' => '11231231231',
|
||||
];
|
||||
$this->request($client, '/api/tags', 'POST', [], json_encode($data));
|
||||
$response = $client->getResponse();
|
||||
$this->assertEquals(400, $response->getStatusCode());
|
||||
$this->assertApiCallValidationError($response, ['name', 'color']);
|
||||
}
|
||||
|
||||
public function testPostActionWithInvalidUser()
|
||||
@@ -128,21 +144,4 @@ class TagControllerTest extends APIControllerBaseTest
|
||||
{
|
||||
$this->assertEntityNotFoundForDelete(User::ROLE_ADMIN, '/api/tags/255');
|
||||
}
|
||||
|
||||
protected function assertStructure(array $result, $full = true)
|
||||
{
|
||||
$expectedKeys = [
|
||||
'id', 'name', 'color'
|
||||
];
|
||||
|
||||
if ($full) {
|
||||
$expectedKeys = array_merge($expectedKeys, []);
|
||||
}
|
||||
|
||||
$actual = array_keys($result);
|
||||
sort($actual);
|
||||
sort($expectedKeys);
|
||||
|
||||
$this->assertEquals($expectedKeys, $actual, 'Tag structure does not match');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
self::assertEquals(2, \count($result));
|
||||
$this->assertStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TeamCollection', $result[0]);
|
||||
}
|
||||
|
||||
public function testGetEntity()
|
||||
@@ -70,7 +70,7 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result, true);
|
||||
self::assertApiResponseTypeStructure('TeamEntity', $result);
|
||||
}
|
||||
|
||||
public function testNotFound()
|
||||
@@ -95,7 +95,7 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('TeamEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
}
|
||||
|
||||
@@ -114,6 +114,20 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
self::assertEquals('Access denied.', $json['message']);
|
||||
}
|
||||
|
||||
public function testPostActionWithValidationErrors()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$data = [
|
||||
'name' => '',
|
||||
'teamlead' => 9999,
|
||||
];
|
||||
$this->request($client, '/api/teams', 'POST', [], json_encode($data));
|
||||
|
||||
$response = $client->getResponse();
|
||||
$this->assertEquals(400, $response->getStatusCode());
|
||||
$this->assertApiCallValidationError($response, ['name', 'teamlead']);
|
||||
}
|
||||
|
||||
public function testPatchAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
@@ -135,11 +149,34 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('TeamEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
self::assertCount(4, $result['users']);
|
||||
}
|
||||
|
||||
public function testPatchActionWithValidationErrors()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$data = [
|
||||
'name' => 'foo',
|
||||
'teamlead' => 1,
|
||||
];
|
||||
$this->request($client, '/api/teams', 'POST', [], json_encode($data));
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$data = [
|
||||
'name' => '1',
|
||||
'teamlead' => 9999,
|
||||
'users' => [9999]
|
||||
];
|
||||
$this->request($client, '/api/teams/' . $result['id'], 'PATCH', [], json_encode($data));
|
||||
|
||||
$response = $client->getResponse();
|
||||
$this->assertEquals(400, $response->getStatusCode());
|
||||
$this->assertApiCallValidationError($response, ['name', 'teamlead', 'users']);
|
||||
}
|
||||
|
||||
public function testDeleteAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
@@ -148,7 +185,7 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('TeamEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
$id = $result['id'];
|
||||
|
||||
@@ -175,7 +212,7 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('TeamEntity', $result);
|
||||
self::assertCount(2, $result['users']);
|
||||
}
|
||||
|
||||
@@ -238,7 +275,7 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('TeamEntity', $result);
|
||||
self::assertCount(3, $result['users']);
|
||||
}
|
||||
|
||||
@@ -300,7 +337,7 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('TeamEntity', $result);
|
||||
self::assertCount(1, $result['customers']);
|
||||
self::assertEquals(1, $result['customers'][0]['id']);
|
||||
}
|
||||
@@ -381,7 +418,7 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('TeamEntity', $result);
|
||||
self::assertCount(0, $result['customers']);
|
||||
}
|
||||
|
||||
@@ -427,13 +464,12 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
self::assertCount(0, $result['projects']);
|
||||
|
||||
$this->request($client, '/api/teams/' . $result['id'] . '/projects/1', 'POST');
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('TeamEntity', $result);
|
||||
self::assertCount(1, $result['projects']);
|
||||
self::assertEquals(1, $result['projects'][0]['id']);
|
||||
}
|
||||
@@ -520,7 +556,7 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('TeamEntity', $result);
|
||||
self::assertCount(0, $result['projects']);
|
||||
}
|
||||
|
||||
@@ -554,23 +590,4 @@ class TeamControllerTest extends APIControllerBaseTest
|
||||
$json = json_decode($client->getResponse()->getContent(), true);
|
||||
self::assertEquals('Project is not assigned to the team', $json['message']);
|
||||
}
|
||||
|
||||
protected function assertStructure(array $result, $full = true)
|
||||
{
|
||||
$expectedKeys = [
|
||||
'id', 'name'
|
||||
];
|
||||
|
||||
if ($full) {
|
||||
$expectedKeys = array_merge($expectedKeys, [
|
||||
'teamlead', 'users', 'customers', 'projects'
|
||||
]);
|
||||
}
|
||||
|
||||
$actual = array_keys($result);
|
||||
sort($actual);
|
||||
sort($expectedKeys);
|
||||
|
||||
self::assertEquals($expectedKeys, $actual, 'Team structure does not match');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(10, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]);
|
||||
}
|
||||
|
||||
public function testGetCollectionFull()
|
||||
@@ -72,8 +72,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(10, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
$this->assertHasSubresources($result[0]);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollectionFull', $result[0]);
|
||||
}
|
||||
|
||||
public function testGetCollectionForOtherUser()
|
||||
@@ -99,14 +98,13 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(10, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]);
|
||||
}
|
||||
|
||||
public function testGetCollectionForAllUser()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||||
$this->importFixtureForUser(User::ROLE_USER);
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture
|
||||
@@ -125,7 +123,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(17, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]);
|
||||
}
|
||||
|
||||
public function testGetCollectionForEmptyResult()
|
||||
@@ -170,7 +168,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(5, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]);
|
||||
}
|
||||
|
||||
public function testGetCollectionWithSingleParamsQuery()
|
||||
@@ -202,14 +200,13 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(5, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]);
|
||||
}
|
||||
|
||||
public function testExportedFilter()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$this->importFixtureForUser(User::ROLE_USER);
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture
|
||||
@@ -240,7 +237,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(7, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]);
|
||||
|
||||
$query = [
|
||||
'page' => 1,
|
||||
@@ -256,7 +253,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(10, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]);
|
||||
|
||||
$query = [
|
||||
'page' => 1,
|
||||
@@ -270,7 +267,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(17, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]);
|
||||
}
|
||||
|
||||
public function testGetEntity()
|
||||
@@ -281,7 +278,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertDefaultStructure($result);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
}
|
||||
|
||||
public function testGetEntityAccessDenied()
|
||||
@@ -301,7 +298,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertDefaultStructure($result);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
}
|
||||
|
||||
public function testGetEntityNotFound()
|
||||
@@ -327,7 +324,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertDefaultStructure($result);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
$this->assertTrue($result['duration'] == 57600 || $result['duration'] == 57660); // 1 minute rounding might be applied
|
||||
$this->assertEquals(2016, $result['rate']);
|
||||
@@ -357,7 +354,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertDefaultStructure($result);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
$this->assertEquals($user->getId(), $result['user']);
|
||||
$this->assertNotEquals($admin->getId(), $result['user']);
|
||||
@@ -437,7 +434,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertDefaultStructure($result);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
$this->assertEquals(25200, $result['duration']);
|
||||
$this->assertEquals(1, $result['exported']);
|
||||
@@ -447,7 +444,6 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$this->importFixtureForUser(User::ROLE_USER);
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture
|
||||
@@ -510,7 +506,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertDefaultStructure($result);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
$id = $result['id'];
|
||||
|
||||
@@ -585,10 +581,9 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
}
|
||||
|
||||
public function testGetRecentCollectionWithSubresources()
|
||||
public function testGetRecentAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
$start = new \DateTime('-10 days');
|
||||
|
||||
@@ -614,14 +609,12 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(1, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
$this->assertHasSubresources($result[0]);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollectionFull', $result[0]);
|
||||
}
|
||||
|
||||
public function testActiveAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
$start = new \DateTime('-10 days');
|
||||
|
||||
@@ -642,7 +635,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$results = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertEquals(3, \count($results));
|
||||
foreach ($results as $timesheet) {
|
||||
$this->assertDefaultStructure($timesheet, false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollectionFull', $timesheet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,7 +643,6 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$this->importFixtureForUser(User::ROLE_USER);
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
$start = new \DateTime('-10 days');
|
||||
|
||||
@@ -668,6 +660,11 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->request($client, '/api/timesheets/11/stop', 'PATCH');
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
/** @var Timesheet $timesheet */
|
||||
$timesheet = $em->getRepository(Timesheet::class)->find(1);
|
||||
@@ -692,7 +689,6 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$this->importFixtureForUser(User::ROLE_USER);
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
$start = new \DateTime('-10 days');
|
||||
|
||||
@@ -715,7 +711,6 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$this->importFixtureForUser(User::ROLE_USER);
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture
|
||||
@@ -736,7 +731,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(5, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]);
|
||||
|
||||
$query = ['tags' => 'Test,Admin'];
|
||||
$this->assertAccessIsGranted($client, '/api/timesheets', 'GET', $query);
|
||||
@@ -745,7 +740,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(10, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]);
|
||||
|
||||
$query = ['tags' => 'Nothing-2-see,here'];
|
||||
$this->assertAccessIsGranted($client, '/api/timesheets', 'GET', $query);
|
||||
@@ -754,7 +749,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(20, \count($result));
|
||||
$this->assertDefaultStructure($result[0], false);
|
||||
self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]);
|
||||
}
|
||||
|
||||
public function testRestartAction()
|
||||
@@ -772,7 +767,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertDefaultStructure($result, true);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
$this->assertEmpty($result['description']);
|
||||
$this->assertEmpty($result['tags']);
|
||||
|
||||
@@ -812,7 +807,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertDefaultStructure($result, true);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
$this->assertEquals('foo', $result['description']);
|
||||
$this->assertEquals([['name' => 'sdfsdf', 'value' => 'nnnnn'], ['name' => '1234567890', 'value' => '1234567890']], $result['metaFields']);
|
||||
$this->assertEquals(['another', 'testing', 'bar'], $result['tags']);
|
||||
@@ -832,8 +827,6 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
$start = new \DateTime('-10 days');
|
||||
|
||||
$fixture = new TimesheetFixtures();
|
||||
@@ -874,7 +867,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertDefaultStructure($result);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
$this->assertTrue($result['duration'] == 57600 || $result['duration'] == 57660); // 1 minute rounding might be applied
|
||||
$this->assertEquals(2016, $result['rate']);
|
||||
@@ -884,7 +877,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertDefaultStructure($result);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
$this->assertTrue($result['duration'] == 57600 || $result['duration'] == 57660); // 1 minute rounding might be applied
|
||||
$this->assertEquals(2016, $result['rate']);
|
||||
@@ -907,7 +900,8 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
$this->request($client, '/api/timesheets/1/export', 'PATCH');
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
$this->assertDefaultStructure(json_decode($client->getResponse()->getContent(), true), true);
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
|
||||
$em->clear();
|
||||
/** @var Timesheet $timesheet */
|
||||
@@ -988,46 +982,13 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
|
||||
$this->assertEquals(['name' => 'metatestmock', 'value' => 'another,testing,bar'], $result['metaFields'][0]);
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
/** @var Timesheet $timesheet */
|
||||
$timesheet = $em->getRepository(Timesheet::class)->find(1);
|
||||
$this->assertEquals('another,testing,bar', $timesheet->getMetaField('metatestmock')->getValue());
|
||||
}
|
||||
|
||||
protected function assertDefaultStructure(array $result, $full = true)
|
||||
{
|
||||
$expectedKeys = [
|
||||
'id', 'begin', 'end', 'duration', 'description', 'rate', 'activity', 'project', 'tags', 'user', 'metaFields', 'internalRate'
|
||||
];
|
||||
|
||||
if ($full) {
|
||||
$expectedKeys = array_merge($expectedKeys, [
|
||||
'exported', 'fixedRate', 'hourlyRate'
|
||||
]);
|
||||
}
|
||||
|
||||
$actual = array_keys($result);
|
||||
sort($actual);
|
||||
sort($expectedKeys);
|
||||
|
||||
$this->assertEquals($expectedKeys, $actual, 'Timesheet structure does not match');
|
||||
}
|
||||
|
||||
protected function assertHasSubresources(array $result)
|
||||
{
|
||||
$this->assertArrayHasKey('activity', $result);
|
||||
$this->assertArrayHasKey('id', $result['activity']);
|
||||
$this->assertArrayHasKey('name', $result['activity']);
|
||||
$this->assertArrayHasKey('visible', $result['activity']);
|
||||
$this->assertArrayHasKey('project', $result['activity']);
|
||||
|
||||
$this->assertArrayHasKey('project', $result);
|
||||
$this->assertArrayHasKey('id', $result['project']);
|
||||
$this->assertArrayHasKey('name', $result['project']);
|
||||
$this->assertArrayHasKey('visible', $result['project']);
|
||||
$this->assertArrayHasKey('customer', $result['project']);
|
||||
$this->assertArrayHasKey('id', $result['project']['customer']);
|
||||
$this->assertArrayHasKey('name', $result['project']['customer']);
|
||||
$this->assertArrayHasKey('visible', $result['project']['customer']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,21 +49,21 @@ class UserControllerTest extends APIControllerBaseTest
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(7, \count($result));
|
||||
foreach ($result as $user) {
|
||||
$this->assertStructure($user, false);
|
||||
self::assertApiResponseTypeStructure('UserCollection', $user);
|
||||
}
|
||||
}
|
||||
|
||||
public function testGetCollectionWithQuery()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
|
||||
$this->assertAccessIsGranted($client, '/api/users', 'GET', ['visible' => 2, 'orderBy' => 'email', 'order' => 'DESC']);
|
||||
$this->assertAccessIsGranted($client, '/api/users', 'GET', ['visible' => 2, 'orderBy' => 'email', 'order' => 'DESC', 'term' => 'chris']);
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(1, \count($result));
|
||||
foreach ($result as $user) {
|
||||
$this->assertStructure($user, false);
|
||||
self::assertApiResponseTypeStructure('UserCollection', $user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ class UserControllerTest extends APIControllerBaseTest
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(8, \count($result));
|
||||
foreach ($result as $user) {
|
||||
$this->assertStructure($user, false);
|
||||
self::assertApiResponseTypeStructure('UserCollection', $user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ class UserControllerTest extends APIControllerBaseTest
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('UserEntity', $result);
|
||||
self::assertEquals('1', $result['id']);
|
||||
self::assertEquals('CFO', $result['title']);
|
||||
self::assertEquals('Clara Haynes', $result['alias']);
|
||||
@@ -101,7 +101,7 @@ class UserControllerTest extends APIControllerBaseTest
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('UserEntity', $result);
|
||||
self::assertEquals('6', $result['id']);
|
||||
self::assertEquals('Super Administrator', $result['title']);
|
||||
self::assertEquals('', $result['alias']);
|
||||
@@ -125,7 +125,7 @@ class UserControllerTest extends APIControllerBaseTest
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('UserEntity', $result);
|
||||
}
|
||||
|
||||
public function testPostAction()
|
||||
@@ -150,7 +150,7 @@ class UserControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('UserEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
self::assertEquals('foo', $result['username']);
|
||||
self::assertEquals('test123', $result['avatar']);
|
||||
@@ -161,6 +161,50 @@ class UserControllerTest extends APIControllerBaseTest
|
||||
self::assertEquals(['ROLE_TEAMLEAD', 'ROLE_ADMIN'], $result['roles']);
|
||||
}
|
||||
|
||||
public function testPostActionWithShortPassword()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
|
||||
$data = [
|
||||
'username' => 'foo',
|
||||
'email' => 'foo@example.com',
|
||||
'avatar' => 'test123',
|
||||
'title' => 'asdfghjkl',
|
||||
'plainPassword' => '1234567',
|
||||
'enabled' => true,
|
||||
'language' => 'ru',
|
||||
'timezone' => 'Europe/Paris',
|
||||
'roles' => [
|
||||
'ROLE_TEAMLEAD',
|
||||
'ROLE_ADMIN'
|
||||
],
|
||||
];
|
||||
$this->request($client, '/api/users', 'POST', [], json_encode($data));
|
||||
|
||||
$response = $client->getResponse();
|
||||
$this->assertEquals(400, $response->getStatusCode());
|
||||
$this->assertApiCallValidationError($response, ['plainPassword']);
|
||||
}
|
||||
|
||||
public function testPostActionWithValidationErrors()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
|
||||
$data = [
|
||||
'username' => '',
|
||||
'email' => '',
|
||||
'plainPassword' => '123456',
|
||||
'language' => 'xx',
|
||||
'timezone' => 'XXX/YYY',
|
||||
'roles' => [
|
||||
'ABC',
|
||||
],
|
||||
];
|
||||
$this->request($client, '/api/users', 'POST', [], json_encode($data));
|
||||
|
||||
$response = $client->getResponse();
|
||||
$this->assertEquals(400, $response->getStatusCode());
|
||||
$this->assertApiCallValidationError($response, ['username', 'email', 'plainPassword', 'language', 'timezone', 'roles']);
|
||||
}
|
||||
|
||||
public function testPostActionWithInvalidUser()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
@@ -216,7 +260,7 @@ class UserControllerTest extends APIControllerBaseTest
|
||||
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
self::assertApiResponseTypeStructure('UserEntity', $result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
self::assertEquals('foo', $result['username']);
|
||||
self::assertEquals('test321', $result['avatar']);
|
||||
@@ -227,21 +271,36 @@ class UserControllerTest extends APIControllerBaseTest
|
||||
self::assertEquals(['ROLE_TEAMLEAD'], $result['roles']);
|
||||
}
|
||||
|
||||
protected function assertStructure(array $result, $full = true)
|
||||
public function testPatchActionWithUnknownUser()
|
||||
{
|
||||
$expectedKeys = ['id', 'username', 'enabled', 'alias'];
|
||||
$this->assertEntityNotFoundForPatch(User::ROLE_SUPER_ADMIN, '/api/users/255', []);
|
||||
}
|
||||
|
||||
if ($full) {
|
||||
$expectedKeys = array_merge(
|
||||
$expectedKeys,
|
||||
['title', 'avatar', 'teams', 'roles', 'language', 'timezone']
|
||||
);
|
||||
}
|
||||
public function testPatchActionWithInvalidUser()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$this->request($client, '/api/users/1', 'PATCH', [], json_encode(['avatar' => 'asdasd']));
|
||||
$this->assertApiResponseAccessDenied($client->getResponse(), 'Not allowed to edit user');
|
||||
}
|
||||
|
||||
$actual = array_keys($result);
|
||||
sort($actual);
|
||||
sort($expectedKeys);
|
||||
public function testPatchActionWithValidationErrors()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
|
||||
$data = [
|
||||
'username' => '1', // not existing in form
|
||||
'email' => '',
|
||||
'plainPassword' => '123456', // not existing in form
|
||||
'plainApiToken' => '123456', // not existing in form
|
||||
'language' => 'xx',
|
||||
'timezone' => 'XXX/YYY',
|
||||
'roles' => [
|
||||
'ABC',
|
||||
],
|
||||
];
|
||||
$this->request($client, '/api/users/1', 'PATCH', [], json_encode($data));
|
||||
|
||||
$this->assertEquals($expectedKeys, $actual, 'User structure does not match');
|
||||
$response = $client->getResponse();
|
||||
$this->assertEquals(400, $response->getStatusCode());
|
||||
$this->assertApiCallValidationError($response, ['email', 'language', 'timezone', 'roles'], true);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user