From b67915ce913f04540ce318f3ecfb2375366c1770 Mon Sep 17 00:00:00 2001
From: phenaproxima <phenaproxima@205645.no-reply.drupal.org>
Date: Tue, 8 Feb 2022 17:50:07 +0000
Subject: [PATCH] Issue #3263155 by phenaproxima: Remove confusing, duplicative
 code in kernel tests

---
 .../Kernel/PackageManagerKernelTestBase.php   | 42 +++++++++++++----
 .../Kernel/AutomaticUpdatesKernelTestBase.php | 34 +++++++++++---
 .../ReadinessValidationManagerTest.php        | 10 ++--
 .../StagedDatabaseUpdateValidatorTest.php     | 15 +-----
 .../StagedProjectsValidatorTest.php           | 47 ++-----------------
 tests/src/Kernel/UpdaterTest.php              |  9 +---
 6 files changed, 72 insertions(+), 85 deletions(-)

diff --git a/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php b/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
index c75251baf1..647878fcae 100644
--- a/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
+++ b/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
@@ -221,17 +221,9 @@ END,
       'stage' => [],
     ];
     $root = vfsStream::create($tree, $this->vfsRoot)->url();
-    $active_dir = "$root/active";
     TestStage::$stagingRoot = "$root/stage";
 
-    $path_locator = $this->prophesize(PathLocator::class);
-    $path_locator->getProjectRoot()->willReturn($active_dir);
-    $path_locator->getWebRoot()->willReturn('');
-    $path_locator->getVendorDirectory()->willReturn("$active_dir/vendor");
-
-    // We won't need the prophet anymore.
-    $path_locator = $path_locator->reveal();
-    $this->container->set('package_manager.path_locator', $path_locator);
+    $path_locator = $this->mockPathLocator("$root/active");
 
     // Since the path locator now points to a virtual file system, we need to
     // replace the disk space validator with a test-only version that bypasses
@@ -251,6 +243,36 @@ END,
     $this->container->set('package_manager.validator.disk_space', $validator);
   }
 
+  /**
+   * Mocks the path locator and injects it into the service container.
+   *
+   * @param string $project_root
+   *   The project root.
+   * @param string|null $vendor_dir
+   *   (optional) The vendor directory. Defaults to `$project_root/vendor`.
+   * @param string $web_root
+   *   (optional) The web root, relative to the project root. Defaults to ''
+   *   (i.e., same as the project root).
+   *
+   * @return \Drupal\package_manager\PathLocator
+   *   The mocked path locator.
+   */
+  protected function mockPathLocator(string $project_root, string $vendor_dir = NULL, string $web_root = ''): PathLocator {
+    if (empty($vendor_dir)) {
+      $vendor_dir = $project_root . '/vendor';
+    }
+    $path_locator = $this->prophesize(PathLocator::class);
+    $path_locator->getProjectRoot()->willReturn($project_root);
+    $path_locator->getVendorDirectory()->willReturn($vendor_dir);
+    $path_locator->getWebRoot()->willReturn($web_root);
+
+    // We don't need the prophet anymore.
+    $path_locator = $path_locator->reveal();
+    $this->container->set('package_manager.path_locator', $path_locator);
+
+    return $path_locator;
+  }
+
 }
 
 /**
@@ -268,7 +290,7 @@ class TestStage extends Stage {
   /**
    * {@inheritdoc}
    */
-  protected static function getStagingRoot(): string {
+  public static function getStagingRoot(): string {
     return static::$stagingRoot ?: parent::getStagingRoot();
   }
 
diff --git a/tests/src/Kernel/AutomaticUpdatesKernelTestBase.php b/tests/src/Kernel/AutomaticUpdatesKernelTestBase.php
index 2721388e30..454ac6bb5d 100644
--- a/tests/src/Kernel/AutomaticUpdatesKernelTestBase.php
+++ b/tests/src/Kernel/AutomaticUpdatesKernelTestBase.php
@@ -3,10 +3,12 @@
 namespace Drupal\Tests\automatic_updates\Kernel;
 
 use Drupal\automatic_updates\CronUpdater;
+use Drupal\automatic_updates\Updater;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\package_manager\Exception\StageValidationException;
 use Drupal\Tests\automatic_updates\Traits\ValidationTestTrait;
 use Drupal\Tests\package_manager\Kernel\PackageManagerKernelTestBase;
+use Drupal\Tests\package_manager\Kernel\TestStage;
 use GuzzleHttp\Client;
 use GuzzleHttp\Handler\MockHandler;
 use GuzzleHttp\HandlerStack;
@@ -97,6 +99,17 @@ abstract class AutomaticUpdatesKernelTestBase extends PackageManagerKernelTestBa
     if ($this->client) {
       $container->set('http_client', $this->client);
     }
+
+    // Use the test-only implementations of the regular and cron updaters.
+    $overrides = [
+      'automatic_updates.updater' => TestUpdater::class,
+      'automatic_updates.cron_updater' => TestCronUpdater::class,
+    ];
+    foreach ($overrides as $service_id => $class) {
+      if ($container->hasDefinition($service_id)) {
+        $container->getDefinition($service_id)->setClass($class);
+      }
+    }
   }
 
   /**
@@ -118,22 +131,29 @@ abstract class AutomaticUpdatesKernelTestBase extends PackageManagerKernelTestBa
 }
 
 /**
- * A test-only version of the cron updater to expose internal methods.
+ * A test-only version of the regular updater to override internals.
  */
