From 078bd2cbb949c3b065d4e1a2dae7a7ba40f15207 Mon Sep 17 00:00:00 2001
From: phenaproxima <phenaproxima@205645.no-reply.drupal.org>
Date: Thu, 30 Sep 2021 16:34:09 +0000
Subject: [PATCH] Issue #3239889 by phenaproxima, tedbow: Add an offline kernel
 test of UpdateRecommender

---
 .../AutomaticUpdatesFunctionalTestBase.php    | 48 +++++++++++++++
 .../Functional/FileSystemOperationsTest.php   | 18 ++----
 tests/src/Functional/UpdaterFormTest.php      | 27 +--------
 .../Kernel/AutomaticUpdatesKernelTestBase.php | 50 ++++++++++++++++
 tests/src/Kernel/UpdateRecommenderTest.php    | 59 +++++++++++++++++++
 tests/src/Kernel/UpdaterTest.php              | 20 +------
 6 files changed, 166 insertions(+), 56 deletions(-)
 create mode 100644 tests/src/Functional/AutomaticUpdatesFunctionalTestBase.php
 create mode 100644 tests/src/Kernel/AutomaticUpdatesKernelTestBase.php
 create mode 100644 tests/src/Kernel/UpdateRecommenderTest.php

diff --git a/tests/src/Functional/AutomaticUpdatesFunctionalTestBase.php b/tests/src/Functional/AutomaticUpdatesFunctionalTestBase.php
new file mode 100644
index 0000000000..b55aed5bba
--- /dev/null
+++ b/tests/src/Functional/AutomaticUpdatesFunctionalTestBase.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Drupal\Tests\automatic_updates\Functional;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Base class for functional tests of the Automatic Updates module.
+ */
+abstract class AutomaticUpdatesFunctionalTestBase extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['update', 'update_test'];
+
+  /**
+   * Sets the current (running) version of core, as known to the Update module.
+   *
+   * @param string $version
+   *   The current version of core.
+   */
+  protected function setCoreVersion(string $version): void {
+    $this->config('update_test.settings')
+      ->set('system_info.#all.version', $version)
+      ->save();
+  }
+
+  /**
+   * Sets the release metadata file to use when fetching available updates.
+   *
+   * @param string $file
+   *   The path of the XML metadata file to use.
+   */
+  protected function setReleaseMetadata(string $file): void {
+    $this->config('update.settings')
+      ->set('fetch.url', $this->baseUrl . '/automatic-update-test')
+      ->save();
+
+    [$project, $fixture] = explode('.', basename($file, '.xml'), 2);
+    $this->config('update_test.settings')
+      ->set('xml_map', [
+        $project => $fixture,
+      ])
+      ->save();
+  }
+
+}
diff --git a/tests/src/Functional/FileSystemOperationsTest.php b/tests/src/Functional/FileSystemOperationsTest.php
index 0935b37aef..1347ceb3b4 100644
--- a/tests/src/Functional/FileSystemOperationsTest.php
+++ b/tests/src/Functional/FileSystemOperationsTest.php
@@ -6,19 +6,18 @@ use Drupal\automatic_updates\ComposerStager\Cleaner;
 use Drupal\automatic_updates\PathLocator;
 use Drupal\automatic_updates\Updater;
 use Drupal\Core\Site\Settings;
-use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests handling of files and directories during an update.
  *
  * @group automatic_updates
  */
