N°7629 Deprecate utils::GetClassesForInterface in favor of InterfaceDiscovery::FindItopClasses

Improve caching strategy and robustness
This commit is contained in:
Romain Quetiez
2024-07-06 12:08:51 +02:00
parent 147aad9221
commit baf85e7a80
19 changed files with 845 additions and 112 deletions

View File

@@ -501,4 +501,26 @@ abstract class ItopTestCase extends TestCase
}
closedir($dir);
}
/**
* An alternative to assertEquals in case the order of the elements in the array is not important
*
* @since 3.2.0
*/
protected function AssertArraysHaveSameItems(array $aExpectedClasses, array $aClasses, string $sMessage = ''): void
{
sort($aClasses);
sort($aExpectedClasses);
$sExpected = implode("\n", $aExpectedClasses);
$sActual = implode("\n", $aClasses);
if ($sExpected === $sActual) {
$this->assertTrue(true);
return;
}
$sMessage .= "\nExpected:\n$sExpected\nActual:\n$sActual";
var_export($aClasses);
$this->fail($sMessage);
}
}

View File

@@ -6,6 +6,8 @@
namespace Combodo\iTop\Test\UnitTest\Application;
use Combodo\iTop\Application\UI\Base\iUIBlockFactory;
use Combodo\iTop\Service\InterfaceDiscovery\InterfaceDiscovery;
use Combodo\iTop\Test\UnitTest\ItopCustomDatamodelTestCase;
use MetaModel;
use utils;
@@ -26,6 +28,186 @@ class ApplicationExtensionTest extends ItopCustomDatamodelTestCase
return __DIR__ . '/Delta/application-extension-usages-in-snippets.xml';
}
/**
* TODO: remove when the refactoring is done
*/
public function testInterfaceDiscovery(): void
{
$oInterfaceDiscoveryService = InterfaceDiscovery::GetInstance();
$this->AssertArraysHaveSameItems(
[
0 => 'Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory',
1 => 'Combodo\iTop\Application\UI\Base\Component\ButtonGroup\ButtonGroupUIBlockFactory',
2 => 'Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory',
3 => 'Combodo\iTop\Application\UI\Base\Component\CollapsibleSection\CollapsibleSectionUIBlockFactory',
4 => 'Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory',
5 => 'Combodo\iTop\Application\UI\Base\Component\FieldBadge\FieldBadgeUIBlockFactory',
6 => 'Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory',
7 => 'Combodo\iTop\Application\UI\Base\Component\Field\FieldUIBlockFactory',
8 => 'Combodo\iTop\Application\UI\Base\Component\Form\FormUIBlockFactory',
9 => 'Combodo\iTop\Application\UI\Base\Component\Input\FileSelect\FileSelectUIBlockFactory',
10 => 'Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory',
11 => 'Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectOptionUIBlockFactory',
12 => 'Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectUIBlockFactory',
13 => 'Combodo\iTop\Application\UI\Base\Component\Input\Set\SetUIBlockFactory',
14 => 'Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory',
15 => 'Combodo\iTop\Application\UI\Base\Component\Spinner\SpinnerUIBlockFactory',
16 => 'Combodo\iTop\Application\UI\Base\Component\Template\TemplateUIBlockFactory',
17 => 'Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory',
18 => 'Combodo\iTop\Application\UI\Base\Component\Toolbar\Separator\ToolbarSeparatorUIBlockFactory',
19 => 'Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarSpacer\ToolbarSpacerUIBlockFactory',
20 => 'Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory',
21 => 'Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\ColumnUIBlockFactory',
22 => 'Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactory',
23 => 'Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory',
24 => 'Combodo\iTop\Application\UI\Links\Set\LinkSetUIBlockFactory',
],
$oInterfaceDiscoveryService->FindItopClasses(iUIBlockFactory::class)
);
}
/**
* Protection test for Refactoring
* TODO: This test should be removed when the refactoring is done
* @--data--Provider HardcodedImplementationsProvider
*/
public function testGetClassesForInterfaceReturnsExactlySomething()
{
foreach ($this->InterfaceToExpectedClasses() as $sInterface => $aExpectedClasses) {
$aClasses = utils::GetClassesForInterface($sInterface, '', ['[\\\\/]lib[\\\\/]', '[\\\\/]node_modules[\\\\/]', '[\\\\/]test[\\\\/]', '[\\\\/]tests[\\\\/]']);
$this->AssertArraysHaveSameItems($aExpectedClasses, $aClasses, "Found unexpected classes extending the '$sInterface' API");
}
}
public function InterfaceToExpectedClasses(): array
{
return [
\iFieldRendererMappingsExtension::class => [
'ExampleFor_iFieldRendererMappingsExtension',
'Combodo\iTop\Renderer\Bootstrap\BsFieldRendererMappings',
'Combodo\iTop\Renderer\Console\ConsoleFieldRendererMappings',
],
\iNewsroomProvider::class => [
'ExampleFor_iNewsroomProvider',
'HubNewsroomProvider',
'Combodo\iTop\Application\Newsroom\iTopNewsroomProvider',
],
\iBackupExtraFilesExtension::class => [
'ExampleFor_iBackupExtraFilesExtension',
],
\Combodo\iTop\Application\UI\Base\iUIBlockFactory::class => [
0 => 'Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectUIBlockFactory',
2 => 'Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory',
3 => 'Combodo\iTop\Application\UI\Base\Component\ButtonGroup\ButtonGroupUIBlockFactory',
4 => 'Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory',
5 => 'Combodo\iTop\Application\UI\Base\Component\CollapsibleSection\CollapsibleSectionUIBlockFactory',
6 => 'Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory',
7 => 'Combodo\iTop\Application\UI\Base\Component\FieldBadge\FieldBadgeUIBlockFactory',
8 => 'Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory',
9 => 'Combodo\iTop\Application\UI\Base\Component\Field\FieldUIBlockFactory',
10 => 'Combodo\iTop\Application\UI\Base\Component\Form\FormUIBlockFactory',
11 => 'Combodo\iTop\Application\UI\Base\Component\Input\FileSelect\FileSelectUIBlockFactory',
12 => 'Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory',
13 => 'Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectOptionUIBlockFactory',
14 => 'Combodo\iTop\Application\UI\Base\Component\Input\Set\SetUIBlockFactory',
15 => 'Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory',
16 => 'Combodo\iTop\Application\UI\Base\Component\Spinner\SpinnerUIBlockFactory',
17 => 'Combodo\iTop\Application\UI\Base\Component\Template\TemplateUIBlockFactory',
18 => 'Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory',
19 => 'Combodo\iTop\Application\UI\Base\Component\Toolbar\Separator\ToolbarSeparatorUIBlockFactory',
20 => 'Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarSpacer\ToolbarSpacerUIBlockFactory',
21 => 'Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory',
22 => 'Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\ColumnUIBlockFactory',
23 => 'Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactory',
24 => 'Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory',
25 => 'Combodo\iTop\Application\UI\Links\Set\LinkSetUIBlockFactory',
],
\Combodo\iTop\Controller\iController::class => [
0 => 'Combodo\iTop\CoreUpdate\Controller\UpdateController',
1 => 'Combodo\iTop\CoreUpdate\Controller\AjaxController',
2 => 'Combodo\iTop\Controller\Base\Layout\ActivityPanelController',
3 => 'Combodo\iTop\Controller\Base\Layout\ObjectController',
4 => 'Combodo\iTop\Controller\Links\LinkSetController',
5 => 'Combodo\iTop\Controller\Newsroom\iTopNewsroomController',
6 => 'Combodo\iTop\Controller\Notifications\ActionController',
7 => 'Combodo\iTop\Controller\Notifications\NotificationsCenterController',
8 => 'Combodo\iTop\Controller\OAuth\OAuthLandingController',
9 => 'Combodo\iTop\Controller\PreferencesController',
10 => 'Combodo\iTop\Controller\TemporaryObjects\TemporaryObjectController',
11 => 'Combodo\iTop\Controller\WelcomePopupController',
12 => 'Combodo\iTop\OAuthClient\Controller\AjaxOauthClientController',
13 => 'Combodo\iTop\OAuthClient\Controller\OAuthClientController',
],
\Combodo\iTop\Application\UI\Hook\iKeyboardShortcut::class => [
0 => 'Combodo\iTop\Application\UI\Base\Component\GlobalSearch\GlobalSearch',
1 => 'Combodo\iTop\Application\UI\Base\Component\QuickCreate\QuickCreate',
2 => 'Combodo\iTop\Application\UI\Base\Layout\NavigationMenu\NavigationMenu',
3 => 'Combodo\iTop\Application\UI\Base\Layout\Object\ObjectDetails',
4 => 'Combodo\iTop\Application\UI\Base\Layout\Object\ObjectSummary',
],
\Combodo\iTop\Service\Events\iEventServiceSetup::class => [
0 => 'Combodo\iTop\Application\EventRegister\ApplicationEvents',
1 => 'Combodo\iTop\Core\EventListener\AttributeBlobEventListener',
2 => 'Combodo\iTop\Service\TemporaryObjects\TemporaryObjectsEvents',
3 => 'Combodo\iTop\Attachments\Hook\EventListener',
],
\iWelcomePopupExtension::class => [
'Combodo\iTop\Application\WelcomePopup\Provider\DefaultProvider'
],
\iProcess::class => [
0 => 'BackupExec',
1 => 'BulkExportResultGC',
2 => 'CheckStopWatchThresholds',
3 => 'Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomGC',
4 => 'Combodo\iTop\Service\TemporaryObjects\TemporaryObjectGC',
5 => 'Combodo\iTop\SessionTracker\SessionGC',
6 => 'ExecAsyncTask',
7 => 'InlineImageGC',
8 => 'LogFileRotationProcess',
9 => 'ObsolescenceDateUpdater',
]
];
}
/**
* TODO: This test should be removed when the refactoring is done
* Protection of the use case UIBlockExtension::getTokenParsers(), which uses a filter on the class, and does not exclude any directories
*/
public function testVerySpecificCallToGetClassesForInterfaces()
{
$this->AssertArraysHaveSameItems(
[
0 => 'Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory',
1 => 'Combodo\iTop\Application\UI\Base\Component\ButtonGroup\ButtonGroupUIBlockFactory',
2 => 'Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory',
3 => 'Combodo\iTop\Application\UI\Base\Component\CollapsibleSection\CollapsibleSectionUIBlockFactory',
4 => 'Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory',
5 => 'Combodo\iTop\Application\UI\Base\Component\FieldBadge\FieldBadgeUIBlockFactory',
6 => 'Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory',
7 => 'Combodo\iTop\Application\UI\Base\Component\Field\FieldUIBlockFactory',
8 => 'Combodo\iTop\Application\UI\Base\Component\Form\FormUIBlockFactory',
9 => 'Combodo\iTop\Application\UI\Base\Component\Input\FileSelect\FileSelectUIBlockFactory',
10 => 'Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory',
11 => 'Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectOptionUIBlockFactory',
12 => 'Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectUIBlockFactory',
13 => 'Combodo\iTop\Application\UI\Base\Component\Input\Set\SetUIBlockFactory',
14 => 'Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory',
15 => 'Combodo\iTop\Application\UI\Base\Component\Spinner\SpinnerUIBlockFactory',
16 => 'Combodo\iTop\Application\UI\Base\Component\Template\TemplateUIBlockFactory',
17 => 'Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory',
18 => 'Combodo\iTop\Application\UI\Base\Component\Toolbar\Separator\ToolbarSeparatorUIBlockFactory',
19 => 'Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarSpacer\ToolbarSpacerUIBlockFactory',
20 => 'Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory',
21 => 'Combodo\iTop\Application\UI\Base\Layout\MultiColumn\Column\ColumnUIBlockFactory',
22 => 'Combodo\iTop\Application\UI\Base\Layout\MultiColumn\MultiColumnUIBlockFactory',
23 => 'Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory',
24 => 'Combodo\iTop\Application\UI\Links\Set\LinkSetUIBlockFactory',
],
utils::GetClassesForInterface(iUIBlockFactory::class, 'UIBlockFactory')
);
}
/**
* This test ensures that APIs are discovered / registered / called.
*
@@ -44,7 +226,7 @@ class ApplicationExtensionTest extends ItopCustomDatamodelTestCase
if ($sCallMethod === static::ENUM_API_CALL_METHOD_ENUMPLUGINS) {
$iExtendingClassesCount = count(MetaModel::EnumPlugins($sAPIFQCN));
} else {
$iExtendingClassesCount = count(utils::GetClassesForInterface($sAPIFQCN, '', ['[\\\\/]lib[\\\\/]', '[\\\\/]node_modules[\\\\/]', '[\\\\/]test[\\\\/]', '[\\\\/]tests[\\\\/]']));
$iExtendingClassesCount = count(InterfaceDiscovery::GetInstance()->FindItopClasses($sAPIFQCN));
}
$this->assertGreaterThan(0, $iExtendingClassesCount, "Found no class extending the $sAPIFQCN API");
}

View File

@@ -0,0 +1,166 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Service\Cache;
use Combodo\iTop\Service\Cache\DataModelDependantCache;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use Exception;
class DataModelDependantCacheTest extends ItopTestCase
{
private DataModelDependantCache $oCacheService;
private string $sCacheRootDir;
protected function setUp(): void
{
parent::setUp();
$this->RequireOnceItopFile('setup/setuputils.class.inc.php');
$this->sCacheRootDir = self::CreateTmpdir();
$this->oCacheService = DataModelDependantCache::GetInstance();
$this->SetNonPublicProperty($this->oCacheService, 'sStorageRootDir', $this->sCacheRootDir);
}
protected function tearDown(): void
{
$this->SetNonPublicProperty($this->oCacheService, 'sStorageRootDir', null);
self::RecurseRmdir($this->sCacheRootDir);
parent::tearDown();
}
public function testShouldStoreAndFetchVariousDataTypes(): void
{
$this->oCacheService->Store('pool-A', 'key-array', ['value1', 'value2']);
$this->oCacheService->Store('pool-A', 'key-string', 'foo');
$this->oCacheService->Store('pool-A', 'key-int', 1971);
$this->assertEquals(['value1', 'value2'], $this->oCacheService->Fetch('pool-A', 'key-array'));
$this->assertEquals('foo', $this->oCacheService->Fetch('pool-A', 'key-string'));
$this->assertEquals(1971, $this->oCacheService->Fetch('pool-A', 'key-int'));
}
public function testShouldNotAllowToStoreNull(): void
{
$this->ExpectExceptionMessage('Cannot store NULL in the cache');
$this->oCacheService->Store('pool-A', 'key', null);
}
public function testShouldStoreInADirectoryRebuiltOnCompilation(): void
{
// Given the storage is reset to the default
$this->SetNonPublicProperty($this->oCacheService, 'sStorageRootDir', null);
// Then
$sFilePath = $this->InvokeNonPublicMethod(DataModelDependantCache::class, 'MakeCacheFileName', $this->oCacheService, ['pool-A', 'key']);
$this->assertStringContainsString('data/cache-', $sFilePath);
}
public function testPoolShouldSeparateEntriesHavingTheSameKey(): void
{
// Given
$this->oCacheService->Store('pool-A', 'key', ['data-default']);
$this->oCacheService->Store('pool-B', 'key', ['data-pool-B']);
// Then
$this->assertEquals(['data-default'], $this->oCacheService->Fetch('pool-A', 'key'));
$this->assertEquals(['data-pool-B'], $this->oCacheService->Fetch('pool-B', 'key'));
$this->assertEquals(null, $this->oCacheService->Fetch('pool-C-unknown', 'key'));
}
public function testPoolsShouldBeVisibleInThePath(): void
{
$sFilePath = $this->InvokeNonPublicMethod(DataModelDependantCache::class, 'MakeCacheFileName', $this->oCacheService, ['pool-B', 'key']);
$this->assertStringContainsString('pool-B', $sFilePath);
}
public function testFetchShouldReturnNullForNonExistingKey(): void
{
$this->assertNull($this->oCacheService->Fetch('pool-A', 'non-existing-key'));
}
public function testAnUnknownPoolShouldFailSilently(): void
{
$this->assertNull($this->oCacheService->Fetch('unknown-pool', 'non-existing-key'));
}
public function testDeleteItemAndHasEntry()
{
// Given an empy cache
// Then
$this->assertFalse($this->oCacheService->HasEntry('pool-A', 'key'), 'HasEntry should return false for non-existing key');
// When
$this->oCacheService->Store('pool-A', 'key', 'some data...');
// Then
$this->assertTrue($this->oCacheService->HasEntry('pool-A', 'key'), 'HasEntry should return true for newly created key');
// When
$this->oCacheService->DeleteItem('pool-A', 'key');
// Then
$this->assertFalse($this->oCacheService->HasEntry('pool-A', 'key'), 'HasEntry should return true for a removed key');
}
public function testDeleteItemShouldPreserveOtherEntries()
{
// Given
$this->oCacheService->Store('pool-A', 'key', 'some data...');
$this->oCacheService->Store('pool-A', 'key2', 'some data...');
// Then
$this->oCacheService->DeleteItem('pool-A', 'key');
// When
$this->assertTrue($this->oCacheService->HasEntry('pool-A', 'key2'));
}
public function testDeleteItemShouldPreserveHomonymsFromDifferentPools()
{
// Given
$this->oCacheService->Store('pool-A', 'key', 'some data...');
$this->oCacheService->Store('pool-B', 'key', 'some data...');
// When
$this->oCacheService->DeleteItem('pool-B', 'key');
// Then
$this->assertTrue($this->oCacheService->HasEntry('pool-A', 'key'), 'DeleteItem should not have altered the pool "default"');
}
public function testClearShouldRemoveAllEntriesFromTheCurrentPool()
{
// Given
$this->oCacheService->Store('pool-A', 'key', 'some data...');
$this->oCacheService->Store('pool-A', 'key2', 'some data...');
$this->oCacheService->Store('pool-B', 'key', 'some data...');
// When
$this->oCacheService->Clear('pool-A');
// Then
$this->assertFalse($this->oCacheService->HasEntry('pool-A', 'key'), 'DeleteItem should remove all entries from the current pool');
$this->assertFalse($this->oCacheService->HasEntry('pool-A', 'key2'), 'DeleteItem should remove all entries from the current pool');
$this->assertTrue($this->oCacheService->HasEntry('pool-B', 'key'), 'DeleteItem should not alter entries from other pools');
}
public function testGetEntryModificationTime()
{
// Given an entry created at a specific time
$this->oCacheService->Store('pool-A', 'key', 'some data...');
$iRefTime = time();
$sFilePath = $this->InvokeNonPublicMethod(DataModelDependantCache::class, 'MakeCacheFileName', $this->oCacheService, ['pool-A', 'key']);
touch($sFilePath, $iRefTime);
// Then
$this->assertEquals($iRefTime, $this->oCacheService->GetEntryModificationTime('pool-A', 'key'), 'GetEntryModificationTime should return the modification time of the cache file');
$this->assertEquals(null, $this->oCacheService->GetEntryModificationTime('pool-A', 'non-existing-key'), 'GetEntryModificationTime should return null for an invalid key');
}
public function testKeyUndesiredCharactersShouldBeTransformedToUnderscore()
{
$sUglyKey = 'key with ugly characters:\{&"#@ç^²/,;[(|🤔';
$sFilePath = $this->InvokeNonPublicMethod(DataModelDependantCache::class, 'MakeCacheFileName', $this->oCacheService, ['pool-A', $sUglyKey]);
$this->assertEquals('key_with_ugly_characters______________________.php', basename($sFilePath));
}
}

View File

@@ -0,0 +1,73 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Service\InterfaceDiscovery;
use Combodo\iTop\Application\UI\Base\iUIBlockFactory;
use Combodo\iTop\Service\InterfaceDiscovery\InterfaceDiscovery;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
class InterfaceDiscoveryTest extends ItopDataTestCase
{
protected function tearDown(): void
{
$this->SetNonPublicProperty(InterfaceDiscovery::GetInstance(), 'aForcedClassMap', null);
parent::tearDown();
}
public function testShouldSelectTheRequestedItopClasses()
{
$oInterfaceDiscoveryService = InterfaceDiscovery::GetInstance();
$this->GivenClassMap($oInterfaceDiscoveryService, [
'Combodo\iTop\Application\UI\Base\Component\Alert\Alert' => APPROOT . '/sources/Application/UI/Base/Component/Alert/Alert.php',
'Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory' => APPROOT . '/sources/Application/UI/Base/Component/Alert/AlertUIBlockFactory.php',
'Combodo\iTop\Application\UI\Base\Component\ButtonGroup\ButtonGroupUIBlockFactory' => APPROOT . '/sources/Application/UI/Base/Component/ButtonGroup/ButtonGroupUIBlockFactory.php',
]);
$this->AssertArraysHaveSameItems(
[
'Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory',
'Combodo\iTop\Application\UI\Base\Component\ButtonGroup\ButtonGroupUIBlockFactory',
],
$oInterfaceDiscoveryService->FindItopClasses(iUIBlockFactory::class)
);
}
public function testShouldExcludeSpecifiedDirectories()
{
$oInterfaceDiscoveryService = InterfaceDiscovery::GetInstance();
$this->GivenClassMap($oInterfaceDiscoveryService, [
'Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory' => APPROOT . '/sources/Application/UI/Base/Component/Alert/AlertUIBlockFactory.php',
'Combodo\iTop\Application\UI\Base\Component\ButtonGroup\ButtonGroupUIBlockFactory' => APPROOT . '/sources/Application/UI/Base/Component/ButtonGroup/ButtonGroupUIBlockFactory.php',
]);
$this->AssertArraysHaveSameItems(
[],
$oInterfaceDiscoveryService->FindItopClasses(iUIBlockFactory::class, ['Component/ButtonGroup', '/Alert/'])
);
}
public function testShouldExcludeAliases()
{
$oInterfaceDiscoveryService = InterfaceDiscovery::GetInstance();
$this->GivenClassMap($oInterfaceDiscoveryService, [
'Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory' => APPROOT . '/sources/Application/UI/Base/Component/Alert/AlertUIBlockFactory.php',
'AlbertIsBlockingTheFactory' => APPROOT . '/sources/Application/UI/Base/Component/Alert/AlertUIBlockFactory.php',
]);
class_alias('Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory', 'AlbertIsBlockingTheFactory');
$this->AssertArraysHaveSameItems(
[
'Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory',
],
$oInterfaceDiscoveryService->FindItopClasses(iUIBlockFactory::class)
);
}
private function GivenClassMap(InterfaceDiscovery $oInterfaceDiscoveryService, array $aClassMap): void
{
$this->SetNonPublicProperty($oInterfaceDiscoveryService, 'aForcedClassMap', $aClassMap);
}
}