-class TestCronUpdater extends CronUpdater {
+class TestUpdater extends Updater {
 
   /**
-   * The directory where staging areas will be created.
-   *
-   * @var string
+   * {@inheritdoc}
    */
-  public static $stagingRoot;
+  protected static function getStagingRoot(): string {
+    return TestStage::getStagingRoot();
+  }
+
+}
+
+/**
+ * A test-only version of the cron updater to override and expose internals.
+ */
+class TestCronUpdater extends CronUpdater {
 
   /**
    * {@inheritdoc}
    */
   protected static function getStagingRoot(): string {
-    return static::$stagingRoot ?: parent::getStagingRoot();
+    return TestStage::getStagingRoot();
   }
 
   /**
diff --git a/tests/src/Kernel/ReadinessValidation/ReadinessValidationManagerTest.php b/tests/src/Kernel/ReadinessValidation/ReadinessValidationManagerTest.php
index dc86408949..000cfba28d 100644
--- a/tests/src/Kernel/ReadinessValidation/ReadinessValidationManagerTest.php
+++ b/tests/src/Kernel/ReadinessValidation/ReadinessValidationManagerTest.php
@@ -198,20 +198,20 @@ class ReadinessValidationManagerTest extends AutomaticUpdatesKernelTestBase {
    */
   public function testCronSetting(): void {
     $this->enableModules(['automatic_updates']);
-    $stage_class = NULL;
-    $listener = function (ReadinessCheckEvent $event) use (&$stage_class): void {
-      $stage_class = get_class($event->getStage());
+    $stage = NULL;
+    $listener = function (ReadinessCheckEvent $event) use (&$stage): void {
+      $stage = $event->getStage();
     };
     $event_dispatcher = $this->container->get('event_dispatcher');
     $event_dispatcher->addListener(ReadinessCheckEvent::class, $listener);
     $this->container->get('automatic_updates.readiness_validation_manager')->run();
     // By default, updates will be enabled on cron.
-    $this->assertSame(CronUpdater::class, $stage_class);
+    $this->assertInstanceOf(CronUpdater::class, $stage);
     $this->config('automatic_updates.settings')
       ->set('cron', CronUpdater::DISABLED)
       ->save();
     $this->container->get('automatic_updates.readiness_validation_manager')->run();
-    $this->assertSame(Updater::class, $stage_class);
+    $this->assertInstanceOf(Updater::class, $stage);
   }
 
   /**
diff --git a/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php b/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php
index 248dbca5e1..854e572bc9 100644
--- a/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php
+++ b/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php
@@ -2,11 +2,10 @@
 
 namespace Drupal\Tests\automatic_updates\Kernel\ReadinessValidation;
 
-use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\package_manager\Exception\StageValidationException;
 use Drupal\package_manager\ValidationResult;
 use Drupal\Tests\automatic_updates\Kernel\AutomaticUpdatesKernelTestBase;
-use Drupal\Tests\automatic_updates\Kernel\TestCronUpdater;
+use Drupal\Tests\package_manager\Kernel\TestStage;
 
 /**
  * @covers \Drupal\automatic_updates\Validator\StagedDatabaseUpdateValidator
@@ -33,7 +32,7 @@ class StagedDatabaseUpdateValidatorTest extends AutomaticUpdatesKernelTestBase {
   protected function setUp(): void {
     parent::setUp();
 
-    TestCronUpdater::$stagingRoot = $this->vfsRoot->url();
+    TestStage::$stagingRoot = $this->vfsRoot->url();
 
     /** @var \Drupal\Tests\automatic_updates\Kernel\TestCronUpdater $updater */
     $updater = $this->container->get('automatic_updates.cron_updater');
@@ -65,16 +64,6 @@ class StagedDatabaseUpdateValidatorTest extends AutomaticUpdatesKernelTestBase {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function register(ContainerBuilder $container) {
-    parent::register($container);
-
-    $container->getDefinition('automatic_updates.cron_updater')
-      ->setClass(TestCronUpdater::class);
-  }
-
   /**
    * Tests that no errors are raised if staged files have no DB updates.
    */
diff --git a/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php b/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php
index 8390b8294a..edc1146f48 100644
--- a/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php
+++ b/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php
@@ -2,12 +2,10 @@
 
 namespace Drupal\Tests\automatic_updates\Kernel\ReadinessValidation;
 
-use Drupal\automatic_updates\Updater;
-use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\package_manager\Event\PreApplyEvent;
 use Drupal\package_manager\Exception\StageValidationException;
-use Drupal\package_manager\PathLocator;
 use Drupal\Tests\automatic_updates\Kernel\AutomaticUpdatesKernelTestBase;
+use Drupal\Tests\package_manager\Kernel\TestStage;
 use org\bovigo\vfs\vfsStream;
 use Symfony\Component\Filesystem\Filesystem;
 
@@ -33,16 +31,6 @@ class StagedProjectsValidatorTest extends AutomaticUpdatesKernelTestBase {
     parent::setUp();
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function register(ContainerBuilder $container) {
-    parent::register($container);
-
-    $container->getDefinition('automatic_updates.updater')
-      ->setClass(TestUpdater::class);
-  }
-
   /**
    * Runs the validator under test against an arbitrary pair of directories.
    *
@@ -55,11 +43,7 @@ class StagedProjectsValidatorTest extends AutomaticUpdatesKernelTestBase {
    *   The validation results.
    */
   private function validate(string $active_dir, string $stage_dir): array {
-    $locator = $this->prophesize(PathLocator::class);
-
-    $locator->getProjectRoot()->willReturn($active_dir);
-    $locator->getWebRoot()->willReturn('');
-    $locator->getVendorDirectory()->willReturn($active_dir);
+    $this->mockPathLocator($active_dir, $active_dir);
 
     $stage_dir_exists = is_dir($stage_dir);
     if ($stage_dir_exists) {
@@ -68,16 +52,14 @@ class StagedProjectsValidatorTest extends AutomaticUpdatesKernelTestBase {
       // subdirectory using the stage ID after it is created below.
       $vendor = vfsStream::newDirectory('au_stage');
       $this->vfsRoot->addChild($vendor);
-      TestUpdater::$stagingRoot = $vendor->url();
+      TestStage::$stagingRoot = $vendor->url();
     }
     else {
       // If we are testing non-existent staging directory we can use the path
       // directly.
-      TestUpdater::$stagingRoot = $stage_dir;
+      TestStage::$stagingRoot = $stage_dir;
     }
 
-    $this->container->set('package_manager.path_locator', $locator->reveal());
-
     $updater = $this->container->get('automatic_updates.updater');
     $stage_id = $updater->begin(['drupal' => '9.8.1']);
     if ($stage_dir_exists) {
@@ -213,24 +195,3 @@ class StagedProjectsValidatorTest extends AutomaticUpdatesKernelTestBase {
   }
 
 }
-
-/**
- * A test-only version of the updater.
- */
-class TestUpdater extends Updater {
-
-  /**
-   * The directory where staging areas will be created.
-   *
-   * @var string
-   */
-  public static $stagingRoot;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected static function getStagingRoot(): string {
-    return static::$stagingRoot ?: parent::getStagingRoot();
-  }
-
-}
diff --git a/tests/src/Kernel/UpdaterTest.php b/tests/src/Kernel/UpdaterTest.php
index aabf82e587..0d678d9c00 100644
--- a/tests/src/Kernel/UpdaterTest.php
+++ b/tests/src/Kernel/UpdaterTest.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\Tests\automatic_updates\Kernel;
 
-use Drupal\package_manager\PathLocator;
 use Drupal\Tests\user\Traits\UserCreationTrait;
 
 /**
@@ -45,11 +44,7 @@ class UpdaterTest extends AutomaticUpdatesKernelTestBase {
     // lock file should be scanned to determine the core packages, which should
     // result in drupal/core-recommended being updated.
     $fixture_dir = __DIR__ . '/../../fixtures/fake-site';
-    $locator = $this->prophesize(PathLocator::class);
-    $locator->getProjectRoot()->willReturn($fixture_dir);
-    $locator->getWebRoot()->willReturn('');
-    $locator->getVendorDirectory()->willReturn($fixture_dir);
-    $this->container->set('package_manager.path_locator', $locator->reveal());
+    $locator = $this->mockPathLocator($fixture_dir, $fixture_dir);
 
     $id = $this->container->get('automatic_updates.updater')->begin([
       'drupal' => '9.8.1',
@@ -60,7 +55,7 @@ class UpdaterTest extends AutomaticUpdatesKernelTestBase {
     $kernel->rebuildContainer();
     $this->container = $kernel->getContainer();
     // Keep using the mocked path locator and current user.
-    $this->container->set('package_manager.path_locator', $locator->reveal());
+    $this->container->set('package_manager.path_locator', $locator);
     $this->setCurrentUser($user);
 
     /** @var \Drupal\automatic_updates\Updater $updater */
-- 
GitLab