-class FileSystemOperationsTest extends BrowserTestBase {
+class FileSystemOperationsTest extends AutomaticUpdatesFunctionalTestBase {
 
   /**
    * {@inheritdoc}
    */
-  protected static $modules = ['automatic_updates_test', 'update_test'];
+  protected static $modules = ['automatic_updates_test'];
 
   /**
    * {@inheritdoc}
@@ -91,17 +90,8 @@ class FileSystemOperationsTest extends BrowserTestBase {
     // \Drupal\automatic_updates\Validator\UpdateVersionValidator, that need to
     // fetch release metadata. We need to ensure that those HTTP request(s)
     // succeed, so set them up to point to our fake release metadata.
-    $this->config('update_test.settings')
-      ->set('xml_map', [
-        'drupal' => '0.0',
-      ])
-      ->save();
-    $this->config('update.settings')
-      ->set('fetch.url', $this->baseUrl . '/automatic-update-test')
-      ->save();
-    $this->config('update_test.settings')
-      ->set('system_info.#all.version', '9.8.0')
-      ->save();
+    $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.0.0.xml');
+    $this->setCoreVersion('9.8.0');
   }
 
   /**
diff --git a/tests/src/Functional/UpdaterFormTest.php b/tests/src/Functional/UpdaterFormTest.php
index d03229896d..dd5422aaf6 100644
--- a/tests/src/Functional/UpdaterFormTest.php
+++ b/tests/src/Functional/UpdaterFormTest.php
@@ -7,14 +7,13 @@ use Drupal\automatic_updates\Exception\UpdateException;
 use Drupal\automatic_updates\Validation\ValidationResult;
 use Drupal\automatic_updates_test\ReadinessChecker\TestChecker1;
 use Drupal\Tests\automatic_updates\Traits\ValidationTestTrait;
-use Drupal\Tests\BrowserTestBase;
 
 /**
  * @covers \Drupal\automatic_updates\Form\UpdaterForm
  *
  * @group automatic_updates
  */
-class UpdaterFormTest extends BrowserTestBase {
+class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
 
   use ValidationTestTrait;
 
@@ -31,36 +30,14 @@ class UpdaterFormTest extends BrowserTestBase {
     'automatic_updates',
     'automatic_updates_test',
     'package_manager_bypass',
-    'update_test',
   ];
 
-  /**
-   * Sets the running version of core, as known to the Update module.
-   *
-   * @param string $version
-   *   The version of core to set. When checking for updates, this is what the
-   *   Update module will think the running version of core is.
-   */
-  private function setCoreVersion(string $version): void {
-    $this->config('update_test.settings')
-      ->set('system_info.#all.version', $version)
-      ->save();
-  }
-
   /**
    * {@inheritdoc}
    */
   protected function setUp(): void {
     parent::setUp();
-
-    $this->config('update_test.settings')
-      ->set('xml_map', [
-        'drupal' => '0.0',
-      ])
-      ->save();
-    $this->config('update.settings')
-      ->set('fetch.url', $this->baseUrl . '/automatic-update-test')
-      ->save();
+    $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.0.0.xml');
   }
 
   /**
diff --git a/tests/src/Kernel/AutomaticUpdatesKernelTestBase.php b/tests/src/Kernel/AutomaticUpdatesKernelTestBase.php
new file mode 100644
index 0000000000..47ab4b3eed
--- /dev/null
+++ b/tests/src/Kernel/AutomaticUpdatesKernelTestBase.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Drupal\Tests\automatic_updates\Kernel;
+
+use Drupal\KernelTests\KernelTestBase;
+use GuzzleHttp\Client;
+use GuzzleHttp\Handler\MockHandler;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Psr7\Response;
+use GuzzleHttp\Psr7\Utils;
+
+/**
+ * Base class for kernel tests of the Automatic Updates module.
+ */
+abstract class AutomaticUpdatesKernelTestBase extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['update', 'update_test'];
+
+  /**
+   * Sets the current (running) version of core, as known to the Update module.
+   *
+   * @param string $version
+   *   The current version of core.
+   */
+  protected function setCoreVersion(string $version): void {
+    $this->config('update_test.settings')
+      ->set('system_info.#all.version', $version)
+      ->save();
+  }
+
+  /**
+   * Sets the release metadata file to use when fetching available updates.
+   *
+   * @param string $file
+   *   The path of the XML metadata file to use.
+   */
+  protected function setReleaseMetadata(string $file): void {
+    $metadata = Utils::tryFopen($file, 'r');
+    $response = new Response(200, [], Utils::streamFor($metadata));
+    $handler = new MockHandler([$response]);
+    $client = new Client([
+      'handler' => HandlerStack::create($handler),
+    ]);
+    $this->container->set('http_client', $client);
+  }
+
+}
diff --git a/tests/src/Kernel/UpdateRecommenderTest.php b/tests/src/Kernel/UpdateRecommenderTest.php
new file mode 100644
index 0000000000..8de05d44d8
--- /dev/null
+++ b/tests/src/Kernel/UpdateRecommenderTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Drupal\Tests\automatic_updates\Kernel;
+
+use Drupal\automatic_updates\UpdateRecommender;
+
+/**
+ * @covers \Drupal\automatic_updates\UpdateRecommender
+ *
+ * @group automatic_updates
+ */
+class UpdateRecommenderTest extends AutomaticUpdatesKernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'automatic_updates',
+    'package_manager',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->installConfig('update');
+  }
+
+  /**
+   * Tests fetching the recommended release when an update is available.
+   */
+  public function testUpdateAvailable(): void {
+    $this->setCoreVersion('9.8.0');
+    $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.0.0.xml');
+
+    $recommender = new UpdateRecommender();
+    $recommended_release = $recommender->getRecommendedRelease(TRUE);
+    $this->assertNotEmpty($recommended_release);
+    $this->assertSame('9.8.1', $recommended_release->getVersion());
+    // Getting the recommended release again should not trigger another request.
+    $this->assertNotEmpty($recommender->getRecommendedRelease());
+  }
+
+  /**
+   * Tests fetching the recommended release when there is no update available.
+   */
+  public function testNoUpdateAvailable(): void {
+    $this->setCoreVersion('9.8.1');
+    $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.0.0.xml');
+
+    $recommender = new UpdateRecommender();
+    $recommended_release = $recommender->getRecommendedRelease(TRUE);
+    $this->assertNull($recommended_release);
+    // Getting the recommended release again should not trigger another request.
+    $this->assertNull($recommender->getRecommendedRelease());
+  }
+
+}
diff --git a/tests/src/Kernel/UpdaterTest.php b/tests/src/Kernel/UpdaterTest.php
index 7b0080ffe5..2151697e8e 100644
--- a/tests/src/Kernel/UpdaterTest.php
+++ b/tests/src/Kernel/UpdaterTest.php
@@ -2,11 +2,6 @@
 
 namespace Drupal\Tests\automatic_updates\Kernel;
 
