You are here

class Tests in Drupal 7 to 8/9 Module Upgrader 8

Same name in this branch
  1. 8 src/Plugin/DMU/Analyzer/Tests.php \Drupal\drupalmoduleupgrader\Plugin\DMU\Analyzer\Tests
  2. 8 src/Plugin/DMU/Converter/Tests.php \Drupal\drupalmoduleupgrader\Plugin\DMU\Converter\Tests

Plugin annotation


@Converter(
 id = "tests",
 description = @Translation("Modifies test classes.")
)

Hierarchy

Expanded class hierarchy of Tests

File

src/Plugin/DMU/Converter/Tests.php, line 24

Namespace

Drupal\drupalmoduleupgrader\Plugin\DMU\Converter
View source
class Tests extends ConverterBase {
  private $target;

  /**
   * {@inheritdoc}
   */
  public function isExecutable(TargetInterface $target) {
    foreach ([
      'DrupalTestCase',
      'DrupalWebTestCase',
    ] as $parent_class) {
      if ($target
        ->getIndexer('class')
        ->getQuery()
        ->condition('parent', $parent_class)
        ->countQuery()
        ->execute()) {
        return TRUE;
      }
    }
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function convert(TargetInterface $target) {
    $this->target = $target;
    $mapping = [
      'DrupalWebTestCase' => 'convertWeb',
      'AJAXTestCase' => 'convertAjax',
    ];
    foreach ($mapping as $parent_class => $convert_method) {
      $test_files = $target
        ->getIndexer('class')
        ->getQuery([
        'file',
      ])
        ->condition('parent', $parent_class)
        ->execute()
        ->fetchCol();
      foreach ($test_files as $test_file) {

        /** @var \Pharborist\Objects\Classnode[] $tests */
        $tests = $target
          ->open($test_file)
          ->find(Filter::isInstanceOf('\\Pharborist\\Objects\\SingleInheritanceNode'))
          ->toArray();
        foreach ($tests as $test) {
          if ((string) $test
            ->getExtends() === $parent_class) {
            $this
              ->{$convert_method}($test);
          }
        }
      }
    }
  }

  /**
   * Converts a single web test.
   *
   * @param \Pharborist\Objects\ClassNode $test
   */
  public function convertWeb(ClassNode $test) {
    $test
      ->setExtends('\\Drupal\\simpletest\\WebTestBase');
    $this
      ->convertInfo($test);
    $this
      ->setModules($test);
    $this
      ->setProfile($test);
    $this
      ->move($test);
  }

  /**
   * Converts the test's getInfo() method to an annotation.
   *
   * @param \Pharborist\Objects\ClassNode $test
   */
  private function convertInfo(ClassNode $test) {
    $info = $this
      ->extractInfo($test);
    if ($info) {
      $comment = '';
      $comment .= $info['description'] . "\n\n";
      $comment .= '@group ' . $this->target
        ->id();
      if (isset($info['dependencies'])) {
        $comment .= "\n";
        foreach ($info['dependencies'] as $module) {
          $comment .= '@requires module . ' . $module . "\n";
        }
      }
      $test
        ->setDocComment(DocCommentNode::create($comment));
    }
    else {
      $this->log
        ->error('Could not get info for test {class}.', [
        'class' => $test
          ->getName(),
      ]);
    }
  }

  /**
   * Extracts the return value of the test's getInfo() method, if there's no
   * logic in the method.
   *
   * @param \Pharborist\Objects\ClassNode $test
   *
   * @return array|null
   */
  private function extractInfo(ClassNode $test) {
    if ($test
      ->hasMethod('getInfo')) {
      $info = $test
        ->getMethod('getInfo');
      if (!$info
        ->is(new ContainsLogicFilter())) {
        return eval($info
          ->getBody()
          ->getText());
      }
    }
  }

  /**
   * Sets the test's $modules property.
   *
   * @param \Pharborist\Objects\ClassNode $test
   */
  private function setModules(ClassNode $test) {
    $modules = $this
      ->extractModules($test);
    if ($modules) {

      // @todo Use ClassNode::createProperty() when #124 lands in Pharborist
      $property = Parser::parseSnippet('class Foo { public static $modules = ["' . implode('", "', $modules) . '"]; }')
        ->getBody()
        ->firstChild()
        ->remove();
      $test
        ->appendProperty($property);
    }
  }

  /**
   * Extracts every module required by a web test by scanning its calls
   * to parent::setUp().
   *
   * @param \Pharborist\Objects\ClassNode $test
   *
   * @return string[]
   *   Array of modules set up by this module.
   */
  private function extractModules(ClassNode $test) {
    $modules = [];
    $test
      ->find(Filter::isClassMethodCall('parent', 'setUp'))
      ->filter(function (ClassMethodCallNode $call) {
      return sizeof($call
        ->getArguments()) > 0;
    })
      ->each(function (ClassMethodCallNode $call) use (&$modules) {
      foreach ($call
        ->getArguments() as $argument) {
        if ($argument instanceof StringNode) {
          $modules[] = $argument
            ->toValue();
        }
      }
      $call
        ->clearArguments();
    });
    return array_unique($modules);
  }

  /**
   * Sets the test's $profile property.
   *
   * @param \Pharborist\Objects\ClassNode $test
   */
  private function setProfile(ClassNode $test) {
    if (!$test
      ->hasProperty('profile')) {
      $test
        ->appendProperty(ClassMemberNode::create('profile', StringNode::create("'standard'"), 'protected'));
    }
  }
  public function move(ClassNode $test) {
    $ns = 'Drupal\\' . $this->target
      ->id() . '\\Tests';
    RootNode::create($ns)
      ->getNamespace($ns)
      ->append($test
      ->remove());
    WhitespaceNode::create("\n\n")
      ->insertBefore($test);
    $this
      ->writeClass($this->target, $test);
  }

  /**
   * Converts a single Ajax test.
   *
   * @param \Pharborist\Objects\ClassNode $test
   */
  public function convertAjax(ClassNode $test) {
    $test
      ->setExtends('\\Drupal\\system\\Tests\\Ajax\\AjaxTestBase');
    $this
      ->setModules($test);
    $this
      ->move($test);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ConverterBase::buildFixMe protected function Builds a FIXME notice using either the text in the plugin definition, or passed-in text.
ConverterBase::DOC_COMMENT constant
ConverterBase::executeHook protected function Executes the target module's implementation of the specified hook, and returns the result.
ConverterBase::implement protected function Creates an empty implementation of a hook.
ConverterBase::LINE_COMMENT constant
ConverterBase::parse protected function Parses a generated class into a syntax tree.
ConverterBase::rewriteFunction protected function Parametrically rewrites a function.
ConverterBase::write public function Writes a file to the target module's directory.
ConverterBase::writeClass public function Writes a class to the target module's PSR-4 root.
ConverterBase::writeInfo protected function Writes out arbitrary data in YAML format.
ConverterBase::writeService protected function Writes a service definition to the target module's services.yml file.
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$log protected property
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::create public static function Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface::create 2
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
PluginBase::__construct public function Constructs a \Drupal\Component\Plugin\PluginBase object. Overrides PluginBase::__construct 11
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
Tests::$target private property
Tests::convert public function Performs required conversions. Overrides ConverterInterface::convert
Tests::convertAjax public function Converts a single Ajax test.
Tests::convertInfo private function Converts the test's getInfo() method to an annotation.
Tests::convertWeb public function Converts a single web test.
Tests::extractInfo private function Extracts the return value of the test's getInfo() method, if there's no logic in the method.
Tests::extractModules private function Extracts every module required by a web test by scanning its calls to parent::setUp().
Tests::isExecutable public function Returns if this conversion applies to the target module. If FALSE, the convert() method will not be called. Overrides ConverterBase::isExecutable
Tests::move public function
Tests::setModules private function Sets the test's $modules property.
Tests::setProfile private function Sets the test's $profile property.