Added test coverage for APITraits.

This commit is contained in:
Abdulmhsen B. A. A.
2024-09-18 19:57:33 +03:00
parent d1b7c80acd
commit e8598c4dcb
5 changed files with 199 additions and 8 deletions

View File

@@ -45,6 +45,30 @@ final class Container
return new self();
}
/**
* Reinitialize the container.
* This method is used to reinitialize the container with a new instance of the base container.
* This is useful when the container needs to be reset and reinitialized with a new base container.
* This method is typically used in unit tests to ensure that the container is in a known state.
*
* @return self The reinitialized container.
*/
public static function reinitialize(): self
{
self::$container = null;
return self::init();
}
/**
* Reset the container.
*
* @return void
*/
public static function reset(): void
{
self::$container = null;
}
/**
* Add a new service to the container.
*

View File

@@ -38,7 +38,7 @@ trait APITraits
$configFile = ConfigFile::open(Config::get('backends_file'), 'yaml', autoCreate: true);
if (null === $configFile->get("{$name}.type", null)) {
throw new RuntimeException(r("Backend '{backend}' doesn't exists.", ['backend' => $name]));
throw new RuntimeException(r("Backend '{backend}' doesn't exists.", ['backend' => $name]), 1000);
}
$default = $configFile->get($name);
@@ -112,17 +112,18 @@ trait APITraits
protected function getBasicClient(string $type, DataUtil $data): iClient
{
if (null === ($class = Config::get("supported.{$type}", null))) {
throw new InvalidArgumentException(r("Unexpected client type '{type}' was given.", ['type' => $type]));
throw new InvalidArgumentException(r("Unexpected client type '{type}' was given.", ['type' => $type]), 2000
);
}
$options = [];
if (null === $data->get('url')) {
throw new InvalidArgumentException('No URL was given.');
throw new InvalidArgumentException('No URL was given.', 2001);
}
if (null === $data->get('token')) {
throw new InvalidArgumentException('No token was given.');
throw new InvalidArgumentException('No token was given.', 2002);
}
if (null !== $data->get('options.' . Options::ADMIN_TOKEN)) {

View File

@@ -155,6 +155,7 @@ class PDOAdapterTest extends TestCase
public function test_getAll_call_without_initialized_container(): void
{
$this->db->setOptions(['class' => null]);
Container::reset();
$this->checkException(
closure: fn() => $this->db->getAll(),
reason: 'When calling getAll without initialized container, an exception should be thrown.',

View File

@@ -6,7 +6,7 @@ test_plex:
uuid: s00000000000000000000000000000000000000p
export:
enabled: true
lastSync: null
lastSync: 1724273445
import:
enabled: true
lastSync: 1724173445
@@ -57,6 +57,4 @@ test_emby:
match:
user: false
uuid: true
options:
MAX_EPISODE_RANGE: 6
IMPORT_METADATA_ONLY: true
options: { }

View File

@@ -0,0 +1,167 @@
<?php
declare(strict_types=1);
namespace Tests\Libs\Traits;
use App\Backends\Common\ClientInterface as iClient;
use App\Backends\Plex\PlexClient;
use App\Libs\Config;
use App\Libs\Container;
use App\Libs\DataUtil;
use App\Libs\Entity\StateInterface as iState;
use App\Libs\Exceptions\InvalidArgumentException;
use App\Libs\Exceptions\RuntimeException;
use App\Libs\Options;
use App\Libs\TestCase;
use App\Libs\Traits\APITraits;
class APITraitsTest extends TestCase
{
public function __construct(?string $name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
Container::init();
Config::init(require __DIR__ . '/../../../config/config.php');
foreach ((array)require __DIR__ . '/../../../config/services.php' as $name => $definition) {
Container::add($name, $definition);
}
Config::save('backends_file', __DIR__ . '/../../Fixtures/test_servers.yaml');
Config::save('api.secure', true);
}
public function test_getClient()
{
$trait = new class() {
use APITraits {
getClient as public;
}
};
$client = $trait->getClient('test_plex');
$this->assertInstanceOf(PlexClient::class, $client, 'getClient() should return a PlexClient instance');
$this->checkException(
closure: fn() => $trait->getClient('test_unknown'),
reason: 'getClient() should throw a RuntimeException when the backend is not found',
exception: RuntimeException::class,
exceptionCode: 1000,
);
}
public function test_getBackends()
{
$trait = new class() {
use APITraits {
getBackends as public;
}
};
$data = $trait->getBackends();
$this->assertCount(3, $data, 'getBackends() should return an array with 2 elements');
$data = $trait->getBackends('test_plex');
$this->assertCount(1, $data, 'getBackends() When filtering by name, should return an array with 1 element');
}
public function test_getBackend()
{
$trait = new class() {
use APITraits {
getBackend as public;
}
};
$data = $trait->getBackend('test_plex');
$this->assertSame('test_plex', ag($data, 'name'), 'getBackend() should return the backend data.');
$this->assertNull(
$trait->getBackend('not_set'),
'getBackend() should return an empty array when the backend is not found.'
);
}
public function test_formatEntity()
{
$trait = new class() {
use APITraits {
formatEntity as public;
}
};
$entity = $trait->formatEntity(require __DIR__ . '/../../Fixtures/EpisodeEntity.php');
$data = $trait->formatEntity($entity, includeContext: true);
$keys = iState::ENTITY_KEYS;
$keys[] = iState::COLUMN_META_DATA_PROGRESS;
$keys[] = iState::COLUMN_EXTRA_EVENT;
$keys[] = 'content_title';
$keys[] = 'content_path';
$keys[] = 'rguids';
$keys[] = 'reported_by';
$keys[] = 'webUrl';
$keys[] = 'not_reported_by';
$keys[] = 'isTainted';
foreach ($keys as $key) {
$this->assertArrayHasKey($key, $data, 'formatEntity() should return an array with the ' . $key . ' key.');
}
}
public function test_getBasicClient()
{
$trait = new class() {
use APITraits {
getBasicClient as public;
}
};
$data = DataUtil::fromArray([
'type' => 'plex',
'url' => 'http://localhost:32400',
'token' => 'test_token',
'options' => [
Options::ADMIN_TOKEN => 'test_admin_token',
Options::IS_LIMITED_TOKEN => true,
],
]);
$this->checkException(
closure: fn() => $trait->getBasicClient('not_set', $data),
reason: 'getBasicClient() should throw an InvalidArgumentException when the type is not supported.',
exception: InvalidArgumentException::class,
exceptionCode: 2000,
);
$this->checkException(
closure: fn() => $trait->getBasicClient('plex', $data->without('url')),
reason: 'getBasicClient() should throw an InvalidArgumentException when the url is missing.',
exception: InvalidArgumentException::class,
exceptionCode: 2001,
);
$this->checkException(
closure: fn() => $trait->getBasicClient('plex', $data->without('token')),
reason: 'getBasicClient() should throw an InvalidArgumentException when the token is missing.',
exception: InvalidArgumentException::class,
exceptionCode: 2002,
);
$client = $trait->getBasicClient('plex', $data);
$this->assertInstanceOf(iClient::class, $client, 'getBasicClient() should return a client instance.');
$this->assertSame(
$data->get('options.' . Options::ADMIN_TOKEN),
ag($client->getContext()->options, Options::ADMIN_TOKEN),
'Client getContext() should have the admin token registered.',
);
$this->assertSame(
$data->get('options.' . Options::IS_LIMITED_TOKEN),
ag($client->getContext()->options, Options::IS_LIMITED_TOKEN),
'Client getContext() should have the is limited token registered.',
);
$this->assertTrue($client->getContext()->isLimitedToken(), 'Client isLimitedToken() should return true.');
}
}