From 97828225db59615a6ff4e4dbbd19da25318eceea Mon Sep 17 00:00:00 2001 From: odain Date: Fri, 23 Jan 2026 09:28:54 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B08764=20-=20fix=20setup=20wizards=20trans?= =?UTF-8?q?itions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup/wizardsteps.class.inc.php | 21 ++- .../setup/WizStepModulesChoiceFake.php | 3 +- .../setup/WizStepModulesChoiceTest.php | 136 +++++++++++++++++- 3 files changed, 145 insertions(+), 15 deletions(-) diff --git a/setup/wizardsteps.class.inc.php b/setup/wizardsteps.class.inc.php index fab3c92b8..436599723 100644 --- a/setup/wizardsteps.class.inc.php +++ b/setup/wizardsteps.class.inc.php @@ -1894,7 +1894,6 @@ EOF $index = $idx ?? $this->GetStepIndex(); if (is_null($this->aSteps)) { - $this->aSteps = []; $this->oWizard->SetParameter('additional_extensions_modules', json_encode([])); // Default value, no additional extensions $aOptions = $this->oExtensionsMap->GetAllExtensionsOptionInfo(); @@ -1903,29 +1902,27 @@ EOF $aParams = new XMLParameters($this->GetSourceFilePath()); $this->aSteps = $aParams->Get('steps', []); - // Additional step for the "extensions" - $aStepDefinition = [ - 'title' => 'Extensions', - 'description' => '

Select additional extensions to install. You can launch the installation again to install new extensions or remove installed ones.

', - 'banner' => '/images/icons/icons8-puzzle.svg', - 'options' => $aOptions, - ]; - // Display this step of the wizard only if there is something to display if (count($aOptions) > 0) { + $this->aSteps[] = [ + 'title' => 'Extensions', + 'description' => '

Select additional extensions to install. You can launch the installation again to install new extensions or remove installed ones.

', + 'banner' => '/images/icons/icons8-puzzle.svg', + 'options' => $aOptions, + ]; $this->oWizard->SetParameter('additional_extensions_modules', json_encode($aOptions)); } } else { // No wizard configuration provided, build a standard one with just one big list. All items are mandatory, only works when there are no conflicted modules. - $aStepDefinition = [ + $this->aSteps = [ + [ 'title' => 'Modules Selection', 'description' => '

Select the modules to install. You can launch the installation again to install new modules, but you cannot remove already installed modules.

', 'banner' => '/images/icons/icons8-apps-tab.svg', 'options' => $aOptions, + ], ]; } - - $this->aSteps[] = $aStepDefinition; } return $this->aSteps[$index] ?? null; diff --git a/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceFake.php b/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceFake.php index 69a99b3dd..6b2ed3caf 100644 --- a/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceFake.php +++ b/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceFake.php @@ -4,7 +4,8 @@ class WizStepModulesChoiceFake extends WizStepModulesChoice { public function __construct(WizardController $oWizard, $sCurrentState) { - + $this->oWizard = $oWizard; + $this->sCurrentState = $sCurrentState; } public function setExtensionMap(iTopExtensionsMap $oMap) diff --git a/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceTest.php b/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceTest.php index 5f30de425..b3a6ba391 100644 --- a/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceTest.php +++ b/tests/php-unit-tests/unitary-tests/setup/WizStepModulesChoiceTest.php @@ -3,13 +3,16 @@ namespace Combodo\iTop\Test\UnitTest\Integration; use Combodo\iTop\Test\UnitTest\ItopTestCase; -use ItopExtensionsMap; +use iTopExtensionsMap; use iTopExtensionsMapFake; use ModuleDiscovery; use WizardController; +use WizStepModulesChoiceFake; +use XMLParameters; class WizStepModulesChoiceTest extends ItopTestCase { + private WizStepModulesChoiceFake $oStep; protected function setUp(): void { parent::setUp(); @@ -17,7 +20,7 @@ class WizStepModulesChoiceTest extends ItopTestCase require_once __DIR__.'/iTopExtensionsMapFake.php'; require_once __DIR__.'/WizStepModulesChoiceFake.php'; - $this->oStep = new \WizStepModulesChoiceFake(new WizardController('', ''), ''); + $this->oStep = new WizStepModulesChoiceFake(new WizardController('', ''), ''); ModuleDiscovery::ResetCache(); } @@ -350,4 +353,133 @@ class WizStepModulesChoiceTest extends ItopTestCase $this->assertEquals($aExpectedRemovedList, $aRemovedList); } + public function testGetStepInfo_PackageWithoutInstallationXML() + { + $aExtensionsOnDiskOrDb = [ + 'itop-ext-added1' => [ + 'installed' => false, + ], + 'itop-ext-added2' => [ + 'installed' => false, + ], + ]; + + $oWizStepModulesChoice = $this->GivenWizStepModulesChoice($aExtensionsOnDiskOrDb); + + $expected = [ + 'title' => 'Modules Selection', + 'description' => '

Select the modules to install. You can launch the installation again to install new modules, but you cannot remove already installed modules.

', + 'banner' => '/images/icons/icons8-apps-tab.svg', + 'options' => $aExtensionsOnDiskOrDb, + ]; + + $this->CallAndCheckTwice($oWizStepModulesChoice, [], $expected); + $this->CallAndCheckTwice($oWizStepModulesChoice, [1], null); + } + + public static function PackageWithInstallationXMLProvider() + { + + require_once __DIR__.'/../../../../approot.inc.php'; + require_once APPROOT.'setup/parameters.class.inc.php'; + + $aExtensionsOnDiskOrDb = [ + 'itop-ext-added1' => [ + 'installed' => false, + ], + 'itop-ext-added2' => [ + 'installed' => false, + ], + ]; + + $aUsecases = []; + + $expected = self::GetStep(0); + $aUsecases["[no step] with extensions"] = [ + 'aExtensionsOnDiskOrDb' => $aExtensionsOnDiskOrDb, + 'aArgs' => [], + 'expected' => $expected, + ]; + + for ($i = 0; $i < 5; $i++) { + $expected = self::GetStep($i); + $aUsecases["[step $i] with extensions"] = [ + 'aExtensionsOnDiskOrDb' => $aExtensionsOnDiskOrDb, + 'aArgs' => [$i], + 'expected' => $expected, + ]; + } + + $expected = [ + 'title' => 'Extensions', + 'description' => '

Select additional extensions to install. You can launch the installation again to install new extensions or remove installed ones.

', + 'banner' => '/images/icons/icons8-puzzle.svg', + 'options' => $aExtensionsOnDiskOrDb, + ]; + $aUsecases["[step 5] with extensions => EXTENSION STEP"] = [ + 'aExtensionsOnDiskOrDb' => $aExtensionsOnDiskOrDb, + 'aArgs' => [5], + 'expected' => $expected, + ]; + + $aUsecases["[step 6] with extensions => NO STEP ANYMORE"] = [ + 'aExtensionsOnDiskOrDb' => $aExtensionsOnDiskOrDb, + 'aArgs' => [6], + 'expected' => null, + ]; + + $aUsecases["[step 5] without extensions => NO STEP ANYMORE"] = [ + 'aExtensionsOnDiskOrDb' => [], + 'aArgs' => [5], + 'expected' => null, + ]; + + return $aUsecases; + } + + /** + * @dataProvider PackageWithInstallationXMLProvider + */ + public function testGetStepInfo_PackageWithInstallationXML($aExtensionsOnDiskOrDb, $aArgs, $expected) + { + $oWizStepModulesChoice = $this->GivenWizStepModulesChoice($aExtensionsOnDiskOrDb, true); + + $this->CallAndCheckTwice($oWizStepModulesChoice, $aArgs, $expected); + } + + private function GivenWizStepModulesChoice(array $aExtensionsOnDiskOrDb, $bInstallationXmlProvided = false): WizStepModulesChoiceFake + { + $oExtensionsMap = $this->createMock(iTopExtensionsMap::class); + $oExtensionsMap->expects($this->once()) + ->method('GetAllExtensionsOptionInfo') + ->willReturn($aExtensionsOnDiskOrDb); + + $oWizard = new WizardController('', ''); + if ($bInstallationXmlProvided) { + //needed to find installation.xml + $oWizard->SetParameter('source_dir', __DIR__.'/ressources'); + } + $oWizStepModulesChoice = new WizStepModulesChoiceFake($oWizard, ''); + $oWizStepModulesChoice->setExtensionMap($oExtensionsMap); + + return $oWizStepModulesChoice; + } + + private function CallAndCheckTwice($oStep, $aArgs, $expected) + { + $aRes = $this->InvokeNonPublicMethod(WizStepModulesChoiceFake::class, 'GetStepInfo', $oStep, $aArgs); + $this->assertEquals($expected, $aRes, "step:".var_export($aArgs, true)); + + $aRes = $this->InvokeNonPublicMethod(WizStepModulesChoiceFake::class, 'GetStepInfo', $oStep, $aArgs); + $this->assertEquals($expected, $aRes, "(2nd call) step:".var_export($aArgs, true)); + } + + private static function GetStep($index) + { + $aParams = new XMLParameters(__DIR__.'/ressources/installation.xml'); + $aSteps = $aParams->Get('steps', []); + + return $aSteps[$index] ?? null; + } + }