RequireOnceItopFile('/setup/unattended-install/InstallationFileService.php');
require_once __DIR__.'/WebPageFake.php';
require_once __DIR__.'/iTopExtensionsMapFake.php';
require_once __DIR__.'/WizStepModulesChoiceFake.php';
$this->oWizard = new WizardController('', '');
$this->oWizStepModulesChoiceFake = new WizStepModulesChoiceFake($this->oWizard, '');
ModuleDiscovery::ResetCache();
}
/**
* Expected flags for the different scenarios, see the flowchart for a visual representation of the logic:
* @see ressources/compute_choice_flags.flowchart.fun
* @link https://flowchart.fun
*/
public function ProviderComputeChoiceFlags(): array
{
return [
'#node1 - A missing extension should be disabled and unchecked' => [
'aExtensionsOnDiskOrDb' => [
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'missing' => true,
'uninstallable' => true,
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => true,
'installed' => true,
'disabled' => true,
'checked' => false,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node1 - A missing extension should always be disabled and unchecked, even a mandatory extension included in package' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
'source' => 'datamodels', // iTopExtension::SOURCE_WIZARD
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'mandatory' => true,
'missing' => true,
'uninstallable' => true,
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => true,
'installed' => true,
'disabled' => true,
'checked' => false,
'dependency_issue' => false,
'mandatory' => true,
],
],
'#node2 - A mandatory extension included in package should be checked and disabled even if the "disable uninstallation check" flag is set' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => false,
'source' => 'datamodels', // iTopExtension::SOURCE_WIZARD
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'mandatory' => true,
'uninstallable' => true,
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => true,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => false,
'disabled' => true,
'checked' => true,
'dependency_issue' => false,
'mandatory' => true,
],
],
'#node3 - An installed non uninstallable sub extension should force its parent to be checked and disabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
'itop-ext1-1' => [
'installed' => true,
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'sub_options' => [
'options' => [
[
'extension_code' => 'itop-ext1-1',
'uninstallable' => false,
],
],
],
],
'aSelectedComponents' => ['_0' => '_0', '_0_0' => '_0_0'],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => true,
'checked' => true,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node3 - An installed remote sub extension should force its parent to be checked and disabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
'itop-ext1-1' => [
'installed' => true,
'source' => 'data', // iTopExtension::SOURCE_REMOTE
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'sub_options' => [
'options' => [
[
'extension_code' => 'itop-ext1-1',
'uninstallable' => true,
],
],
],
],
'aSelectedComponents' => ['_0' => '_0', '_0_0' => '_0_0'],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => true,
'checked' => true,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node4 - An installed uninstallable sub extension should force its parent to be checked but not disabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => false,
],
'itop-ext1-1' => [
'installed' => true,
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'sub_options' => [
'options' => [
[
'extension_code' => 'itop-ext1-1',
'uninstallable' => true,
],
],
],
],
'aSelectedComponents' => ['_0_0' => '_0_0'],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => false,
'disabled' => false,
'checked' => true,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node4 - An installed non uninstallable sub extension should force its parent to be checked but not disabled if the "disable uninstallation check" flag is set' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
'itop-ext1-1' => [
'installed' => true,
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'sub_options' => [
'options' => [
[
'extension_code' => 'itop-ext1-1',
'uninstallable' => false,
],
],
],
],
'aSelectedComponents' => ['_0' => '_0', '_0_0' => '_0_0'],
'bDisableUninstallChecks' => true,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => true,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node4 - An installed remote sub extension should force its parent to be checked but not disabled if the "disable uninstallation check" flag is set' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
'itop-ext1-1' => [
'installed' => true,
'source' => 'data', // iTopExtension::SOURCE_REMOTE
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'sub_options' => [
'options' => [
[
'extension_code' => 'itop-ext1-1',
'uninstallable' => true,
],
],
],
],
'aSelectedComponents' => ['_0' => '_0', '_0_0' => '_0_0'],
'bDisableUninstallChecks' => true,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => true,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node5 - A non installed extension with missing dependencies should be not checked and disabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => false,
'missing_dependencies' => [
'itop-ext1-1',
],
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'missing_dependencies' => true,
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => false,
'disabled' => true,
'checked' => false,
'dependency_issue' => true,
'mandatory' => false,
],
],
'#node5 - A non installed extension with missing dependencies should be not checked and disabled even with force uninstall' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => false,
'missing_dependencies' => [
'itop-ext1-1',
],
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'missing_dependencies' => true,
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => true,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => false,
'disabled' => true,
'checked' => false,
'dependency_issue' => true,
'mandatory' => false,
],
],
'#node6 - An installed extension with missing dependencies and without force uninstall should be checked and disabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
'missing_dependencies' => [
'itop-ext1-1',
],
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'missing_dependencies' => true,
],
'aSelectedComponents' => ['_0' => '_0'],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => true,
'checked' => true,
'dependency_issue' => true,
'mandatory' => false,
],
],
'#node7 - An installed extension with missing dependencies and with force uninstall should be checked and enabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
'missing_dependencies' => [
'itop-ext1-1',
],
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'missing_dependencies' => true,
],
'aSelectedComponents' => ['_0' => '_0'],
'bDisableUninstallChecks' => true,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => true,
'dependency_issue' => true,
'mandatory' => false,
],
],
'#node8 - An installed but not selected extension with missing dependencies and with force uninstall should be unchecked and enabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
'missing_dependencies' => [
'itop-ext1-1',
],
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'missing_dependencies' => true,
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => true,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => false,
'dependency_issue' => true,
'mandatory' => false,
],
],
'#node9 - A not selected, not installed extension should not be checked and be enabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => false,
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => false,
'disabled' => false,
'checked' => false,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node10 - A selected but not installed extension should be checked and enabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => false,
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
],
'aSelectedComponents' => ['_0' => '_0'],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => false,
'disabled' => false,
'checked' => true,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node11 - An installed but not selected extension should not be checked and be enabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => false,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node12 - An installed and selected extension should be checked and enabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'missing_dependencies' => false,
],
'aSelectedComponents' => ['_0' => '_0'],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => true,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node13 - An installed non uninstallable extension should be checked and disabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => false,
],
'aSelectedComponents' => ['_0' => '_0'],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => false,
'missing' => false,
'installed' => true,
'disabled' => true,
'checked' => true,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node13 - An installed remote extension should be checked and disabled' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
'source' => 'data', // iTopExtension::SOURCE_REMOTE
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
],
'aSelectedComponents' => ['_0' => '_0'],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => true,
'checked' => true,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node14 - An installed but not selected non uninstallable extension should be checked and enabled if the "disable uninstallation check" flag is set' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => false,
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => true,
'aExpectedFlags' => [
'uninstallable' => false,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => false,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node14 - An installed but not selected remote extension should be checked and enabled if the "disable uninstallation check" flag is set' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
'source' => 'data', // iTopExtension::SOURCE_REMOTE
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => true,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => false,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node15 - An installed non uninstallable extension should be checked and enabled if the "disable uninstallation check" flag is set' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => false,
],
'aSelectedComponents' => ['_0' => '_0'],
'bDisableUninstallChecks' => true,
'aExpectedFlags' => [
'uninstallable' => false,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => true,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node15 - An installed remote extension should be checked and enabled if the "disable uninstallation check" flag is set' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
'source' => 'data', // iTopExtension::SOURCE_REMOTE
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
],
'aSelectedComponents' => ['_0' => '_0'],
'bDisableUninstallChecks' => true,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => true,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node16 - A non installed non uninstallable sub extension should not force its parent flags' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
'itop-ext1-1' => [
'installed' => false,
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'sub_options' => [
'options' => [
[
'extension_code' => 'itop-ext1-1',
'uninstallable' => false,
],
],
],
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => false,
'dependency_issue' => false,
'mandatory' => false,
],
],
'#node16 - A non installed remote sub extension should not force its parent flags' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
'itop-ext1-1' => [
'installed' => false,
'source' => 'data', // iTopExtension::SOURCE_REMOTE
],
],
'aWizardStepDefinition' => [
'extension_code' => 'itop-ext1',
'uninstallable' => true,
'sub_options' => [
'options' => [
[
'extension_code' => 'itop-ext1-1',
'uninstallable' => true,
],
],
],
],
'aSelectedComponents' => [],
'bDisableUninstallChecks' => false,
'aExpectedFlags' => [
'uninstallable' => true,
'missing' => false,
'installed' => true,
'disabled' => false,
'checked' => false,
'dependency_issue' => false,
'mandatory' => false,
],
],
];
}
/**
* @dataProvider ProviderComputeChoiceFlags
*/
public function testComputeChoiceFlags($aExtensionsOnDiskOrDb, $aWizardStepDefinition, $aSelectedComponents, $bDisableUninstallChecks, $aExpectedFlags)
{
$this->oWizStepModulesChoiceFake->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsOnDiskOrDb));
$aFlags = $this->oWizStepModulesChoiceFake->ComputeChoiceFlags($aWizardStepDefinition, '_0', $aSelectedComponents, false, $bDisableUninstallChecks);
$this->assertEquals($aExpectedFlags, $aFlags);
}
public function ProviderGetAddedAndRemovedExtensions()
{
return [
'no extensions' => [
'aExtensionsOnDiskOrDb' => [],
'aSelected' => [],
'aExpectedAddedList' => [],
'aExpectedRemovedList' => [],
],
'no extensions added nor removed' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => false,
],
],
'aSelected' => [],
'aExpectedAddedList' => [],
'aExpectedRemovedList' => [],
],
'One added extension' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => false,
],
],
'aSelected' => ['itop-ext1'],
'aExpectedAddedList' => ['itop-ext1' => 'itop-ext1'],
'aExpectedRemovedList' => [],
],
'One removed extension' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
],
],
'aSelected' => [],
'aExpectedAddedList' => [],
'aExpectedRemovedList' => ['itop-ext1' => 'itop-ext1'],
],
'Forced removed extension' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext1' => [
'installed' => true,
'uninstallable' => false,
],
],
'aSelected' => [],
'aExpectedAddedList' => [],
'aExpectedRemovedList' => ['itop-ext1' => 'itop-ext1'],
],
'added and removed extensions' => [
'aExtensionsOnDiskOrDb' => [
'itop-ext-added1' => [
'installed' => false,
],
'itop-ext-added2' => [
'installed' => false,
],
'itop-ext-removed1' => [
'installed' => true,
],
'itop-ext-removed2' => [
'installed' => true,
],
],
'aSelected' => ['itop-ext-added1', 'itop-ext-added2'],
'aExpectedAddedList' => ['itop-ext-added1' => 'itop-ext-added1', 'itop-ext-added2' => 'itop-ext-added2'],
'aExpectedRemovedList' => ['itop-ext-removed1' => 'itop-ext-removed1', 'itop-ext-removed2' => 'itop-ext-removed2'],
],
];
}
/**
* @dataProvider ProviderGetAddedAndRemovedExtensions
*/
public function testGetAddedAndRemovedExtensions($aExtensionsOnDiskOrDb, $aSelectedExtensions, $aExpectedAddedList, $aExpectedRemovedList)
{
$this->oWizStepModulesChoiceFake->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsOnDiskOrDb));
[$aAddedList, $aRemovedList, $aNotUninstallableList] = $this->oWizStepModulesChoiceFake->GetAddedAndRemovedExtensions($aSelectedExtensions);
$this->assertEquals($aExpectedAddedList, $aAddedList);
$this->assertEquals($aExpectedRemovedList, $aRemovedList);
}
public function testGetStepInfo_PackageWithoutInstallationXML()
{
$aExtensionsOnDiskOrDb = self::GivenExtensionsOnDisk();
$oWizStepModulesChoice = $this->GivenWizStepModulesChoiceWithoutXmlInstallation($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, null, $expected);
$this->CallAndCheckTwice($oWizStepModulesChoice, 1, null);
}
private function GivenWizStepModulesChoiceWithoutXmlInstallation(array $aExtensionsOnDiskOrDb): WizStepModulesChoiceFake
{
$oExtensionsMap = $this->createMock(iTopExtensionsMap::class);
$oExtensionsMap->expects($this->once())
->method('GetAllExtensionsOptionInfo')
->willReturn($aExtensionsOnDiskOrDb);
$oWizard = new WizardController('', '');
$oWizStepModulesChoice = new WizStepModulesChoiceFake($oWizard, '');
$oWizStepModulesChoice->setExtensionMap($oExtensionsMap);
return $oWizStepModulesChoice;
}
public static function PackageWithInstallationXMLProvider()
{
require_once __DIR__.'/../../../../approot.inc.php';
require_once APPROOT.'setup/parameters.class.inc.php';
$aUsecases = [];
$aUsecases["[no step] with extensions"] = [
'iGetStepInfoIdxArg' => null,
'expected' => self::GetStep(0),
];
for ($i = 0; $i < 4; $i++) {
$aUsecases["[step $i] with extensions"] = [
'iGetStepInfoIdxArg' => $i,
'expected' => self::GetStep($i),
];
}
$aUsecases["[step 6] with extensions => NO STEP ANYMORE"] = [
'iGetStepInfoIdxArg' => 6,
'expected' => null,
'iGetAllExtensionsOptionInfoCallCount' => 1,
];
return $aUsecases;
}
/**
* @dataProvider PackageWithInstallationXMLProvider
*/
public function testGetStepInfo_PackageWithInstallationXMLWithExtensions($iGetStepInfoIdxArg, $expected, $iGetAllExtensionsOptionInfoCallCount = 0)
{
$aExtensionsOnDiskOrDb = self::GivenExtensionsOnDisk();
$oWizStepModulesChoice = $this->GivenWizStepModulesChoiceWithXmlInstallation($aExtensionsOnDiskOrDb, $iGetAllExtensionsOptionInfoCallCount);
$this->CallAndCheckTwice($oWizStepModulesChoice, $iGetStepInfoIdxArg, $expected);
}
public function testGetStepInfo_PackageWithInstallationXML_AfterLastStepWithExtensions()
{
$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' => self::GivenExtensionsOnDisk(),
];
$aExtensionsOnDiskOrDb = self::GivenExtensionsOnDisk();
$oWizStepModulesChoice = $this->GivenWizStepModulesChoiceWithXmlInstallation($aExtensionsOnDiskOrDb, 1);
$this->CallAndCheckTwice($oWizStepModulesChoice, 5, $expected);
}
public function testGetStepInfo_PackageWithInstallationXMLAfterLastStepWithoutExtensions()
{
$oWizStepModulesChoice = $this->GivenWizStepModulesChoiceWithXmlInstallation([], 1);
$this->CallAndCheckTwice($oWizStepModulesChoice, 5, null);
}
public function testGetStepInfo_PackageWithInstallationXML_MakeSureNextStepIsAlsoCached()
{
$aExtensionsOnDiskOrDb = self::GivenExtensionsOnDisk();
$oWizStepModulesChoice = $this->GivenWizStepModulesChoiceWithXmlInstallation($aExtensionsOnDiskOrDb, 1);
$this->CallAndCheckTwice($oWizStepModulesChoice, 4, self::GetStep(4));
$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,
];
$this->CallAndCheckTwice($oWizStepModulesChoice, 5, $expected);
}
private static function GivenExtensionsOnDisk(): array
{
return [
'itop-ext-added1' => [
'installed' => false,
],
'itop-ext-added2' => [
'installed' => false,
],
];
}
private function GivenWizStepModulesChoiceWithXmlInstallation(array $aExtensionsOnDiskOrDb, $iGetAllExtensionsOptionInfoCallCount): WizStepModulesChoiceFake
{
$oExtensionsMap = $this->createMock(iTopExtensionsMap::class);
$oExtensionsMap->expects($this->exactly($iGetAllExtensionsOptionInfoCallCount))
->method('GetAllExtensionsOptionInfo')
->willReturn($aExtensionsOnDiskOrDb);
$oWizard = new WizardController('', '');
//needed to find installation.xml
$oWizard->SetParameter('source_dir', __DIR__.'/ressources');
$oWizStepModulesChoice = new WizStepModulesChoiceFake($oWizard, '');
$oWizStepModulesChoice->setExtensionMap($oExtensionsMap);
return $oWizStepModulesChoice;
}
private function CallAndCheckTwice($oStep, $iGetStepInfoIdxArg, $expected)
{
$aRes = $this->InvokeNonPublicMethod(WizStepModulesChoiceFake::class, 'GetStepInfo', $oStep, [$iGetStepInfoIdxArg]);
$this->assertEquals($expected, $aRes, "step:".$iGetStepInfoIdxArg);
$aRes = $this->InvokeNonPublicMethod(WizStepModulesChoiceFake::class, 'GetStepInfo', $oStep, [$iGetStepInfoIdxArg]);
$this->assertEquals($expected, $aRes, "(2nd call) step:".$iGetStepInfoIdxArg);
}
private static function GetStep($index)
{
$aParams = new XMLParameters(__DIR__.'/ressources/installation.xml');
$aSteps = $aParams->Get('steps', []);
return $aSteps[$index] ?? null;
}
public function ProviderGetSelectedModules()
{
return [
'No extension selected' => [
'aSelected' => [],
'aExpectedModules' => [],
'aExpectedExtensions' => [],
],
'One extension selected' => [
'aSelected' => ['_0' => '_0'],
'aExpectedModules' => ['combodo-sample-module' => true],
'aExpectedExtensions' => ['combodo-sample'],
],
'More extensions selected' => [
'aSelected' => ['_0' => '_0', '_1' => '_1'],
'aExpectedModules' => ['combodo-sample-module' => true, 'combodo-test-moduleA' => true, 'combodo-test-moduleB' => true],
'aExpectedExtensions' => ['combodo-sample', 'combodo-test'],
],
];
}
/**
* @dataProvider ProviderGetSelectedModules
*/
public function testGetSelectedModules($aSelectedExtensions, $aExpectedModules, $aExpectedExtensions)
{
$aExtensionsMapData = [
'combodo-sample' => [
'installed' => false,
],
'combodo-test' => [
'installed' => false,
],
];
$this->oWizStepModulesChoiceFake->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsMapData));
$aStepInfo = [
'title' => 'Extensions',
'description' => '',
'banner' => '',
'options' => [
[
'extension_code' => 'combodo-sample',
'title' => 'Sample extension',
'description' => '',
'more_info' => '',
'default' => true,
'modules' => [
'combodo-sample-module',
],
'mandatory' => false,
'source_label' => '',
'uninstallable' => true,
'missing' => false,
],
[
'extension_code' => 'combodo-test',
'title' => 'Test extension',
'description' => '',
'more_info' => '',
'default' => true,
'modules' => [
'combodo-test-moduleA',
'combodo-test-moduleB',
],
'mandatory' => false,
'source_label' => '',
'uninstallable' => true,
'missing' => false,
],
],
];
$aModules = [];
$aExtensions = [];
$this->oWizStepModulesChoiceFake->GetSelectedModules($aStepInfo, $aSelectedExtensions, $aModules, '', '', $aExtensions);
$this->assertEquals($aExpectedModules, $aModules);
$this->assertEquals($aExpectedExtensions, $aExtensions);
}
public function testGetSelectedModulesShouldAlwaysSelectMandatoryExtension()
{
$aSelectedExtensions = ['_0' => '_0'];
$aExtensionsMapData = [
'combodo-sample' => [
'installed' => true,
],
];
$this->oWizStepModulesChoiceFake->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsMapData));
$aStepInfo = [
'title' => 'Extensions',
'description' => '',
'banner' => '',
'options' => [
[
'extension_code' => 'combodo-sample',
'title' => 'Sample extension',
'description' => '',
'more_info' => '',
'default' => true,
'modules' => [
'combodo-sample-module',
],
'mandatory' => false,
'source_label' => '',
'uninstallable' => true,
'missing' => true,
],
],
];
$aExpectedModules = ['combodo-sample-module' => true];
$aExpectedExtensions = ['combodo-sample'];
$aModules = [];
$aExtensions = [];
$this->oWizStepModulesChoiceFake->GetSelectedModules($aStepInfo, $aSelectedExtensions, $aModules, '', '', $aExtensions);
$this->assertEquals($aExpectedModules, $aModules);
$this->assertEquals($aExpectedExtensions, $aExtensions);
}
public function testGetSelectedModulesShouldShouldParseAutoSelectCondition()
{
//the 'auto_select' parameter, contrary to its name, deselect the module if its result is false
$aSelectedExtensions = ['_0' => '_0'];
$aExtensionsMapData = [
'combodo-sample' => [
'installed' => true,
'module_info' => [
'combodo-sample-module' => [
'auto_select' => 'true && false',
],
],
],
];
$this->oWizStepModulesChoiceFake->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsMapData));
$aStepInfo = [
'title' => 'Extensions',
'description' => '',
'banner' => '',
'options' => [
[
'extension_code' => 'combodo-sample',
'title' => 'Sample extension',
'description' => '',
'more_info' => '',
'default' => true,
'modules' => [
'combodo-sample-module',
],
'mandatory' => false,
'source_label' => '',
'uninstallable' => true,
'missing' => true,
],
],
];
$aExpectedModules = [];
$aExpectedExtensions = ['combodo-sample'];
$aModules = [];
$aExtensions = [];
$this->oWizStepModulesChoiceFake->GetSelectedModules($aStepInfo, $aSelectedExtensions, $aModules, '', '', $aExtensions);
$this->assertEquals($aExpectedModules, $aModules);
$this->assertEquals($aExpectedExtensions, $aExtensions);
}
public function testGetSelectedModulesWithSubOptions()
{
$aSelectedExtensions = ['_0' => '_0', '_0_0' => '_0_0'];
$aExtensionsMapData = [
'combodo-sample' => [
'installed' => false,
],
'combodo-sub-sample' => [
'installed' => false,
],
];
$this->oWizStepModulesChoiceFake->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsMapData));
$aStepInfo = [
'options' => [
[
'extension_code' => 'combodo-sample',
'title' => 'Sample extension',
'description' => '',
'more_info' => '',
'default' => true,
'modules' => [
'combodo-sample-module',
],
'mandatory' => false,
'source_label' => '',
'uninstallable' => true,
'missing' => false,
'sub_options' => [
'options' => [
[
'extension_code' => 'combodo-sub-sample',
'title' => 'Sample sub extension',
'description' => '',
'more_info' => '',
'default' => true,
'modules' => [
'combodo-sub-sample-module',
],
'mandatory' => false,
'source_label' => '',
'uninstallable' => true,
'missing' => false,
],
],
],
],
],
];
$aExpectedModules = ['combodo-sample-module' => true, 'combodo-sub-sample-module' => true];
$aExpectedExtensions = ['combodo-sample', 'combodo-sub-sample'];
$aModules = [];
$aExtensions = [];
$this->oWizStepModulesChoiceFake->GetSelectedModules($aStepInfo, $aSelectedExtensions, $aModules, '', '', $aExtensions);
$this->assertEquals($aExpectedModules, $aModules);
$this->assertEquals($aExpectedExtensions, $aExtensions);
}
public function testGetSelectedModulesShouldThrowAnExceptionWhenAnySelectedExtensionDoesNotHaveAnyAssociatedModules()
{
$aExtensionsMapData = [
'combodo-sample' => [
'installed' => false,
],
];
$this->oWizStepModulesChoiceFake->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsMapData));
//GetSelectedModules
$aStepInfo = [
'title' => 'Extensions',
'description' => '',
'banner' => '',
'options' => [
[
'extension_code' => 'combodo-sample',
'title' => 'Sample extension',
'description' => '',
'more_info' => '',
'default' => true,
'modules' => [],
'mandatory' => false,
'source_label' => '',
'uninstallable' => true,
'missing' => false,
],
],
];
$aModules = [];
$aExtensions = [];
$this->expectException('Exception');
$this->expectExceptionMessage('Extension combodo-sample does not have any module associated');
$this->oWizStepModulesChoiceFake->GetSelectedModules($aStepInfo, ['_0' => '_0'], $aModules, '', '', $aExtensions);
}
public function testGetSelectedModulesShouldNotThrowAnExceptionWhenAMandatoryModuleIsMissing()
{
$aExtensionsMapData = [];
$this->oWizStepModulesChoiceFake->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsMapData));
//GetSelectedModules
$aStepInfo = [
'title' => 'Extensions',
'description' => '',
'banner' => '',
'options' => [
[
'extension_code' => 'combodo-sample',
'title' => 'Sample extension',
'description' => '',
'more_info' => '',
'default' => true,
'modules' => [],
'mandatory' => true,
'source_label' => '',
'uninstallable' => true,
'missing' => true,
],
],
];
$aModules = [];
$aExtensions = [];
$this->oWizStepModulesChoiceFake->GetSelectedModules($aStepInfo, ['_0' => '_0'], $aModules, '', '', $aExtensions);
$this->assertCount(0, $aModules);
$this->assertCount(1, $aExtensions);
}
public function ProviderDisplayOptions()
{
return [
'no choices' => [
'aStepOptions' => [],
'aStepAlternatives' => [],
'aSelectedComponents' => [],
'aDefaults' => [],
'aExpectedHTML' => '',
],
'one not installed extension' => [
'aStepOptions' => [
[
'extension_code' => 'itop-ext-not-installed',
'title' => 'My extension',
'description' => 'Do something',
'more_info' => '',
'modules' => [],
'source_label' => 'Local extensions folder',
'uninstallable' => true,
'missing' => false,
'version' => '1.2.3',
],
],
'aStepAlternatives' => [],
'aSelectedComponents' => [],
'aDefaults' => [],
'aExpectedHTML' => <<
HTML,
],
'one installed extension' => [
'aStepOptions' => [
[
'extension_code' => 'itop-ext-installed',
'title' => 'My extension',
'description' => 'Do something',
'more_info' => '',
'modules' => [],
'source_label' => 'Local extensions folder',
'uninstallable' => true,
'missing' => false,
'version' => '1.2.3',
],
],
'aStepAlternatives' => [],
'aSelectedComponents' => [],
'aDefaults' => [],
'aExpectedHTML' => <<
HTML,
],
'one installed extension that cannot be uninstalled' => [
'aStepOptions' => [
[
'extension_code' => 'itop-ext-installed',
'title' => 'My extension',
'description' => 'Do something',
'more_info' => '',
'modules' => [],
'source_label' => 'Local extensions folder',
'uninstallable' => false,
'missing' => false,
'version' => '1.2.3',
],
],
'aStepAlternatives' => [],
'aSelectedComponents' => ['_0' => '_0'],
'aDefaults' => [],
'aExpectedHTML' => <<
HTML,
],
'one choice alternative' => [
'aStepOptions' => [],
'aStepAlternatives' => [
[
'extension_code' => 'itop-alt-nothing',
'title' => 'No Change',
'description' => 'Do nothing',
'modules' => [],
],
],
'aSelectedComponents' => [],
'aDefaults' => [],
'aExpectedHTML' => <<
HTML,
],
'two choices alternative with non-empty installed' => [
'aStepOptions' => [],
'aStepAlternatives' => [
[
'extension_code' => 'itop-alt-something',
'title' => 'Change',
'description' => 'I am something',
'modules' => [
'itop-alt-module',
],
],
[
'extension_code' => 'itop-alt-nothing',
'title' => 'No Change',
'description' => 'Do nothing',
'modules' => [],
],
],
'aSelectedComponents' => [],
'aDefaults' => [],
'aExpectedHTML' => <<
HTML,
],
'two choices with sub options' => [
'aStepOptions' => [],
'aStepAlternatives' => [
[
'extension_code' => 'itop-alt-something',
'title' => 'Change',
'description' => 'I am something',
'modules' => [],
'sub_options' => [
'options' => [
[
'extension_code' => 'itop-ext-not-installed',
'title' => 'My extension',
'description' => 'Do something',
'more_info' => '',
'modules' => [],
//'source_label' => '',
'uninstallable' => true,
'missing' => false,
//'version' => '1.2.3',
],
],
],
],
[
'extension_code' => 'itop-alt-nothing',
'title' => 'No Change',
'description' => 'Do nothing',
'modules' => [],
],
],
'aSelectedComponents' => [],
'aDefaults' => [],
'aExpectedHTML' => <<
HTML,
],
];
}
/**
* @dataProvider ProviderDisplayOptions
*/
public function testDisplayOptions($aStepOptions, $aStepAlternatives, $aSelectedComponents, $aDefaults, $sExpectedHTML)
{
$aExtensionsOnDiskOrDb = [
'itop-ext-not-installed' => [
'installed' => false,
],
'itop-ext-installed' => [
'installed' => true,
],
'itop-alt-nothing' => [
'installed' => false,
],
'itop-alt-something' => [
'installed' => true,
],
];
$this->oWizStepModulesChoiceFake->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsOnDiskOrDb));
$aStepInfo = [
'options' => $aStepOptions,
'alternatives' => $aStepAlternatives,
];
$oPage = new \WebPageFake();
$this->oWizStepModulesChoiceFake->DisplayOptions($oPage, $aStepInfo, $aSelectedComponents, $aDefaults);
$this->assertEquals($sExpectedHTML, $oPage->sContent);
}
public function testGetSelectedComponents()
{
$aParams = new XMLParameters(__DIR__.'/ressources/installation_330.xml');
$aSteps = $aParams->Get('steps', []);
$aSelectedExtensions = ["itop-config-mgmt-core","itop-config-mgmt-datacenter","itop-config-mgmt-end-user","itop-config-mgmt-storage","itop-config-mgmt-virtualization","itop-container-mgmt","itop-service-mgmt-service-provider","itop-ticket-mgmt-itil","itop-ticket-mgmt-itil-user-request","itop-ticket-mgmt-itil-incident", "itop-ticket-mgmt-itil-enhanced-portal","itop-change-mgmt-simple","itop-kown-error-mgmt","itop-problem-mgmt","combodo-oauth2-client","combodo-mfa-extended","combodo-data-replication","combodo-api-playground","combodo-snapshot"];
$aRes = $this->oWizStepModulesChoiceFake->GetSelectedComponents($aSteps, json_encode($aSelectedExtensions));
$aExpected = json_decode('[{"_0":"_0","_1":"_1","_2":"_2","_3":"_3","_4":"_4","_4_0":"_4_0"},{"_0":"_1"},{"_0":"_1","_1_0":"_1_0", "_1_1": "_1_1", "_1_2": "_1_2"},{"_0":"_0"},{"_0":"_0","_1":"_1"}]', true);
$this->assertEquals($aExpected, $aRes);
}
public function testGetWizardSteps()
{
$this->oWizard->SetParameter('source_dir', __DIR__.'/ressources');
$aExtensionsOnDiskOrDb = [
'itop-ext-not-installed' => [
'installed' => false,
],
'itop-ext-installed' => [
'installed' => true,
],
];
$this->oWizStepModulesChoiceFake->setExtensionMap(iTopExtensionsMapFake::createFromArray($aExtensionsOnDiskOrDb));
$expected = [
["class" => "WizStepWelcome","state" => ""],
["class" => "WizStepDetectedInfo","state" => ""],
["class" => "WizStepUpgradeMiscParams","state" => ""],
];
for ($i = 0;$i <= 5; $i++) {
$expected [] = ["class" => "WizStepModulesChoice","state" => "".$i];
}
$this->assertEquals($expected, $this->oWizStepModulesChoiceFake->GetWizardSteps());
}
public function testGetWizardStepsWithoutAnyExtension()
{
$this->oWizard->SetParameter('source_dir', __DIR__.'/ressources');
$oExtensionMap = $this->createMock(iTopExtensionsMap::class);
$oExtensionMap->expects(self::any())->method('GetAllExtensionsOptionInfo')->willReturn([]);
$this->oWizStepModulesChoiceFake->setExtensionMap($oExtensionMap);
$expected = [
["class" => "WizStepWelcome","state" => ""],
["class" => "WizStepDetectedInfo","state" => ""],
["class" => "WizStepUpgradeMiscParams","state" => ""],
];
for ($i = 0;$i <= 4; $i++) {
$expected [] = ["class" => "WizStepModulesChoice","state" => "".$i];
}
$this->assertEquals($expected, $this->oWizStepModulesChoiceFake->GetWizardSteps());
}
public function provideGetLatestWizardStateFromStepClass(): array
{
return [
['WizStepWelcome', ''],
['WizStepDetectedInfo', ''],
['WizStepUpgradeMiscParams', ''],
['WizStepModulesChoice', '5'],
];
}
/** @dataProvider provideGetLatestWizardStateFromStepClass */
public function testGetLatestWizardStateFromStepClass(string $sStepClass, string $sExpectedState): void
{
$aSteps = [
['class' => 'WizStepWelcome', 'state' => ''],
['class' => 'WizStepDetectedInfo', 'state' => ''],
['class' => 'WizStepUpgradeMiscParams', 'state' => ''],
['class' => 'WizStepModulesChoice', 'state' => '0'],
['class' => 'WizStepModulesChoice', 'state' => '1'],
['class' => 'WizStepModulesChoice', 'state' => '2'],
['class' => 'WizStepModulesChoice', 'state' => '3'],
['class' => 'WizStepModulesChoice', 'state' => '4'],
['class' => 'WizStepModulesChoice', 'state' => '5'],
];
$this->oWizard->SetWizardSteps($aSteps);
$oWizardState = $this->oWizard->GetLatestWizardStateFromStepClass($sStepClass);
$this->assertEquals(new WizardState($sStepClass, $sExpectedState), $oWizardState);
}
}