-use Drupal\KernelTests\KernelTestBase;
-use GuzzleHttp\Client;
-use GuzzleHttp\Handler\MockHandler;
-use GuzzleHttp\Psr7\Response;
-use GuzzleHttp\Psr7\Utils;
 use Prophecy\Argument;
 
 /**
@@ -14,7 +9,7 @@ use Prophecy\Argument;
  *
  * @group automatic_updates
  */
-class UpdaterTest extends KernelTestBase {
+class UpdaterTest extends AutomaticUpdatesKernelTestBase {
 
   /**
    * {@inheritdoc}
@@ -23,25 +18,16 @@ class UpdaterTest extends KernelTestBase {
     'automatic_updates',
     'automatic_updates_test',
     'package_manager',
-    'update',
-    'update_test',
   ];
 
   /**
    * Tests that correct versions are staged after calling ::begin().
    */
   public function testCorrectVersionsStaged() {
-    // Ensure that the HTTP client will fetch our fake release metadata.
-    $release_data = Utils::tryFopen(__DIR__ . '/../../fixtures/release-history/drupal.0.0.xml', 'r');
-    $response = new Response(200, [], Utils::streamFor($release_data));
-    $handler = new MockHandler([$response]);
-    $client = new Client(['handler' => $handler]);
-    $this->container->set('http_client', $client);
+    $this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.0.0.xml');
 
     // Set the running core version to 9.8.0.
-    $this->config('update_test.settings')
-      ->set('system_info.#all.version', '9.8.0')
-      ->save();
+    $this->setCoreVersion('9.8.0');
 
     $this->container->get('automatic_updates.updater')->begin([
       'drupal' => '9.8.1',
-- 
GitLab