From 8a52604ed96ed60dc2e5cb0aab26ea75d509c8af Mon Sep 17 00:00:00 2001 From: Eric Espie Date: Mon, 16 Mar 2026 17:44:55 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B08761=20-=20Assist=20in=20cleaning=20up?= =?UTF-8?q?=20data=20prior=20to=20uninstalling=20extensions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DeletionPlanServiceTest.php | 253 ++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/DeletionPlanServiceTest.php diff --git a/tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/DeletionPlanServiceTest.php b/tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/DeletionPlanServiceTest.php new file mode 100644 index 000000000..9ae5a98e5 --- /dev/null +++ b/tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/DeletionPlanServiceTest.php @@ -0,0 +1,253 @@ +RequireOnceItopFile('env-production/combodo-data-feature-removal/vendor/autoload.php'); + } + + //--- GetDeletionPlanSummary tests --- + + /** + * Tests that GetDeletionPlanSummary returns an empty array when passed null as input. + */ + public function testGetDeletionPlanSummaryReturnsEmptyArrayWhenNull(): void + { + $oService = DeletionPlanService::GetInstance(); + $aResult = $oService->GetDeletionPlanSummary(null); + + $this->assertIsArray($aResult); + $this->assertEmpty($aResult); + } + + /** + * Tests that GetDeletionPlanSummary returns an empty array when the input class list is empty. + */ + public function testGetDeletionPlanSummaryReturnsEmptyArrayWhenEmptyClasses(): void + { + $oMockService = $this->getMockBuilder(DeletionPlanService::class) + ->disableOriginalConstructor() + ->onlyMethods(['GetDeletionPlan']) + ->getMock(); + + $oDeletionPlan = new DeletionPlan(); + $oMockService->method('GetDeletionPlan')->willReturn($oDeletionPlan); + + DeletionPlanService::SetInstance($oMockService); + + $aResult = $oMockService->GetDeletionPlanSummary([]); + + $this->assertIsArray($aResult); + $this->assertEmpty($aResult); + } + + /** + * Tests GetDeletionPlanSummary for various delete/update scenarios using a data provider. + * Verifies summary output for each class matches expected values. + * + * @dataProvider GetDeletionPlanSummaryWithDeletesProvider + */ + public function testGetDeletionPlanSummaryWithDeletes(array $aToDelete, array $aToUpdate, array $aExpected): void + { + $oDeletionPlan = $this->createMock(DeletionPlan::class); + $oDeletionPlan->method('ListDeletes')->willReturn($aToDelete); + $oDeletionPlan->method('ListUpdates')->willReturn($aToUpdate); + + $oMockService = $this->getMockBuilder(DeletionPlanService::class) + ->disableOriginalConstructor() + ->onlyMethods(['GetDeletionPlan']) + ->getMock(); + + $oMockService->method('GetDeletionPlan')->willReturn($oDeletionPlan); + + $aResult = $oMockService->GetDeletionPlanSummary(['SomeClass']); + + foreach ($aExpected as $sClass => $aExpectedValues) { + $this->assertArrayHasKey($sClass, $aResult); + $this->assertInstanceOf(DeletionPlanSummaryEntity::class, $aResult[$sClass]); + $this->assertEquals($aExpectedValues['iDeleteCount'], $aResult[$sClass]->iDeleteCount); + $this->assertEquals($aExpectedValues['iUpdateCount'], $aResult[$sClass]->iUpdateCount); + $this->assertEquals($aExpectedValues['iMode'], $aResult[$sClass]->iMode); + $this->assertEquals($aExpectedValues['sIssue'], $aResult[$sClass]->sIssue); + } + } + + /** + * Provides multiple scenarios for testGetDeletionPlanSummaryWithDeletes, including deletes, updates, issues, and multiple classes. + * + * @return array + */ + public function GetDeletionPlanSummaryWithDeletesProvider(): array + { + return [ + 'single class with deletes only' => [ + 'aToDelete' => [ + 'Server' => [ + 1 => ['to_delete' => null, 'mode' => DEL_AUTO, 'requested_explicitely' => true], + 2 => ['to_delete' => null, 'mode' => DEL_SILENT, 'requested_explicitely' => false], + ], + ], + 'aToUpdate' => [], + 'aExpected' => [ + 'Server' => [ + 'iDeleteCount' => 2, + 'iUpdateCount' => 0, + 'iMode' => DEL_AUTO, + 'sIssue' => null, + ], + ], + ], + 'single class with deletes and issue' => [ + 'aToDelete' => [ + 'Server' => [ + 1 => ['to_delete' => null, 'mode' => DEL_MANUAL, 'requested_explicitely' => false, 'issue' => 'Cannot delete'], + ], + ], + 'aToUpdate' => [], + 'aExpected' => [ + 'Server' => [ + 'iDeleteCount' => 1, + 'iUpdateCount' => 0, + 'iMode' => DEL_MANUAL, + 'sIssue' => 'Cannot delete', + ], + ], + ], + 'single class with updates only' => [ + 'aToDelete' => [], + 'aToUpdate' => [ + 'Person' => [ + 10 => ['to_reset' => null, 'attributes' => ['org_id' => null]], + 11 => ['to_reset' => null, 'attributes' => ['org_id' => null]], + 12 => ['to_reset' => null, 'attributes' => ['org_id' => null]], + ], + ], + 'aExpected' => [ + 'Person' => [ + 'iDeleteCount' => 0, + 'iUpdateCount' => 3, + 'iMode' => 0, + 'sIssue' => null, + ], + ], + ], + 'class with both deletes and updates' => [ + 'aToDelete' => [ + 'Server' => [ + 1 => ['to_delete' => null, 'mode' => DEL_AUTO, 'requested_explicitely' => true], + ], + ], + 'aToUpdate' => [ + 'Server' => [ + 5 => ['to_reset' => null, 'attributes' => ['org_id' => null]], + ], + ], + 'aExpected' => [ + 'Server' => [ + 'iDeleteCount' => 1, + 'iUpdateCount' => 1, + 'iMode' => DEL_AUTO, + 'sIssue' => null, + ], + ], + ], + 'multiple classes' => [ + 'aToDelete' => [ + 'Server' => [ + 1 => ['to_delete' => null, 'mode' => DEL_AUTO, 'requested_explicitely' => true], + ], + 'NetworkDevice' => [ + 3 => ['to_delete' => null, 'mode' => DEL_SILENT, 'requested_explicitely' => false], + 4 => ['to_delete' => null, 'mode' => DEL_SILENT, 'requested_explicitely' => false], + ], + ], + 'aToUpdate' => [ + 'Person' => [ + 10 => ['to_reset' => null, 'attributes' => ['org_id' => null]], + ], + ], + 'aExpected' => [ + 'Server' => [ + 'iDeleteCount' => 1, + 'iUpdateCount' => 0, + 'iMode' => DEL_AUTO, + 'sIssue' => null, + ], + 'NetworkDevice' => [ + 'iDeleteCount' => 2, + 'iUpdateCount' => 0, + 'iMode' => DEL_SILENT, + 'sIssue' => null, + ], + 'Person' => [ + 'iDeleteCount' => 0, + 'iUpdateCount' => 1, + 'iMode' => 0, + 'sIssue' => null, + ], + ], + ], + ]; + } + + //--- ExecuteDeletionPlan tests --- + + /** + * Tests that ExecuteDeletionPlan throws a DataFeatureRemovalException when the deletion plan contains issues. + */ + public function testExecuteDeletionPlanThrowsExceptionWhenIssuesExist(): void + { + $this->RequireOnceItopFile('datamodels/2.x/combodo-data-feature-removal/src/Helper/DataFeatureRemovalException.php'); + + $oDeletionPlan = $this->createMock(DeletionPlan::class); + $oDeletionPlan->method('GetIssues')->willReturn(['Some issue']); + $oDeletionPlan->method('ListDeletes')->willReturn([]); + $oDeletionPlan->method('ListUpdates')->willReturn([]); + + $oMockService = $this->getMockBuilder(DeletionPlanService::class) + ->disableOriginalConstructor() + ->onlyMethods(['GetDeletionPlan']) + ->getMock(); + + $oMockService->method('GetDeletionPlan')->willReturn($oDeletionPlan); + + $this->expectException(\Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalException::class); + $this->expectExceptionMessage('Deletion Plan cannot be executed due to issues'); + + $oMockService->ExecuteDeletionPlan(['SomeClass']); + } +}