ai_upgrade_assistant-0.2.0-alpha2/tests/src/Unit/Service/UpgradePathGeneratorTest.php

tests/src/Unit/Service/UpgradePathGeneratorTest.php
<?php

namespace Drupal\Tests\ai_upgrade_assistant\Unit\Service;

use Drupal\Tests\UnitTestCase;
use Drupal\ai_upgrade_assistant\Service\UpgradePathGenerator;
use Drupal\ai_upgrade_assistant\Service\MachineLearning\PatternLearningManager;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\State\StateInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Extension\Extension;
use Prophecy\PhpUnit\ProphecyTrait;

/**
 * @coversDefaultClass \Drupal\ai_upgrade_assistant\Service\UpgradePathGenerator
 * @group ai_upgrade_assistant
 */
class UpgradePathGeneratorTest extends UnitTestCase {

  use ProphecyTrait;

  /**
   * The pattern learning manager.
   *
   * @var \Drupal\ai_upgrade_assistant\Service\MachineLearning\PatternLearningManager|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $patternLearning;

  /**
   * The module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $moduleHandler;

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $configFactory;

  /**
   * The state service.
   *
   * @var \Drupal\Core\State\StateInterface|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $state;

  /**
   * The logger factory.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $loggerFactory;

  /**
   * The upgrade path generator.
   *
   * @var \Drupal\ai_upgrade_assistant\Service\UpgradePathGenerator
   */
  protected $upgradePathGenerator;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    $this->patternLearning = $this->prophesize(PatternLearningManager::class);
    $this->moduleHandler = $this->prophesize(ModuleHandlerInterface::class);
    $this->configFactory = $this->prophesize(ConfigFactoryInterface::class);
    $this->state = $this->prophesize(StateInterface::class);
    $this->loggerFactory = $this->prophesize(LoggerChannelFactoryInterface::class);

    $this->upgradePathGenerator = new UpgradePathGenerator(
      $this->patternLearning->reveal(),
      $this->moduleHandler->reveal(),
      $this->configFactory->reveal(),
      $this->state->reveal(),
      $this->loggerFactory->reveal()
    );
  }

  /**
   * @covers ::generateUpgradePath
   */
  public function testGenerateUpgradePath() {
    $module_name = 'test_module';
    $current_version = '8.9.0';
    $target_version = '9.0.0';

    // Mock module info
    $module = $this->prophesize(Extension::class);
    $module->getPath()->willReturn('modules/custom/test_module');
    $module->info = [
      'name' => 'Test Module',
      'dependencies' => ['system (>=8.9.0)'],
    ];

    $this->moduleHandler->getModule($module_name)->willReturn($module->reveal());

    // Mock pattern learning
    $patterns = [
      [
        'type' => 'api_call',
        'pattern' => 'drupal_set_message',
        'context' => ['class' => 'TestController'],
      ],
    ];

    $prediction = [
      'confidence' => 0.95,
      'transformation' => [
        'before' => 'drupal_set_message($message)',
        'after' => '\Drupal::messenger()->addMessage($message)',
      ],
    ];

    $this->patternLearning->getModulePatterns($module_name)->willReturn($patterns);
    $this->patternLearning->predictTransformation($patterns[0])->willReturn($prediction);

    // Generate upgrade path
    $path = $this->upgradePathGenerator->generateUpgradePath(
      $module_name,
      $current_version,
      $target_version
    );

    // Verify basic path structure
    $this->assertIsArray($path);
    $this->assertEquals($module_name, $path['module']);
    $this->assertEquals($current_version, $path['current_version']);
    $this->assertEquals($target_version, $path['target_version']);
    $this->assertArrayHasKey('steps', $path);
    $this->assertArrayHasKey('dependencies', $path);
    $this->assertArrayHasKey('risks', $path);
    $this->assertArrayHasKey('estimated_effort', $path);
    $this->assertArrayHasKey('metadata', $path);

    // Verify steps
    $this->assertNotEmpty($path['steps']);
    $found_api_step = false;
    foreach ($path['steps'] as $step) {
      if ($step['type'] === 'pattern_transformation') {
        $found_api_step = true;
        $this->assertEquals(0.95, $step['confidence']);
        $this->assertTrue($step['automated']);
      }
    }
    $this->assertTrue($found_api_step, 'API transformation step not found');

    // Verify dependencies
    $this->assertArrayHasKey('required', $path['dependencies']);
    $this->assertNotEmpty($path['dependencies']['required']);
    $this->assertEquals('system', $path['dependencies']['required'][0]['name']);
  }

  /**
   * @covers ::analyzeVersionChanges
   */
  public function testAnalyzeVersionChanges() {
    $changes = $this->callProtectedMethod(
      $this->upgradePathGenerator,
      'analyzeVersionChanges',
      ['8.9.0', '9.0.0']
    );

    $this->assertIsArray($changes);
    $this->assertArrayHasKey('9.0.0', $changes);
    $this->assertArrayHasKey('api_changes', $changes['9.0.0']);
    $this->assertArrayHasKey('deprecated_features', $changes['9.0.0']);
    $this->assertArrayHasKey('new_features', $changes['9.0.0']);
    $this->assertArrayHasKey('breaking_changes', $changes['9.0.0']);
  }

  /**
   * @covers ::optimizeUpgradePath
   */
  public function testOptimizeUpgradePath() {
    $steps = [
      [
        'type' => 'pattern_transformation',
        'confidence' => 0.8,
        'version' => '9.0.0',
      ],
      [
        'type' => 'breaking_change',
        'version' => '9.0.0',
      ],
      [
        'type' => 'api_update',
        'version' => '9.0.0',
      ],
    ];

    $optimized = $this->callProtectedMethod(
      $this->upgradePathGenerator,
      'optimizeUpgradePath',
      [$steps]
    );

    // Verify step ordering (breaking_change should be first)
    $this->assertEquals('breaking_change', $optimized[0]['type']);
  }

  /**
   * @covers ::assessRisks
   */
  public function testAssessRisks() {
    $steps = [
      [
        'type' => 'breaking_change',
        'description' => 'Major API change',
      ],
      [
        'type' => 'pattern_transformation',
        'description' => 'Update API call',
        'confidence' => 0.9,
      ],
    ];

    $assessment = $this->callProtectedMethod(
      $this->upgradePathGenerator,
      'assessRisks',
      ['test_module', $steps]
    );

    $this->assertArrayHasKey('risks', $assessment);
    $this->assertArrayHasKey('effort', $assessment);
    $this->assertNotEmpty($assessment['risks']);

    // High risk step should be included
    $found_high_risk = false;
    foreach ($assessment['risks'] as $risk) {
      if ($risk['level'] === 'high') {
        $found_high_risk = true;
        break;
      }
    }
    $this->assertTrue($found_high_risk, 'High risk step not found in assessment');
  }

  /**
   * @covers ::calculateConfidenceScore
   */
  public function testCalculateConfidenceScore() {
    $steps = [
      [
        'type' => 'breaking_change',
        'automated' => false,
      ],
      [
        'type' => 'pattern_transformation',
        'confidence' => 0.95,
        'automated' => true,
      ],
    ];

    $score = $this->callProtectedMethod(
      $this->upgradePathGenerator,
      'calculateConfidenceScore',
      [$steps]
    );

    $this->assertIsFloat($score);
    $this->assertGreaterThan(0, $score);
    $this->assertLessThanOrEqual(1, $score);
  }

  /**
   * Helper method to call protected methods.
   */
  protected function callProtectedMethod($object, $method, array $args) {
    $reflection = new \ReflectionClass(get_class($object));
    $method = $reflection->getMethod($method);
    $method->setAccessible(true);
    return $method->invokeArgs($object, $args);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc