diff --git a/composer.json b/composer.json
index a79cf4cb0cdefb7e5ba4f768e04c8420ea9f2d8a..8e4fac63342238c93073c9306f6aa8b417a99b17 100644
--- a/composer.json
+++ b/composer.json
@@ -153,7 +153,7 @@
         "drupal/rebuild_cache_access": "1.7",
         "drupal/recaptcha": "3.1",
         "drupal/recaptcha_v3": "^1.4",
-        "drupal/redirect": "1.6",
+        "drupal/redirect": "1.8",
         "drupal/roleassign": "1.0.0-beta1",
         "drupal/scheduler": "1.3",
         "drupal/simple_gmap": "3.0.1",
diff --git a/composer.lock b/composer.lock
index af6ea3061902fcb188d0d1a189fad51600ef4857..b738535168f4d9f1b2e056f0969283741c8b2da5 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "00b3339b124e176f69a985ebf27eaa8c",
+    "content-hash": "281e458b48bd7024a28b7013a9e5aad2",
     "packages": [
         {
             "name": "alchemy/zippy",
@@ -6661,26 +6661,26 @@
         },
         {
             "name": "drupal/redirect",
-            "version": "1.6.0",
+            "version": "1.8.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/redirect.git",
-                "reference": "8.x-1.6"
+                "reference": "8.x-1.8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/redirect-8.x-1.6.zip",
-                "reference": "8.x-1.6",
-                "shasum": "f848e001deac8425ae57d4b9397087c491d37294"
+                "url": "https://ftp.drupal.org/files/projects/redirect-8.x-1.8.zip",
+                "reference": "8.x-1.8",
+                "shasum": "a7a440423434472ff7115ae69df01553f763f839"
             },
             "require": {
-                "drupal/core": "^8.8 || ^9"
+                "drupal/core": "^9.2 || ^10"
             },
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-1.6",
-                    "datestamp": "1589312204",
+                    "version": "8.x-1.8",
+                    "datestamp": "1661806955",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -13181,16 +13181,16 @@
         },
         {
             "name": "symfony/dependency-injection",
-            "version": "v4.4.44",
+            "version": "v4.4.49",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/dependency-injection.git",
-                "reference": "25502a57182ba1e15da0afd64c975cae4d0a1471"
+                "reference": "9065fe97dbd38a897e95ea254eb5ddfe1310f734"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/25502a57182ba1e15da0afd64c975cae4d0a1471",
-                "reference": "25502a57182ba1e15da0afd64c975cae4d0a1471",
+                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/9065fe97dbd38a897e95ea254eb5ddfe1310f734",
+                "reference": "9065fe97dbd38a897e95ea254eb5ddfe1310f734",
                 "shasum": ""
             },
             "require": {
@@ -13247,7 +13247,7 @@
             "description": "Allows you to standardize and centralize the way objects are constructed in your application",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/dependency-injection/tree/v4.4.44"
+                "source": "https://github.com/symfony/dependency-injection/tree/v4.4.49"
             },
             "funding": [
                 {
@@ -13263,7 +13263,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-07-20T09:59:04+00:00"
+            "time": "2022-11-16T16:18:09+00:00"
         },
         {
             "name": "symfony/deprecation-contracts",
@@ -15041,16 +15041,16 @@
         },
         {
             "name": "symfony/psr-http-message-bridge",
-            "version": "v2.1.3",
+            "version": "v2.1.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/psr-http-message-bridge.git",
-                "reference": "d444f85dddf65c7e57c58d8e5b3a4dbb593b1840"
+                "reference": "a125b93ef378c492e274f217874906fb9babdebb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/d444f85dddf65c7e57c58d8e5b3a4dbb593b1840",
-                "reference": "d444f85dddf65c7e57c58d8e5b3a4dbb593b1840",
+                "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/a125b93ef378c492e274f217874906fb9babdebb",
+                "reference": "a125b93ef378c492e274f217874906fb9babdebb",
                 "shasum": ""
             },
             "require": {
@@ -15109,7 +15109,7 @@
             ],
             "support": {
                 "issues": "https://github.com/symfony/psr-http-message-bridge/issues",
-                "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.3"
+                "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.4"
             },
             "funding": [
                 {
@@ -15125,7 +15125,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2022-09-05T10:34:54+00:00"
+            "time": "2022-11-28T22:46:34+00:00"
         },
         {
             "name": "symfony/routing",
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index f5e38062421407fdffa9af75b8a1c35634088bc0..be4b26ef65e596889ce7faf336f843bde3739421 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -6900,27 +6900,27 @@
         },
         {
             "name": "drupal/redirect",
-            "version": "1.6.0",
-            "version_normalized": "1.6.0.0",
+            "version": "1.8.0",
+            "version_normalized": "1.8.0.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/redirect.git",
-                "reference": "8.x-1.6"
+                "reference": "8.x-1.8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/redirect-8.x-1.6.zip",
-                "reference": "8.x-1.6",
-                "shasum": "f848e001deac8425ae57d4b9397087c491d37294"
+                "url": "https://ftp.drupal.org/files/projects/redirect-8.x-1.8.zip",
+                "reference": "8.x-1.8",
+                "shasum": "a7a440423434472ff7115ae69df01553f763f839"
             },
             "require": {
-                "drupal/core": "^8.8 || ^9"
+                "drupal/core": "^9.2 || ^10"
             },
             "type": "drupal-module",
             "extra": {
                 "drupal": {
-                    "version": "8.x-1.6",
-                    "datestamp": "1589312204",
+                    "version": "8.x-1.8",
+                    "datestamp": "1661806955",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
@@ -13698,17 +13698,17 @@
         },
         {
             "name": "symfony/dependency-injection",
-            "version": "v4.4.44",
-            "version_normalized": "4.4.44.0",
+            "version": "v4.4.49",
+            "version_normalized": "4.4.49.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/dependency-injection.git",
-                "reference": "25502a57182ba1e15da0afd64c975cae4d0a1471"
+                "reference": "9065fe97dbd38a897e95ea254eb5ddfe1310f734"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/25502a57182ba1e15da0afd64c975cae4d0a1471",
-                "reference": "25502a57182ba1e15da0afd64c975cae4d0a1471",
+                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/9065fe97dbd38a897e95ea254eb5ddfe1310f734",
+                "reference": "9065fe97dbd38a897e95ea254eb5ddfe1310f734",
                 "shasum": ""
             },
             "require": {
@@ -13739,7 +13739,7 @@
                 "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
                 "symfony/yaml": ""
             },
-            "time": "2022-07-20T09:59:04+00:00",
+            "time": "2022-11-16T16:18:09+00:00",
             "type": "library",
             "installation-source": "dist",
             "autoload": {
@@ -13767,7 +13767,7 @@
             "description": "Allows you to standardize and centralize the way objects are constructed in your application",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/dependency-injection/tree/v4.4.44"
+                "source": "https://github.com/symfony/dependency-injection/tree/v4.4.49"
             },
             "funding": [
                 {
@@ -15627,17 +15627,17 @@
         },
         {
             "name": "symfony/psr-http-message-bridge",
-            "version": "v2.1.3",
-            "version_normalized": "2.1.3.0",
+            "version": "v2.1.4",
+            "version_normalized": "2.1.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/psr-http-message-bridge.git",
-                "reference": "d444f85dddf65c7e57c58d8e5b3a4dbb593b1840"
+                "reference": "a125b93ef378c492e274f217874906fb9babdebb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/d444f85dddf65c7e57c58d8e5b3a4dbb593b1840",
-                "reference": "d444f85dddf65c7e57c58d8e5b3a4dbb593b1840",
+                "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/a125b93ef378c492e274f217874906fb9babdebb",
+                "reference": "a125b93ef378c492e274f217874906fb9babdebb",
                 "shasum": ""
             },
             "require": {
@@ -15658,7 +15658,7 @@
             "suggest": {
                 "nyholm/psr7": "For a super lightweight PSR-7/17 implementation"
             },
-            "time": "2022-09-05T10:34:54+00:00",
+            "time": "2022-11-28T22:46:34+00:00",
             "type": "symfony-bridge",
             "extra": {
                 "branch-alias": {
@@ -15698,7 +15698,7 @@
             ],
             "support": {
                 "issues": "https://github.com/symfony/psr-http-message-bridge/issues",
-                "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.3"
+                "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.4"
             },
             "funding": [
                 {
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 1299061afa43b57da0ff0cf677599a7e21c19ec6..f22cf837b10e9c1675ee70366b7ae9ec161e105e 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -3,7 +3,7 @@
         'name' => 'osu-asc-webservices/d8-upstream',
         'pretty_version' => 'dev-master',
         'version' => 'dev-master',
-        'reference' => 'ba6af3568d179c683bcb49150597c4f6eb32e14e',
+        'reference' => '7b38d41b8b6ae95e9b0320d434f2220a4367f2d9',
         'type' => 'project',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -1127,9 +1127,9 @@
             'dev_requirement' => false,
         ),
         'drupal/redirect' => array(
-            'pretty_version' => '1.6.0',
-            'version' => '1.6.0.0',
-            'reference' => '8.x-1.6',
+            'pretty_version' => '1.8.0',
+            'version' => '1.8.0.0',
+            'reference' => '8.x-1.8',
             'type' => 'drupal-module',
             'install_path' => __DIR__ . '/../../web/modules/redirect',
             'aliases' => array(),
@@ -1594,7 +1594,7 @@
         'osu-asc-webservices/d8-upstream' => array(
             'pretty_version' => 'dev-master',
             'version' => 'dev-master',
-            'reference' => 'ba6af3568d179c683bcb49150597c4f6eb32e14e',
+            'reference' => '7b38d41b8b6ae95e9b0320d434f2220a4367f2d9',
             'type' => 'project',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),
@@ -2190,9 +2190,9 @@
             'dev_requirement' => false,
         ),
         'symfony/dependency-injection' => array(
-            'pretty_version' => 'v4.4.44',
-            'version' => '4.4.44.0',
-            'reference' => '25502a57182ba1e15da0afd64c975cae4d0a1471',
+            'pretty_version' => 'v4.4.49',
+            'version' => '4.4.49.0',
+            'reference' => '9065fe97dbd38a897e95ea254eb5ddfe1310f734',
             'type' => 'library',
             'install_path' => __DIR__ . '/../symfony/dependency-injection',
             'aliases' => array(),
@@ -2403,9 +2403,9 @@
             'dev_requirement' => false,
         ),
         'symfony/psr-http-message-bridge' => array(
-            'pretty_version' => 'v2.1.3',
-            'version' => '2.1.3.0',
-            'reference' => 'd444f85dddf65c7e57c58d8e5b3a4dbb593b1840',
+            'pretty_version' => 'v2.1.4',
+            'version' => '2.1.4.0',
+            'reference' => 'a125b93ef378c492e274f217874906fb9babdebb',
             'type' => 'symfony-bridge',
             'install_path' => __DIR__ . '/../symfony/psr-http-message-bridge',
             'aliases' => array(),
diff --git a/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php b/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php
index 3b8086d0931e6c38844e07a886d1c6fb73bf39ef..185a097ebe20bb2b66a4a1ceca23ac0be34efedc 100644
--- a/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php
+++ b/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php
@@ -42,7 +42,7 @@ public function process(ContainerBuilder $container)
 
         $tagsToKeep = $container->hasParameter('container.behavior_describing_tags')
             ? $container->getParameter('container.behavior_describing_tags')
-            : ['container.do_not_inline', 'container.service_locator', 'container.service_subscriber'];
+            : ['container.do_not_inline', 'container.service_locator', 'container.service_subscriber', 'container.service_subscriber.locator'];
 
         foreach ($definitions as [$id, $definition]) {
             $decoratedService = $definition->getDecoratedService();
diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php b/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php
index 5fdbe5686dbfa81017a0f4101e9592f568df5c81..72b093043bf15cff415a6e315b55f0539f01f011 100644
--- a/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php
@@ -39,6 +39,10 @@ protected function processValue($value, $isRoot = false)
             return self::register($this->container, $value->getValues());
         }
 
+        if ($value instanceof Definition) {
+            $value->setBindings(parent::processValue($value->getBindings()));
+        }
+
         if (!$value instanceof Definition || !$value->hasTag('container.service_locator')) {
             return parent::processValue($value, $isRoot);
         }
diff --git a/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php b/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php
index 61650df9f680570a249f08b924ec2b8991104871..b1b6f9ae260ff021af0cce236efb03c57e31b81c 100644
--- a/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php
+++ b/vendor/symfony/psr-http-message-bridge/Factory/PsrHttpFactory.php
@@ -142,7 +142,7 @@ public function createResponse(Response $symfonyResponse)
                     $stream->write($buffer);
 
                     return '';
-                });
+                }, 1);
 
                 $symfonyResponse->sendContent();
                 ob_end_clean();
diff --git a/web/modules/redirect/composer.json b/web/modules/redirect/composer.json
index bae3099f88e23aa4803dd217662f344dd0692542..36ec2347bb756b991e08e2496e2eb0906776f37a 100644
--- a/web/modules/redirect/composer.json
+++ b/web/modules/redirect/composer.json
@@ -4,6 +4,6 @@
   "type": "drupal-module",
   "license": "GPL-2.0-or-later",
   "require": {
-      "drupal/core": "^8.8 || ^9"
+      "drupal/core": "^9.2 || ^10"
   }
 }
diff --git a/web/modules/redirect/modules/redirect_404/redirect_404.info.yml b/web/modules/redirect/modules/redirect_404/redirect_404.info.yml
index fa92a99dc4a12075a821fc1bb3cda090ab72d07e..cbb0af0e4e405ca8fa956844b6536d625e307abc 100644
--- a/web/modules/redirect/modules/redirect_404/redirect_404.info.yml
+++ b/web/modules/redirect/modules/redirect_404/redirect_404.info.yml
@@ -1,14 +1,14 @@
 name: 'Redirect 404'
 type: module
 description: 'Logs 404 errors and allows users to create redirects for often requested but missing pages.'
-core_version_requirement: ^8.8 || ^9
+core_version_requirement: ^9.2 || ^10
 configure: redirect_404.fix_404
 
 dependencies:
  - redirect:redirect
  - drupal:views
 
-# Information added by Drupal.org packaging script on 2020-05-12
-version: '8.x-1.6'
+# Information added by Drupal.org packaging script on 2022-08-29
+version: '8.x-1.8'
 project: 'redirect'
-datestamp: 1589312206
+datestamp: 1661806957
diff --git a/web/modules/redirect/modules/redirect_404/redirect_404.module b/web/modules/redirect/modules/redirect_404/redirect_404.module
index cdcc5ffe73d253605adff65e2f5d86ebc662d4be..6f981394c2892bdc665af60ef9a68d7dff6391d6 100644
--- a/web/modules/redirect/modules/redirect_404/redirect_404.module
+++ b/web/modules/redirect/modules/redirect_404/redirect_404.module
@@ -43,12 +43,22 @@ function redirect_404_form_redirect_settings_form_alter(&$form, FormStateInterfa
     '#description' => t('The maximum number of 404 error logs to keep in the database log. Requires a <a href=":cron">cron maintenance task</a>.', [':cron' => Url::fromRoute('system.status')->toString()])
   ];
 
+  $form['reset_404'] = [
+    '#type' => 'submit',
+    '#value' => t('Clear all 404 log entries'),
+    '#submit' => ['redirect_404_reset_submit'],
+  ];
+
   $ignored_pages = $config->get('pages');
   // Add a new path to be ignored, if there is an ignore argument in the query.
   if ($path_to_ignore = \Drupal::request()->query->get('ignore')) {
-    $ignored_pages .= "\n" . $path_to_ignore;
+    $ignored_pages .= $path_to_ignore;
   }
 
+  // Replace '\r\n' with '\n' to keep consistency in tests.
+  // See: https://www.drupal.org/project/redirect/issues/3244924
+  $ignored_pages = str_replace("\r\n", "\n", $ignored_pages);
+
   $form['ignore_pages'] = [
     '#type' => 'textarea',
     '#title' => t('Pages to ignore'),
@@ -102,3 +112,10 @@ function redirect_404_redirect_presave(Redirect $redirect) {
   // Mark a potentially existing log entry for this path as resolved.
   \Drupal::service('redirect.not_found_storage')->resolveLogRequest($path, $langcode);
 }
+
+/**
+ * Submit Handler for Reseting all the 404 logs from Database.
+ */
+function redirect_404_reset_submit() {
+  \Drupal::database()->truncate('redirect_404')->execute();
+}
diff --git a/web/modules/redirect/modules/redirect_404/src/EventSubscriber/Redirect404Subscriber.php b/web/modules/redirect/modules/redirect_404/src/EventSubscriber/Redirect404Subscriber.php
index f7cd1416ae101907769db7c98d04ce4ba7369945..39d954bec74d26b1319dff5c4305070e198a970f 100644
--- a/web/modules/redirect/modules/redirect_404/src/EventSubscriber/Redirect404Subscriber.php
+++ b/web/modules/redirect/modules/redirect_404/src/EventSubscriber/Redirect404Subscriber.php
@@ -8,10 +8,10 @@
 use Drupal\redirect_404\RedirectNotFoundStorageInterface;
 use Drupal\Core\Path\CurrentPathStack;
 use Symfony\Component\HttpFoundation\RequestStack;
-use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpKernel\Event\ExceptionEvent;
 
 /**
  * An EventSubscriber that listens to redirect 404 errors.
@@ -96,12 +96,12 @@ public static function getSubscribedEvents() {
   /**
    * Logs an exception of 404 Redirect errors.
    *
-   * @param GetResponseForExceptionEvent $event
+   * @param ExceptionEvent $event
    *   Is given by the event dispatcher.
    */
-  public function onKernelException(GetResponseForExceptionEvent $event) {
+  public function onKernelException(ExceptionEvent $event) {
     // Only log page not found (404) errors.
-    if ($event->getException() instanceof NotFoundHttpException) {
+    if ($event->getThrowable() instanceof NotFoundHttpException) {
       $path = $this->currentPath->getPath();
 
       // Ignore paths specified in the redirect settings.
diff --git a/web/modules/redirect/modules/redirect_404/tests/src/Functional/Fix404RedirectUILanguageTest.php b/web/modules/redirect/modules/redirect_404/tests/src/Functional/Fix404RedirectUILanguageTest.php
index eb966b91b7f543d4a6c15c7c5110abacee5dcec4..3a079a4346ee09c68d60f81f07d17ea86ccdd81e 100644
--- a/web/modules/redirect/modules/redirect_404/tests/src/Functional/Fix404RedirectUILanguageTest.php
+++ b/web/modules/redirect/modules/redirect_404/tests/src/Functional/Fix404RedirectUILanguageTest.php
@@ -25,7 +25,7 @@ class Fix404RedirectUILanguageTest extends Redirect404TestBase {
    *
    * @var array
    */
-  public static $modules = ['language'];
+  protected static $modules = ['language'];
 
   /**
    * Admin user's permissions for this test.
@@ -45,7 +45,7 @@ class Fix404RedirectUILanguageTest extends Redirect404TestBase {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
 
     // Enable some languages for this test.
@@ -75,16 +75,16 @@ public function testFix404RedirectList() {
 
     // Go to the "fix 404" page and check the listing.
     $this->drupalGet('admin/config/search/redirect/404');
-    $this->assertText('testing');
+    $this->assertSession()->pageTextContains('testing');
     $this->assertLanguageInTableBody('French');
     // Check the Language view filter uses the default language filter.
-    $this->assertOption('edit-langcode', 'All');
-    $this->assertOption('edit-langcode', 'en');
-    $this->assertOption('edit-langcode', 'de');
-    $this->assertOption('edit-langcode', 'es');
-    $this->assertOption('edit-langcode', 'fr');
-    $this->assertOption('edit-langcode', LanguageInterface::LANGCODE_NOT_SPECIFIED);
-    $this->clickLink(t('Add redirect'));
+    $this->assertSession()->optionExists('edit-langcode', 'All');
+    $this->assertSession()->optionExists('edit-langcode', 'en');
+    $this->assertSession()->optionExists('edit-langcode', 'de');
+    $this->assertSession()->optionExists('edit-langcode', 'es');
+    $this->assertSession()->optionExists('edit-langcode', 'fr');
+    $this->assertSession()->optionExists('edit-langcode', LanguageInterface::LANGCODE_NOT_SPECIFIED);
+    $this->clickLink('Add redirect');
 
     // Check if we generate correct Add redirect url and if the form is
     // pre-filled.
@@ -95,41 +95,41 @@ public function testFix404RedirectList() {
       'source' => 'testing',
     ];
     $parsed_url = UrlHelper::parse($this->getUrl());
-    $this->assertEqual(Url::fromRoute('redirect.add')->setAbsolute()->toString(), $parsed_url['path']);
-    $this->assertEqual($expected_query, $parsed_url['query']);
-    $this->assertFieldByName('redirect_source[0][path]', 'testing');
-    $this->assertOptionSelected('edit-language-0-value', 'fr');
+    $this->assertEquals($parsed_url['path'], Url::fromRoute('redirect.add')->setAbsolute()->toString());
+    $this->assertEquals($parsed_url['query'], $expected_query);
+    $this->assertSession()->fieldValueEquals('redirect_source[0][path]', 'testing');
+    $this->assertSession()->optionExists('edit-language-0-value', 'fr');
     // Save the redirect.
     $edit = ['redirect_redirect[0][uri]' => '/node'];
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    $this->assertUrl('admin/config/search/redirect/404');
-    $this->assertText('There are no 404 errors to fix.');
+    $this->submitForm($edit, 'Save');
+    $this->assertSession()->addressEquals('admin/config/search/redirect/404');
+    $this->assertSession()->pageTextContains('There are no 404 errors to fix.');
     // Check if the redirect works as expected.
     $this->assertRedirect('fr/testing', 'fr/node', 301);
 
     // Test removing a redirect assignment, visit again the non existing page.
     $this->drupalGet('admin/config/search/redirect');
-    $this->assertText('testing');
+    $this->assertSession()->pageTextContains('testing');
     $this->assertLanguageInTableBody('French');
     $this->clickLink('Delete', 0);
-    $this->drupalPostForm(NULL, [], 'Delete');
-    $this->assertUrl('admin/config/search/redirect');
-    $this->assertText('There is no redirect yet.');
+    $this->submitForm([], 'Delete');
+    $this->assertSession()->addressEquals('admin/config/search/redirect');
+    $this->assertSession()->pageTextContains('There is no redirect yet.');
     $this->drupalGet('admin/config/search/redirect/404');
-    $this->assertText('There are no 404 errors to fix.');
+    $this->assertSession()->pageTextContains('There are no 404 errors to fix.');
     // Should be listed again in the 404 overview.
     $this->drupalGet('fr/testing');
     $this->drupalGet('admin/config/search/redirect/404');
     $this->assertLanguageInTableBody('French');
     // Check the error path visit count.
-    $this->assertFieldByXPath('//table/tbody/tr/td[2]', 2);
+    $this->assertSession()->elementTextContains('xpath', '//table/tbody/tr/td[2]', 2);
     $this->clickLink('Add redirect');
     // Save the redirect with a different langcode.
-    $this->assertFieldByName('redirect_source[0][path]', 'testing');
-    $this->assertOptionSelected('edit-language-0-value', 'fr');
+    $this->assertSession()->fieldValueEquals('redirect_source[0][path]', 'testing');
+    $this->assertSession()->optionExists('edit-language-0-value', 'fr');
     $edit['language[0][value]'] = 'es';
-    $this->drupalPostForm(NULL, $edit, 'Save');
-    $this->assertUrl('admin/config/search/redirect/404');
+    $this->submitForm($edit, 'Save');
+    $this->assertSession()->addressEquals('admin/config/search/redirect/404');
     // Should still be listed, redirecting to another language does not resolve
     // the path.
     $this->assertLanguageInTableBody('French');
@@ -147,34 +147,34 @@ public function testFix404RedirectList() {
     $this->assertLanguageInTableBody('French');
     $this->assertLanguageInTableBody('English');
     $this->assertLanguageInTableBody('German');
-    $this->assertText('testing1');
-    $this->assertText('testing2');
-    $this->assertText('testing2?test=1');
-    $this->assertText('testing2?test=2');
+    $this->assertSession()->pageTextContains('testing1');
+    $this->assertSession()->pageTextContains('testing2');
+    $this->assertSession()->pageTextContains('testing2?test=1');
+    $this->assertSession()->pageTextContains('testing2?test=2');
 
     // Test the Language view filter.
     $this->drupalGet('admin/config/search/redirect/404', ['query' => ['langcode' => 'de']]);
-    $this->assertText('English');
+    $this->assertSession()->pageTextContains('English');
     $this->assertNoLanguageInTableBody('English');
     $this->assertLanguageInTableBody('German');
-    $this->assertNoText('testing1');
-    $this->assertText('testing2');
-    $this->assertText('testing2?test=1');
-    $this->assertText('testing2?test=2');
+    $this->assertSession()->pageTextNotContains('testing1');
+    $this->assertSession()->pageTextContains('testing2');
+    $this->assertSession()->pageTextContains('testing2?test=1');
+    $this->assertSession()->pageTextContains('testing2?test=2');
     $this->drupalGet('admin/config/search/redirect/404');
     $this->assertLanguageInTableBody('English');
     $this->assertLanguageInTableBody('German');
-    $this->assertText('testing1');
-    $this->assertText('testing2');
-    $this->assertText('testing2?test=1');
-    $this->assertText('testing2?test=2');
+    $this->assertSession()->pageTextContains('testing1');
+    $this->assertSession()->pageTextContains('testing2');
+    $this->assertSession()->pageTextContains('testing2?test=1');
+    $this->assertSession()->pageTextContains('testing2?test=2');
     $this->drupalGet('admin/config/search/redirect/404', ['query' => ['langcode' => 'en']]);
     $this->assertLanguageInTableBody('English');
     $this->assertNoLanguageInTableBody('German');
-    $this->assertText('testing1');
-    $this->assertNoText('testing2');
-    $this->assertNoText('testing2?test=1');
-    $this->assertNoText('testing2?test=2');
+    $this->assertSession()->pageTextContains('testing1');
+    $this->assertSession()->pageTextNotContains('testing2');
+    $this->assertSession()->pageTextNotContains('testing2?test=1');
+    $this->assertSession()->pageTextNotContains('testing2?test=2');
 
     // Assign a redirect to 'testing1'.
     $this->clickLink('Add redirect');
@@ -184,13 +184,13 @@ public function testFix404RedirectList() {
       'source' => 'testing1',
     ];
     $parsed_url = UrlHelper::parse($this->getUrl());
-    $this->assertEqual(Url::fromRoute('redirect.add')->setAbsolute()->toString(), $parsed_url['path']);
-    $this->assertEqual($expected_query, $parsed_url['query']);
-    $this->assertFieldByName('redirect_source[0][path]', 'testing1');
-    $this->assertOptionSelected('edit-language-0-value', 'en');
+    $this->assertEquals($parsed_url['path'], Url::fromRoute('redirect.add')->setAbsolute()->toString());
+    $this->assertEquals($parsed_url['query'], $expected_query);
+    $this->assertSession()->fieldValueEquals('redirect_source[0][path]', 'testing1');
+    $this->assertSession()->optionExists('edit-language-0-value', 'en');
     $edit = ['redirect_redirect[0][uri]' => '/node'];
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    $this->assertUrl('admin/config/search/redirect/404');
+    $this->submitForm($edit, 'Save');
+    $this->assertSession()->addressEquals('admin/config/search/redirect/404');
     $this->assertNoLanguageInTableBody('English');
     $this->assertLanguageInTableBody('German');
     $this->drupalGet('admin/config/search/redirect');
diff --git a/web/modules/redirect/modules/redirect_404/tests/src/Functional/Fix404RedirectUITest.php b/web/modules/redirect/modules/redirect_404/tests/src/Functional/Fix404RedirectUITest.php
index 2045bf885796f65fafe4031aec8a570beef52269..7b1ca6e8d1aa3a2a1a1ae646ad058b375ca07f99 100644
--- a/web/modules/redirect/modules/redirect_404/tests/src/Functional/Fix404RedirectUITest.php
+++ b/web/modules/redirect/modules/redirect_404/tests/src/Functional/Fix404RedirectUITest.php
@@ -21,8 +21,8 @@ public function testFix404Pages() {
 
     // Go to the "fix 404" page and check the listing.
     $this->drupalGet('admin/config/search/redirect/404');
-    $this->assertText('non-existing0');
-    $this->clickLink(t('Add redirect'));
+    $this->assertSession()->pageTextContains('non-existing0');
+    $this->clickLink('Add redirect');
 
     // Check if we generate correct Add redirect url and if the form is
     // pre-filled.
@@ -33,31 +33,31 @@ public function testFix404Pages() {
       'source' => 'non-existing0',
     ];
     $parsed_url = UrlHelper::parse($this->getUrl());
-    $this->assertEqual(Url::fromRoute('redirect.add')->setAbsolute()->toString(), $parsed_url['path']);
-    $this->assertEqual($expected_query, $parsed_url['query']);
-    $this->assertFieldByName('redirect_source[0][path]', 'non-existing0');
+    $this->assertEquals($parsed_url['path'], Url::fromRoute('redirect.add')->setAbsolute()->toString());
+    $this->assertEquals($parsed_url['query'], $expected_query);
+    $this->assertSession()->fieldValueEquals('redirect_source[0][path]', 'non-existing0');
     // Save the redirect.
     $edit = ['redirect_redirect[0][uri]' => '/node'];
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    $this->assertUrl('admin/config/search/redirect/404');
-    $this->assertText('There are no 404 errors to fix.');
+    $this->submitForm($edit, 'Save');
+    $this->assertSession()->addressEquals('admin/config/search/redirect/404');
+    $this->assertSession()->pageTextContains('There are no 404 errors to fix.');
     // Check if the redirect works as expected.
     $this->drupalGet('non-existing0');
-    $this->assertUrl('node');
+    $this->assertSession()->addressEquals('node');
 
     // Test removing a redirect assignment, visit again the non existing page.
     $this->drupalGet('admin/config/search/redirect');
-    $this->assertText('non-existing0');
+    $this->assertSession()->pageTextContains('non-existing0');
     $this->clickLink('Delete', 0);
-    $this->drupalPostForm(NULL, [], 'Delete');
-    $this->assertUrl('admin/config/search/redirect');
-    $this->assertText('There is no redirect yet.');
+    $this->submitForm([], 'Delete');
+    $this->assertSession()->addressEquals('admin/config/search/redirect');
+    $this->assertSession()->pageTextContains('There is no redirect yet.');
     $this->drupalGet('admin/config/search/redirect/404');
-    $this->assertText('There are no 404 errors to fix.');
+    $this->assertSession()->pageTextContains('There are no 404 errors to fix.');
     // Should be listed again in the 404 overview.
     $this->drupalGet('non-existing0');
     $this->drupalGet('admin/config/search/redirect/404');
-    $this->assertText('non-existing0');
+    $this->assertSession()->pageTextContains('non-existing0');
 
     // Visit multiple non existing pages to test the Redirect 404 View.
     $this->drupalGet('non-existing0?test=1');
@@ -65,36 +65,36 @@ public function testFix404Pages() {
     $this->drupalGet('non-existing1');
     $this->drupalGet('non-existing2');
     $this->drupalGet('admin/config/search/redirect/404');
-    $this->assertText('non-existing0?test=1');
-    $this->assertText('non-existing0?test=2');
-    $this->assertText('non-existing0');
-    $this->assertText('non-existing1');
-    $this->assertText('non-existing2');
+    $this->assertSession()->pageTextContains('non-existing0?test=1');
+    $this->assertSession()->pageTextContains('non-existing0?test=2');
+    $this->assertSession()->pageTextContains('non-existing0');
+    $this->assertSession()->pageTextContains('non-existing1');
+    $this->assertSession()->pageTextContains('non-existing2');
 
     // Test the Path view filter.
     $this->drupalGet('admin/config/search/redirect/404', ['query' => ['path' => 'test=']]);
-    $this->assertText('non-existing0?test=1');
-    $this->assertText('non-existing0?test=2');
-    $this->assertNoText('non-existing1');
-    $this->assertNoText('non-existing2');
+    $this->assertSession()->pageTextContains('non-existing0?test=1');
+    $this->assertSession()->pageTextContains('non-existing0?test=2');
+    $this->assertSession()->pageTextNotContains('non-existing1');
+    $this->assertSession()->pageTextNotContains('non-existing2');
     $this->drupalGet('admin/config/search/redirect/404', ['query' => ['path' => 'existing1']]);
-    $this->assertNoText('non-existing0?test=1');
-    $this->assertNoText('non-existing0?test=2');
-    $this->assertNoText('non-existing0');
-    $this->assertText('non-existing1');
-    $this->assertNoText('non-existing2');
+    $this->assertSession()->pageTextNotContains('non-existing0?test=1');
+    $this->assertSession()->pageTextNotContains('non-existing0?test=2');
+    $this->assertSession()->pageTextNotContains('non-existing0');
+    $this->assertSession()->pageTextContains('non-existing1');
+    $this->assertSession()->pageTextNotContains('non-existing2');
     $this->drupalGet('admin/config/search/redirect/404');
-    $this->assertText('non-existing0?test=1');
-    $this->assertText('non-existing0?test=2');
-    $this->assertText('non-existing0');
-    $this->assertText('non-existing1');
-    $this->assertText('non-existing2');
+    $this->assertSession()->pageTextContains('non-existing0?test=1');
+    $this->assertSession()->pageTextContains('non-existing0?test=2');
+    $this->assertSession()->pageTextContains('non-existing0');
+    $this->assertSession()->pageTextContains('non-existing1');
+    $this->assertSession()->pageTextContains('non-existing2');
     $this->drupalGet('admin/config/search/redirect/404', ['query' => ['path' => 'g2']]);
-    $this->assertNoText('non-existing0?test=1');
-    $this->assertNoText('non-existing0?test=2');
-    $this->assertNoText('non-existing0');
-    $this->assertNoText('non-existing1');
-    $this->assertText('non-existing2');
+    $this->assertSession()->pageTextNotContains('non-existing0?test=1');
+    $this->assertSession()->pageTextNotContains('non-existing0?test=2');
+    $this->assertSession()->pageTextNotContains('non-existing0');
+    $this->assertSession()->pageTextNotContains('non-existing1');
+    $this->assertSession()->pageTextContains('non-existing2');
 
     // Assign a redirect to 'non-existing2'.
     $this->clickLink('Add redirect');
@@ -104,19 +104,19 @@ public function testFix404Pages() {
       'destination' => $destination,
     ];
     $parsed_url = UrlHelper::parse($this->getUrl());
-    $this->assertEqual(Url::fromRoute('redirect.add')->setAbsolute()->toString(), $parsed_url['path']);
-    $this->assertEqual($expected_query, $parsed_url['query']);
-    $this->assertFieldByName('redirect_source[0][path]', 'non-existing2');
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    $this->assertUrl('admin/config/search/redirect/404');
-    $this->assertText('non-existing0?test=1');
-    $this->assertText('non-existing0?test=2');
-    $this->assertText('non-existing0');
-    $this->assertText('non-existing1');
-    $this->assertNoText('non-existing2');
+    $this->assertEquals($parsed_url['path'], Url::fromRoute('redirect.add')->setAbsolute()->toString());
+    $this->assertEquals($parsed_url['query'], $expected_query);
+    $this->assertSession()->fieldValueEquals('redirect_source[0][path]', 'non-existing2');
+    $this->submitForm($edit, 'Save');
+    $this->assertSession()->addressEquals('admin/config/search/redirect/404');
+    $this->assertSession()->pageTextContains('non-existing0?test=1');
+    $this->assertSession()->pageTextContains('non-existing0?test=2');
+    $this->assertSession()->pageTextContains('non-existing0');
+    $this->assertSession()->pageTextContains('non-existing1');
+    $this->assertSession()->pageTextNotContains('non-existing2');
     // Check if the redirect works as expected.
     $this->drupalGet('admin/config/search/redirect');
-    $this->assertText('non-existing2');
+    $this->assertSession()->pageTextContains('non-existing2');
   }
 
   /**
@@ -130,7 +130,7 @@ public function testIgnorePages() {
     // Set some pages to be ignored just for the test.
     $node_to_ignore = '/node/' . $node1->id() . '/test';
     $terms_to_ignore = '/term/*';
-    $pages = $node_to_ignore . "\r\n" . $terms_to_ignore;
+    $pages = $node_to_ignore . "\r\n" . $terms_to_ignore . "\n";
     \Drupal::configFactory()
       ->getEditable('redirect_404.settings')
       ->set('pages', $pages)
@@ -142,22 +142,23 @@ public function testIgnorePages() {
     $this->drupalGet('term/1');
     // Go to the "fix 404" page and check there are no 404 entries.
     $this->drupalGet('admin/config/search/redirect/404');
-    $this->assertNoText('node/' . $node1->id() . '/test');
-    $this->assertNoText('term/foo');
-    $this->assertNoText('term/1');
+    $this->assertSession()->pageTextNotContains('node/' . $node1->id() . '/test');
+    $this->assertSession()->pageTextNotContains('term/foo');
+    $this->assertSession()->pageTextNotContains('term/1');
 
     // Visit non existing but 'unignored' page.
     $this->drupalGet('node/' . $node2->id() . '/test');
     // Go to the "fix 404" page and check there is a 404 entry.
     $this->drupalGet('admin/config/search/redirect/404');
-    $this->assertText('node/' . $node2->id() . '/test');
+    $this->assertSession()->pageTextContains('node/' . $node2->id() . '/test');
 
     // Add this 404 entry to the 'ignore path' list, assert it works properly.
     $path_to_ignore = '/node/' . $node2->id() . '/test';
     $destination = '&destination=admin/config/search/redirect/404';
     $this->clickLink('Ignore');
-    $this->assertUrl('admin/config/search/redirect/settings?ignore=' . $path_to_ignore . $destination);
-    $this->assertText('Resolved the path ' . $path_to_ignore . ' in the database. Please check the ignored list and save the settings.');
+    $this->assertSession()->addressEquals('admin/config/search/redirect/settings?ignore=' . $path_to_ignore . $destination);
+    $this->assertSession()->pageTextContains('Resolved the path ' . $path_to_ignore . ' in the database. Please check the ignored list and save the settings.');
+    $this->assertSession()->fieldValueEquals('ignore_pages', $node_to_ignore . "\n/term/*\n/node/2/test");
     $this->assertSession()->elementContains('css', '#edit-ignore-pages', $node_to_ignore);
     $this->assertSession()->elementContains('css', '#edit-ignore-pages', $terms_to_ignore);
     $this->assertSession()->elementContains('css', '#edit-ignore-pages', $path_to_ignore);
@@ -165,12 +166,12 @@ public function testIgnorePages() {
     // Save the path with wildcard, but omitting the leading slash.
     $nodes_to_ignore = 'node/*';
     $edit = ['ignore_pages' => $nodes_to_ignore . "\r\n" . $terms_to_ignore];
-    $this->drupalPostForm(NULL, $edit, 'Save configuration');
+    $this->submitForm($edit, 'Save configuration');
     // Should redirect to 'Fix 404'. Check the 404 entry is not shown anymore.
-    $this->assertUrl('admin/config/search/redirect/404');
-    $this->assertText('The configuration options have been saved.');
-    $this->assertNoText('node/' . $node2->id() . '/test');
-    $this->assertText('There are no 404 errors to fix.');
+    $this->assertSession()->addressEquals('admin/config/search/redirect/404');
+    $this->assertSession()->pageTextContains('The configuration options have been saved.');
+    $this->assertSession()->pageTextNotContains('node/' . $node2->id() . '/test');
+    $this->assertSession()->pageTextContains('There are no 404 errors to fix.');
 
     // Go back to the settings to check the 'Path to ignore' configurations.
     $this->drupalGet('admin/config/search/redirect/settings');
@@ -180,6 +181,55 @@ public function testIgnorePages() {
     $this->assertSession()->elementContains('css', '#edit-ignore-pages', $terms_to_ignore);
     $this->assertSession()->elementNotContains('css', '#edit-ignore-pages', $node_to_ignore);
     $this->assertSession()->elementNotContains('css', '#edit-ignore-pages', $path_to_ignore);
+
+    // Testing whitelines.
+    $this->drupalGet('llama_page');
+    $this->drupalGet('admin/config/search/redirect/404');
+    $this->assertSession()->pageTextContains('llama_page');
+    $this->clickLink('Ignore');
+    $this->assertSession()->fieldValueEquals('ignore_pages', "/node/*\n/term/*\n/llama_page");
+    $this->getSession()->getPage()->pressButton('Save configuration');
+    $this->drupalGet('admin/config/search/redirect/settings');
+    $this->assertSession()->fieldValueEquals('ignore_pages', "/node/*\n/term/*\n/llama_page");
+  }
+
+  /**
+   * Tests the test_404_reset_submit button to remove all 404 entries.
+   */
+  public function test404ResetSubmit() {
+    // Go to non-existing paths:
+    $this->drupalGet('non-existing0');
+    $this->drupalGet('non-existing0?test=1');
+    $this->drupalGet('non-existing0?test=2');
+    $this->drupalGet('non-existing1');
+    $this->drupalGet('non-existing2');
+    // Go to the "Fix 404" page and check wheter these 404 entries exist:
+    $this->drupalGet('admin/config/search/redirect/404');
+    $this->assertSession()->pageTextContains('non-existing0?test=1');
+    $this->assertSession()->pageTextContains('non-existing0?test=2');
+    $this->assertSession()->pageTextContains('non-existing0');
+    $this->assertSession()->pageTextContains('non-existing1');
+    $this->assertSession()->pageTextContains('non-existing2');
+
+    // Go to the "Settings" page, press the "Clear all 404 log entries" button:
+    $this->drupalGet('admin/config/search/redirect/settings');
+    $this->assertSession()->elementExists('css', '#edit-reset-404');
+    $this->getSession()->getPage()->pressButton('Clear all 404 log entries');
+    // Go to the "Fix 404" page and check wheter these 404 entries DO NOT exist:
+    $this->drupalGet('admin/config/search/redirect/404');
+    $this->assertSession()->pageTextNotContains('non-existing0?test=1');
+    $this->assertSession()->pageTextNotContains('non-existing0?test=2');
+    $this->assertSession()->pageTextNotContains('non-existing0');
+    $this->assertSession()->pageTextNotContains('non-existing1');
+    $this->assertSession()->pageTextNotContains('non-existing2');
+
+    // Ensure new 404 entries are created after clearing:
+    $this->drupalGet('non-existing0');
+    $this->drupalGet('non-existing0?test=1');
+    // Go to the "Fix 404" page and check wheter these 404 entries exist:
+    $this->drupalGet('admin/config/search/redirect/404');
+    $this->assertSession()->pageTextContains('non-existing0');
+    $this->assertSession()->pageTextContains('non-existing0?test=1');
   }
 
 }
diff --git a/web/modules/redirect/modules/redirect_404/tests/src/Functional/Redirect404LogSuppressorTest.php b/web/modules/redirect/modules/redirect_404/tests/src/Functional/Redirect404LogSuppressorTest.php
index d133b77b5d4709b4f73c4f8c8e9596d1cb8fcf77..6cb317dff8cc3fadccc045cec8ea9cb959db97d2 100644
--- a/web/modules/redirect/modules/redirect_404/tests/src/Functional/Redirect404LogSuppressorTest.php
+++ b/web/modules/redirect/modules/redirect_404/tests/src/Functional/Redirect404LogSuppressorTest.php
@@ -16,7 +16,7 @@ class Redirect404LogSuppressorTest extends Redirect404TestBase {
    *
    * @var array
    */
-  public static $modules = ['dblog'];
+  protected static $modules = ['dblog'];
 
   /**
    * A user with some relevant administrative permissions.
@@ -35,7 +35,7 @@ class Redirect404LogSuppressorTest extends Redirect404TestBase {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
 
     // Create users with specific permissions.
@@ -52,31 +52,32 @@ public function setUp() {
   public function testSuppress404Events() {
     // Cause a page not found and an access denied event.
     $this->drupalGet('page-not-found');
-    $this->assertResponse(404);
+    $this->assertSession()->statusCodeEquals(404);
     $this->drupalLogin($this->webUser);
     $this->drupalGet('admin/reports/dblog');
-    $this->assertResponse(403);
+    $this->assertSession()->statusCodeEquals(403);
 
     // Assert the events are logged in the dblog reports.
-    $this->assertEqual(Database::getConnection()->query("SELECT COUNT(*) FROM {watchdog} WHERE type = 'page not found'")->fetchField(), 1);
-    $this->assertEqual(Database::getConnection()->query("SELECT COUNT(*) FROM {watchdog} WHERE type = 'access denied'")->fetchField(), 1);
+    $this->assertEquals(1, Database::getConnection()->query("SELECT COUNT(*) FROM {watchdog} WHERE type = 'page not found'")->fetchField());
+    $this->assertEquals(1, Database::getConnection()->query("SELECT COUNT(*) FROM {watchdog} WHERE type = 'access denied'")->fetchField());
 
     // Login as admin and enable suppress_404 to avoid logging the 404 event.
     $this->drupalLogin($this->adminUser);
     $edit = ['suppress_404' => TRUE];
-    $this->drupalPostForm('admin/config/search/redirect/settings', $edit, 'Save configuration');
+    $this->drupalGet('admin/config/search/redirect/settings');
+    $this->submitForm($edit, 'Save configuration');
 
     // Cause again a page not found and an access denied event.
     $this->drupalGet('page-not-found');
-    $this->assertResponse(404);
+    $this->assertSession()->statusCodeEquals(404);
     $this->drupalLogin($this->webUser);
     $this->drupalGet('admin/reports/dblog');
-    $this->assertResponse(403);
+    $this->assertSession()->statusCodeEquals(403);
 
     // Assert only the new access denied event is logged now.
     $this->drupalLogin($this->adminUser);
-    $this->assertEqual(Database::getConnection()->query("SELECT COUNT(*) FROM {watchdog} WHERE type = 'page not found'")->fetchField(), 1);
-    $this->assertEqual(Database::getConnection()->query("SELECT COUNT(*) FROM {watchdog} WHERE type = 'access denied'")->fetchField(), 2);
+    $this->assertEquals(1, Database::getConnection()->query("SELECT COUNT(*) FROM {watchdog} WHERE type = 'page not found'")->fetchField());
+    $this->assertEquals(2, Database::getConnection()->query("SELECT COUNT(*) FROM {watchdog} WHERE type = 'access denied'")->fetchField());
 
   }
 }
diff --git a/web/modules/redirect/modules/redirect_404/tests/src/Functional/Redirect404TestBase.php b/web/modules/redirect/modules/redirect_404/tests/src/Functional/Redirect404TestBase.php
index f83a7c63c2e7da5d4c231e7d54b5be6ec8f8ff2d..6f875c1db54aeee03c7fe1f03e50fb851388a16e 100644
--- a/web/modules/redirect/modules/redirect_404/tests/src/Functional/Redirect404TestBase.php
+++ b/web/modules/redirect/modules/redirect_404/tests/src/Functional/Redirect404TestBase.php
@@ -15,7 +15,7 @@ abstract class Redirect404TestBase extends BrowserTestBase {
    *
    * @var array
    */
-  public static $modules = [
+  protected static $modules = [
     'redirect_404',
     'node',
     'path',
@@ -50,7 +50,7 @@ abstract class Redirect404TestBase extends BrowserTestBase {
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
 
     // Create an admin user.
diff --git a/web/modules/redirect/modules/redirect_404/tests/src/Kernel/Fix404RedirectCronJobTest.php b/web/modules/redirect/modules/redirect_404/tests/src/Kernel/Fix404RedirectCronJobTest.php
index c25818e4bc165ad83c1eea736ec6ba7533f566a0..ea4e98e4494b3910017f20623e43f042b9169c4a 100644
--- a/web/modules/redirect/modules/redirect_404/tests/src/Kernel/Fix404RedirectCronJobTest.php
+++ b/web/modules/redirect/modules/redirect_404/tests/src/Kernel/Fix404RedirectCronJobTest.php
@@ -17,12 +17,12 @@ class Fix404RedirectCronJobTest extends KernelTestBase {
    *
    * @var array
    */
-  public static $modules = ['redirect_404'];
+  protected static $modules = ['redirect_404'];
 
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  protected function setUp(): void {
     parent::setUp();
     $this->installSchema('redirect_404', 'redirect_404');
 
diff --git a/web/modules/redirect/modules/redirect_404/tests/src/Unit/SqlRedirectNotFoundStorageTest.php b/web/modules/redirect/modules/redirect_404/tests/src/Unit/SqlRedirectNotFoundStorageTest.php
index 42e0224e565a5a87e82918ac958ecf79d8fb7175..424a4966c9ff85006b2c5e42a32253258c6fa592 100644
--- a/web/modules/redirect/modules/redirect_404/tests/src/Unit/SqlRedirectNotFoundStorageTest.php
+++ b/web/modules/redirect/modules/redirect_404/tests/src/Unit/SqlRedirectNotFoundStorageTest.php
@@ -17,25 +17,23 @@ class SqlRedirectNotFoundStorageTest extends UnitTestCase {
   /**
    * Mock database connection.
    *
-   * @var \Drupal\Core\Database\Connection|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\Core\Database\Connection|\PHPUnit\Framework\MockObject\MockObject
    */
   protected $database;
 
   /**
    * Mock config factory.
    *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
+   * @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit\Framework\MockObject\MockObject
    */
   protected $configFactory;
 
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  protected function setUp(): void {
     parent::setUp();
-    $this->database = $this->getMockBuilder(Connection::class)
-      ->disableOriginalConstructor()
-      ->getMock();
+    $this->database = $this->createMock(Connection::class);
   }
 
   /**
diff --git a/web/modules/redirect/modules/redirect_domain/redirect_domain.info.yml b/web/modules/redirect/modules/redirect_domain/redirect_domain.info.yml
index eda49f417f2b5540fccd016e9463ec96753ddcba..dd5150d6d44b526966eef39433f68fa12a919096 100644
--- a/web/modules/redirect/modules/redirect_domain/redirect_domain.info.yml
+++ b/web/modules/redirect/modules/redirect_domain/redirect_domain.info.yml
@@ -1,13 +1,13 @@
 name: 'Redirect Domain'
 type: module
 description: 'Allows users to redirect between domains.'
-core_version_requirement: ^8.8 || ^9
+core_version_requirement: ^9.2 || ^10
 configure: redirect_domain.domain_list
 
 dependencies:
  - redirect:redirect
 
-# Information added by Drupal.org packaging script on 2020-05-12
-version: '8.x-1.6'
+# Information added by Drupal.org packaging script on 2022-08-29
+version: '8.x-1.8'
 project: 'redirect'
-datestamp: 1589312206
+datestamp: 1661806957
diff --git a/web/modules/redirect/modules/redirect_domain/src/EventSubscriber/DomainRedirectRequestSubscriber.php b/web/modules/redirect/modules/redirect_domain/src/EventSubscriber/DomainRedirectRequestSubscriber.php
index b2ebbf303d1c9c0aa3bdf141ee87e06b9f7ed7b4..066869255eac7487e49ca08a6020672bcb5b3251 100644
--- a/web/modules/redirect/modules/redirect_domain/src/EventSubscriber/DomainRedirectRequestSubscriber.php
+++ b/web/modules/redirect/modules/redirect_domain/src/EventSubscriber/DomainRedirectRequestSubscriber.php
@@ -7,8 +7,8 @@
 use Drupal\Core\Routing\TrustedRedirectResponse;
 use Drupal\Core\Url;
 use Drupal\redirect\RedirectChecker;
+use Symfony\Component\HttpKernel\Event\RequestEvent;
 use Symfony\Component\HttpKernel\KernelEvents;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
@@ -62,10 +62,10 @@ public function __construct(ConfigFactoryInterface $config_factory, RedirectChec
   /**
    * Handles the domain redirect if any found.
    *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+   * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
    *   The event to process.
    */
-  public function onKernelRequestCheckDomainRedirect(GetResponseEvent $event) {
+  public function onKernelRequestCheckDomainRedirect(RequestEvent $event) {
     $request = clone $event->getRequest();
 
     if (!$this->redirectChecker->canRedirect($request)) {
@@ -111,12 +111,12 @@ public function onKernelRequestCheckDomainRedirect(GetResponseEvent $event) {
   /**
    * Prior to set the response it check if we can redirect.
    *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+   * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
    *   The event object.
    * @param \Drupal\Core\Url $url
    *   The Url where we want to redirect.
    */
-  protected function setResponse(GetResponseEvent $event, Url $url) {
+  protected function setResponse(RequestEvent $event, Url $url) {
     $request = $event->getRequest();
 
     parse_str($request->getQueryString(), $query);
diff --git a/web/modules/redirect/modules/redirect_domain/tests/src/FunctionalJavascript/RedirectDomainUITest.php b/web/modules/redirect/modules/redirect_domain/tests/src/FunctionalJavascript/RedirectDomainUITest.php
index f3c59c3ac80f47582a3a2c4f6bbf1783342e67a4..40d04699517614c5073bb47afbbf57e9ddef05b9 100644
--- a/web/modules/redirect/modules/redirect_domain/tests/src/FunctionalJavascript/RedirectDomainUITest.php
+++ b/web/modules/redirect/modules/redirect_domain/tests/src/FunctionalJavascript/RedirectDomainUITest.php
@@ -16,7 +16,7 @@ class RedirectDomainUITest extends WebDriverTestBase {
    *
    * @var array
    */
-  public static $modules = [
+  protected static $modules = [
     'redirect_domain',
   ];
 
@@ -38,9 +38,9 @@ public function testDomainRedirect() {
     $this->drupalGet('/admin/config/search/redirect/domain');
 
     // Assert that there are 2 domain redirect fields.
-    $this->assertFieldByName('redirects[0][from]');
-    $this->assertFieldByName('redirects[0][sub_path]');
-    $this->assertFieldByName('redirects[0][destination]');
+    $this->assertSession()->fieldExists('redirects[0][from]');
+    $this->assertSession()->fieldExists('redirects[0][sub_path]');
+    $this->assertSession()->fieldExists('redirects[0][destination]');
 
     // Add another field for new domain redirect.
     $page = $this->getSession()->getPage();
@@ -57,13 +57,13 @@ public function testDomainRedirect() {
     $page->pressButton('Save');
 
     // Check the new domain redirects.
-    $this->assertFieldByName('redirects[0][from]', 'foo.example.org');
-    $this->assertFieldByName('redirects[0][destination]', 'www.example.org/foo');
-    $this->assertFieldByName('redirects[1][from]', 'bar.example.org');
-    $this->assertFieldByName('redirects[1][destination]', 'www.example.org/bar');
+    $this->assertSession()->fieldValueEquals('redirects[0][from]', 'foo.example.org');
+    $this->assertSession()->fieldValueEquals('redirects[0][destination]', 'www.example.org/foo');
+    $this->assertSession()->fieldValueEquals('redirects[1][from]', 'bar.example.org');
+    $this->assertSession()->fieldValueEquals('redirects[1][destination]', 'www.example.org/bar');
 
     // Ensure that the sub paths are correct.
-    $this->assertFieldByName('redirects[0][sub_path]', '/sub-path');
-    $this->assertFieldByName('redirects[1][sub_path]', '/');
+    $this->assertSession()->fieldValueEquals('redirects[0][sub_path]', '/sub-path');
+    $this->assertSession()->fieldValueEquals('redirects[1][sub_path]', '/');
   }
 }
diff --git a/web/modules/redirect/modules/redirect_domain/tests/src/Unit/DomainRedirectRequestSubscriberTest.php b/web/modules/redirect/modules/redirect_domain/tests/src/Unit/DomainRedirectRequestSubscriberTest.php
index 24cc37c0185c46aed151eeb450e17b34eed1e1cc..28884512ea0b063e18b386b3e4291b873840c41a 100644
--- a/web/modules/redirect/modules/redirect_domain/tests/src/Unit/DomainRedirectRequestSubscriberTest.php
+++ b/web/modules/redirect/modules/redirect_domain/tests/src/Unit/DomainRedirectRequestSubscriberTest.php
@@ -10,7 +10,7 @@
 use Drupal\Tests\UnitTestCase;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\Event\RequestEvent;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
 
 /**
@@ -78,9 +78,7 @@ public function testDomainRedirect($request_url, $response_url) {
     ];
 
     // Create a mock redirect checker.
-    $checker = $this->getMockBuilder(RedirectChecker::class)
-      ->disableOriginalConstructor()
-      ->getMock();
+    $checker = $this->createMock(RedirectChecker::class);
     $checker->expects($this->any())
       ->method('canRedirect')
       ->will($this->returnValue(TRUE));
@@ -128,15 +126,14 @@ public function testDomainRedirect($request_url, $response_url) {
    * @param $query_string
    *   The query string in the url.
    *
-   * @return GetResponseEvent
+   * @return RequestEvent
    *   The response for the request.
    */
   protected function getGetResponseEventStub($path_info, $query_string) {
     $request = Request::create($path_info . '?' . $query_string, 'GET', [], [], [], ['SCRIPT_NAME' => 'index.php']);
 
-    $http_kernel = $this->getMockBuilder(HttpKernelInterface::class)
-      ->getMock();
-    return new GetResponseEvent($http_kernel, $request, HttpKernelInterface::MASTER_REQUEST);
+    $http_kernel = $this->createMock(HttpKernelInterface::class);
+    return new RequestEvent($http_kernel, $request, HttpKernelInterface::MASTER_REQUEST);
   }
 
   /**
diff --git a/web/modules/redirect/redirect.api.php b/web/modules/redirect/redirect.api.php
index 9ec1bdff7d4b2f7c394de2aab00247e700577a76..6f442bcac634a5a480f33d1246db4371842c1a2b 100644
--- a/web/modules/redirect/redirect.api.php
+++ b/web/modules/redirect/redirect.api.php
@@ -5,6 +5,8 @@
  * Hooks provided by the Redirect module.
  */
 
+use Drupal\Core\Routing\TrustedRedirectResponse;
+
 /**
  * @defgroup redirect_api_hooks Redirect API Hooks
  * @{
@@ -53,6 +55,31 @@
  * @{
  */
 
+/**
+ * Act on a redirect response when it is triggered.
+ *
+ * This hook is invoked before the response is sent to the user. The redirect
+ * entity itself is sent as well for inspection.
+ *
+ * @param Drupal\Core\Routing\TrustedRedirectResponse $response
+ *   The generated redirect response object before it is delivered.
+ * @param \Drupal\redirect\Entity\Redirect $redirect
+ *   The redirect entity used to generate the response object.
+ *
+ * @ingroup redirect_api_hooks
+ */
+function hook_redirect_response_alter(TrustedRedirectResponse $response, \Drupal\redirect\Entity\Redirect $redirect) {
+  // Set a drupal message.
+  if (!$redirect->getRedirectUrl()->isExternal()) {
+    \Drupal::messenger()->addWarning(t('You are not being directed off-site.'));
+  }
+
+  // If `some condition`, send to Drupal.org.
+  if (FALSE) {
+    $response->setTrustedTargetUrl('http://drupal.org');
+  }
+}
+
 /**
  * Act on redirects being loaded from the database.
  *
@@ -121,22 +148,6 @@ function hook_redirect_prepare($redirect) {
 
 }
 
-/**
- * Act on a redirect being redirected.
- *
- * This hook is invoked from redirect_redirect() before the redirect callback
- * is invoked.
- *
- * @param $redirect
- *   The redirect that is being used for the redirect.
- *
- * @see redirect_redirect()
- * @see drupal_page_is_cacheable()
- * @ingroup redirect_api_hooks
- */
-function hook_redirect_alter($redirect) {
-}
-
 /**
  * @} End of "addtogroup hooks".
  */
diff --git a/web/modules/redirect/redirect.drush.inc b/web/modules/redirect/redirect.drush.inc
index e9bc05892f3af99eecbf75eb8109cd2798823776..af728da72f048a33b0f4ce5dc9fc38df1103e8ff 100644
--- a/web/modules/redirect/redirect.drush.inc
+++ b/web/modules/redirect/redirect.drush.inc
@@ -30,7 +30,7 @@ function drush_redirect_generate_redirects($count = NULL) {
   if (drush_generate_is_number($count) == FALSE) {
     return drush_set_error('DEVEL_GENERATE_INVALID_INPUT', t('Invalid number of redirects.'));
   }
-  module_load_include('inc', 'redirect', 'redirect.generate');
+  \Drupal::moduleHandler()->loadInclude('redirect', 'inc', 'redirect.generate');
   drush_generate_include_devel();
   redirect_run_unprogressive_batch('redirect_generate_redirects_batch_info', $count, drush_get_option('delete'));
 }
diff --git a/web/modules/redirect/redirect.generate.inc b/web/modules/redirect/redirect.generate.inc
index 50bf69b074424d0d3d13d046ae04a94d1ca50db3..315d71d3f9b50104c236e10eb78baa467425a71d 100644
--- a/web/modules/redirect/redirect.generate.inc
+++ b/web/modules/redirect/redirect.generate.inc
@@ -52,7 +52,7 @@ function redirect_generate_redirects_batch_info($count, $delete = FALSE) {
   return [
     'operations' => $operations,
     'finished' => 'redirect_generate_batch_finished',
-    'file' => drupal_get_path('module', 'redirect') . '/redirect.generate.inc',
+    'file' => \Drupal::service('extension.list.module')->getPath('redirect') . '/redirect.generate.inc',
   ];
 }
 
@@ -94,7 +94,7 @@ function redirect_generate_batch_generate($num, array &$context) {
     $context['sandbox']['nids'] = $query->execute()->fetchAllKeyed(0, 0);
   }
 
-  module_load_include('inc', 'devel_generate');
+  \Drupal::moduleHandler()->loadInclude('devel_generate', 'inc');
 
   $limit = 20;
   $types = array_keys(redirect_status_code_options());
diff --git a/web/modules/redirect/redirect.info.yml b/web/modules/redirect/redirect.info.yml
index 687cbe66792686e76434a253973d46639a90706d..3d9b32f75d1130639ada2c51cf4bfca7737e5acf 100644
--- a/web/modules/redirect/redirect.info.yml
+++ b/web/modules/redirect/redirect.info.yml
@@ -1,7 +1,7 @@
 name: Redirect
 type: module
 description: Allows users to redirect from old URLs to new URLs.
-core_version_requirement: ^8.8 || ^9
+core_version_requirement: ^9.2 || ^10
 configure: redirect.settings
 
 dependencies:
@@ -9,7 +9,7 @@ dependencies:
  - drupal:link
  - drupal:views
 
-# Information added by Drupal.org packaging script on 2020-05-12
-version: '8.x-1.6'
+# Information added by Drupal.org packaging script on 2022-08-29
+version: '8.x-1.8'
 project: 'redirect'
-datestamp: 1589312206
+datestamp: 1661806957
diff --git a/web/modules/redirect/redirect.install b/web/modules/redirect/redirect.install
index 536d678eb94fba40f8242a8aebb0fa67f251cf06..be1d130ff394e6f9d0bfe4e0fd2d865552644440 100644
--- a/web/modules/redirect/redirect.install
+++ b/web/modules/redirect/redirect.install
@@ -144,7 +144,7 @@ function redirect_update_8103() {
 
   // Only create if the redirect view doesn't exist and views is enabled.
   if (!View::load('redirect') && \Drupal::moduleHandler()->moduleExists('views')) {
-    $config_path = drupal_get_path('module', 'redirect') . '/config/install/views.view.redirect.yml';
+    $config_path = \Drupal::service('extension.list.module')->getPath('redirect') . '/config/install/views.view.redirect.yml';
     $data = Yaml::parse(file_get_contents($config_path));
     \Drupal::configFactory()->getEditable('views.view.redirect')->setData($data)->save(TRUE);
     $message = 'The new redirect view has been created.';
diff --git a/web/modules/redirect/redirect.module b/web/modules/redirect/redirect.module
index 5d5bae2da5c30c4c830c91f3f7439af6452d0476..18e61cf209812ca5589ab1d7486915c6e85315c8 100644
--- a/web/modules/redirect/redirect.module
+++ b/web/modules/redirect/redirect.module
@@ -30,6 +30,7 @@ function redirect_hook_info() {
     'redirect_update',
     'redirect_delete',
     'redirect_alter',
+    'redirect_response',
   ];
 
   return array_fill_keys($hooks, ['group' => 'redirect']);
@@ -181,7 +182,7 @@ function redirect_delete_by_path($path, $langcode = NULL, $match_subpaths_and_re
   $database = \Drupal::database();
   $query = $database->select('redirect');
   $query->addField('redirect', 'rid');
-  $query_or = new Condition('OR');
+  $query_or = $database->condition('OR');
   $query_or->condition('redirect_source__path', $database->escapeLike($path), 'LIKE');
   if ($match_subpaths_and_redirect) {
     $query_or->condition('redirect_source__path', $database->escapeLike($path . '/') . '%', 'LIKE');
@@ -372,7 +373,9 @@ function redirect_form_node_form_alter(&$form, FormStateInterface $form_state, $
         'destination' => \Drupal::destination()->get(),
       ]),
       'attributes' => [
-        'class' => 'button',
+        'class' => [
+          'button',
+        ],
         'target' => '_blank',
       ],
     ];
diff --git a/web/modules/redirect/src/Entity/Redirect.php b/web/modules/redirect/src/Entity/Redirect.php
index c1796c1fc778092ef2e0bd418810f28425866963..e2b6bafe7ca24dd836d9abe5f73bb2c6a125c396 100644
--- a/web/modules/redirect/src/Entity/Redirect.php
+++ b/web/modules/redirect/src/Entity/Redirect.php
@@ -85,6 +85,11 @@ public static function preCreate(EntityStorageInterface $storage_controller, arr
    * {@inheritdoc}
    */
   public function preSave(EntityStorageInterface $storage_controller) {
+    // Strip any trailing slashes as these are removed when looking for matching
+    // redirects.
+    // @see \Drupal\redirect\EventSubscriber\RedirectRequestSubscriber::onKernelRequestCheckRedirect()
+    $this->redirect_source->path = rtrim($this->redirect_source->path, '/');
+
     // Get the language code directly from the field as language() might not
     // be up to date if the language was just changed.
     $this->set('hash', Redirect::generateHash($this->redirect_source->path, (array) $this->redirect_source->query, $this->get('language')->value));
@@ -207,7 +212,7 @@ public function getRedirect() {
   public function setRedirect($url, array $query = [], array $options = []) {
     $uri = $url . ($query ? '?' . UrlHelper::buildQuery($query) : '');
     $external = UrlHelper::isValid($url, TRUE);
-    $uri = ($external ? $url : 'internal:/' . ltrim($uri, '/'));
+    $uri = ($external ? $uri : 'internal:/' . ltrim($uri, '/'));
     $this->redirect_redirect->set(0, ['uri' => $uri, 'options' => $options]);
   }
 
diff --git a/web/modules/redirect/src/EventSubscriber/RedirectRequestSubscriber.php b/web/modules/redirect/src/EventSubscriber/RedirectRequestSubscriber.php
index f3e35f8cdff64c9b6d48ef7bf5bd7bec988cc87a..b01869d57fc11c98df41f9190394838928a1c394 100644
--- a/web/modules/redirect/src/EventSubscriber/RedirectRequestSubscriber.php
+++ b/web/modules/redirect/src/EventSubscriber/RedirectRequestSubscriber.php
@@ -15,8 +15,8 @@
 use Drupal\redirect\RedirectChecker;
 use Drupal\redirect\RedirectRepository;
 use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Event\RequestEvent;
 use Symfony\Component\HttpKernel\KernelEvents;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\Routing\RequestContext;
 
@@ -105,10 +105,10 @@ public function __construct(RedirectRepository $redirect_repository, LanguageMan
   /**
    * Handles the redirect if any found.
    *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+   * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
    *   The event to process.
    */
-  public function onKernelRequestCheckRedirect(GetResponseEvent $event) {
+  public function onKernelRequestCheckRedirect(RequestEvent $event) {
     // Get a clone of the request. During inbound processing the request
     // can be altered. Allowing this here can lead to unexpected behavior.
     // For example the path_processor.files inbound processor provided by
@@ -122,7 +122,7 @@ public function onKernelRequestCheckRedirect(GetResponseEvent $event) {
     }
 
     // Get URL info and process it to be used for hash generation.
-    parse_str($request->getQueryString(), $request_query);
+    $request_query = $request->query->all();
 
     if (strpos($request->getPathInfo(), '/system/files/') === 0 && !$request->query->has('file')) {
       // Private files paths are split by the inbound path processor and the
@@ -165,6 +165,10 @@ public function onKernelRequestCheckRedirect(GetResponseEvent $event) {
       ];
       $response = new TrustedRedirectResponse($url->setAbsolute()->toString(), $redirect->getStatusCode(), $headers);
       $response->addCacheableDependency($redirect);
+
+      // Invoke hook_redirect_response_alter().
+      $this->moduleHandler->alter('redirect_response', $response, $redirect);
+
       $event->setResponse($response);
     }
   }
@@ -172,12 +176,12 @@ public function onKernelRequestCheckRedirect(GetResponseEvent $event) {
   /**
    * Prior to set the response it check if we can redirect.
    *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+   * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
    *   The event object.
    * @param \Drupal\Core\Url $url
    *   The Url where we want to redirect.
    */
-  protected function setResponse(GetResponseEvent $event, Url $url) {
+  protected function setResponse(RequestEvent $event, Url $url) {
     $request = $event->getRequest();
     $this->context->fromRequest($request);
 
diff --git a/web/modules/redirect/src/EventSubscriber/RouteNormalizerRequestSubscriber.php b/web/modules/redirect/src/EventSubscriber/RouteNormalizerRequestSubscriber.php
index 274ba1e12a8781574ebe0e8f9376c215dc51798e..0b091ccc5cfede6a66566219948eb699a4be1609 100644
--- a/web/modules/redirect/src/EventSubscriber/RouteNormalizerRequestSubscriber.php
+++ b/web/modules/redirect/src/EventSubscriber/RouteNormalizerRequestSubscriber.php
@@ -8,8 +8,8 @@
 use Drupal\Core\Routing\TrustedRedirectResponse;
 use Drupal\Core\Routing\UrlGeneratorInterface;
 use Drupal\redirect\RedirectChecker;
+use Symfony\Component\HttpKernel\Event\RequestEvent;
 use Symfony\Component\HttpKernel\KernelEvents;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
@@ -80,12 +80,12 @@ public function __construct(UrlGeneratorInterface $url_generator, PathMatcherInt
    *   page.
    * - Requested path has an alias: redirect to alias.
    *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+   * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
    *   The Event to process.
    */
-  public function onKernelRequestRedirect(GetResponseEvent $event) {
+  public function onKernelRequestRedirect(RequestEvent $event) {
 
-    if (!$this->config->get('route_normalizer_enabled') || !$event->isMasterRequest()) {
+    if (!$this->config->get('route_normalizer_enabled') || !$event->isMainRequest()) {
       return;
     }
 
@@ -123,8 +123,7 @@ public function onKernelRequestRedirect(GetResponseEvent $event) {
 
       $original_uri = $request->getSchemeAndHttpHost() . $request->getRequestUri();
       $original_uri = urldecode($original_uri);
-      $redirect_uri = urldecode($redirect_uri);
-      if ($redirect_uri != $original_uri) {
+      if (urldecode($redirect_uri) != $original_uri) {
         $response = new TrustedRedirectResponse($redirect_uri, $this->config->get('default_status_code'));
         $response->headers->set('X-Drupal-Route-Normalizer', 1);
         $event->setResponse($response);
diff --git a/web/modules/redirect/src/Form/RedirectDeleteMultipleForm.php b/web/modules/redirect/src/Form/RedirectDeleteMultipleForm.php
index fe4c43e3a8af5ba7b93dee06651e99be1f7054ca..e1d048b1bce33c5415e6888800c32b704b18fc55 100644
--- a/web/modules/redirect/src/Form/RedirectDeleteMultipleForm.php
+++ b/web/modules/redirect/src/Form/RedirectDeleteMultipleForm.php
@@ -27,7 +27,7 @@ class RedirectDeleteMultipleForm extends ConfirmFormBase {
   /**
    * The private tempstore factory.
    *
-   * @var \Drupal\user\PrivateTempStoreFactory
+   * @var \Drupal\Core\TempStore\PrivateTempStoreFactory
    */
   protected $privateTempStoreFactory;
 
diff --git a/web/modules/redirect/src/Form/RedirectForm.php b/web/modules/redirect/src/Form/RedirectForm.php
index 1b4f4534f29ddb1503c496cd45fbd5573b94c196..23fd3add6da78de6086459c009675df6993e51f9 100644
--- a/web/modules/redirect/src/Form/RedirectForm.php
+++ b/web/modules/redirect/src/Form/RedirectForm.php
@@ -39,12 +39,12 @@ protected function prepareEntity() {
         }
       }
 
-      $source_url = urldecode($this->getRequest()->get('source'));
+      $source_url = urldecode($this->getRequest()->get('source') ?? '');
       if (!empty($source_url)) {
         $redirect->setSource($source_url, $source_query);
       }
 
-      $redirect_url = urldecode($this->getRequest()->get('redirect'));
+      $redirect_url = urldecode($this->getRequest()->get('redirect') ?? '');
       if (!empty($redirect_url)) {
         try {
           $redirect->setRedirect($redirect_url, $redirect_query, $redirect_options);
diff --git a/web/modules/redirect/src/Plugin/migrate/source/d7/PathRedirect.php b/web/modules/redirect/src/Plugin/migrate/source/d7/PathRedirect.php
index c9ec720d68b0531e193d716063d87c5454aeb480..7ddcd244cec16fe30cf191dbba64de21dc9f5d49 100644
--- a/web/modules/redirect/src/Plugin/migrate/source/d7/PathRedirect.php
+++ b/web/modules/redirect/src/Plugin/migrate/source/d7/PathRedirect.php
@@ -36,15 +36,14 @@ public function query() {
   public function prepareRow(Row $row) {
     static $default_status_code;
     if (!isset($default_status_code)) {
-      $default_status_code = unserialize($this->getDatabase()
-        ->select('variable', 'v')
-        ->fields('v', ['value'])
-        ->condition('name', 'redirect_default_status_code')
-        ->execute()
-        ->fetchField());
+      // The default status code not necessarily saved to the source database.
+      // In this case, redirects should get the default value from the Drupal 7
+      // version's variable_get() calls, which is 301.
+      // @see https://git.drupalcode.org/project/redirect/-/blob/7f9531d08/redirect.admin.inc#L16
+      $default_status_code = $this->variableGet('redirect_default_status_code', 301);
     }
     $current_status_code = $row->getSourceProperty('status_code');
-    $status_code = $current_status_code != 0 ? $current_status_code : $default_status_code;
+    $status_code = !empty($current_status_code) ? $current_status_code : $default_status_code;
     $row->setSourceProperty('status_code', $status_code);
     return parent::prepareRow($row);
   }
diff --git a/web/modules/redirect/src/RedirectChecker.php b/web/modules/redirect/src/RedirectChecker.php
index 02da7ad2e90b3ba3efcd2dbf77e2d69ad5528965..d1aa829b35f4e1bddd2e1635a42831005773adf9 100644
--- a/web/modules/redirect/src/RedirectChecker.php
+++ b/web/modules/redirect/src/RedirectChecker.php
@@ -6,8 +6,8 @@
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\State\StateInterface;
-use Symfony\Cmf\Component\Routing\RouteObjectInterface;
-use Symfony\Cmf\Component\Routing\RouteProviderInterface;
+use Drupal\Core\Routing\RouteObjectInterface;
+use Drupal\Core\Routing\RouteProviderInterface;
 use Symfony\Component\HttpFoundation\Request;
 
 /**
@@ -80,7 +80,7 @@ public function canRedirect(Request $request, $route_name = NULL) {
       // Do not redirect if this is other than GET request.
       $can_redirect = FALSE;
     }
-    elseif ($this->state->get('system.maintenance_mode') || defined('MAINTENANCE_MODE')) {
+    elseif (!$this->account->hasPermission('access site in maintenance mode') && ($this->state->get('system.maintenance_mode') || defined('MAINTENANCE_MODE'))) {
       // Do not redirect in offline or maintenance mode.
       $can_redirect = FALSE;
     }
diff --git a/web/modules/redirect/src/RedirectRepository.php b/web/modules/redirect/src/RedirectRepository.php
index ff1ccf8bd99cf6178dadb064d29ac9bf054e0d67..8ba2ad362ba2a9244d0a0f06edd07589d789c167 100644
--- a/web/modules/redirect/src/RedirectRepository.php
+++ b/web/modules/redirect/src/RedirectRepository.php
@@ -133,6 +133,7 @@ protected function findByRedirect(Redirect $redirect, $language) {
    */
   public function findBySourcePath($source_path) {
     $ids = $this->manager->getStorage('redirect')->getQuery()
+      ->accessCheck(TRUE)
       ->condition('redirect_source.path', $source_path, 'LIKE')
       ->execute();
     return $this->manager->getStorage('redirect')->loadMultiple($ids);
@@ -150,6 +151,7 @@ public function findBySourcePath($source_path) {
   public function findByDestinationUri(array $destination_uri) {
     $storage = $this->manager->getStorage('redirect');
     $ids = $storage->getQuery()
+      ->accessCheck(TRUE)
       ->condition('redirect_redirect.uri', $destination_uri, 'IN')
       ->execute();
     return $storage->loadMultiple($ids);
diff --git a/web/modules/redirect/tests/fixtures/drupal7-no-default.php b/web/modules/redirect/tests/fixtures/drupal7-no-default.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ba0bb82976bc9ea3c1e7a20d66a407619940344
--- /dev/null
+++ b/web/modules/redirect/tests/fixtures/drupal7-no-default.php
@@ -0,0 +1,229 @@
+<?php
+/**
+ * @file
+ * A database agnostic dump for testing purposes.
+ */
+
+use Drupal\Core\Database\Database;
+
+$connection = Database::getConnection();
+
+$connection->schema()->createTable('redirect', [
+  'fields' => [
+    'rid' => [
+      'type' => 'serial',
+      'not null' => TRUE,
+      'size' => 'normal',
+    ],
+    'hash' => [
+      'type' => 'varchar',
+      'length' => 64,
+      'not null' => TRUE,
+    ],
+    'type' => [
+      'type' => 'varchar',
+      'length' => 64,
+      'not null' => TRUE,
+    ],
+    'uid' => [
+      'type' => 'int',
+      'not null' => TRUE,
+    ],
+    'source' => [
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => TRUE,
+    ],
+    'source_options' => [
+      'type' => 'text',
+      'not null' => TRUE,
+    ],
+    'redirect' => [
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => TRUE,
+    ],
+    'redirect_options' => [
+      'type' => 'text',
+      'not null' => TRUE,
+    ],
+    'language' => [
+      'type' => 'varchar',
+      'length' => 12,
+      'not null' => TRUE,
+      'default' => '',
+    ],
+    'status_code' => [
+      'type' => 'int',
+      'size' => 'small',
+      'not null' => TRUE,
+    ],
+    'count' => [
+      'type' => 'int',
+      'not null' => TRUE,
+    ],
+    'access' => [
+      'type' => 'int',
+      'not null' => TRUE,
+    ],
+  ],
+  'primary key' => ['rid'],
+  'unique keys' => [
+    'source_language' => ['source', 'language'],
+    'expires' => ['type', 'access']
+  ],
+  'mysql_character_set' => 'utf8',
+]);
+
+
+$connection->insert('redirect')
+  ->fields([
+    'rid',
+    'hash',
+    'type',
+    'uid',
+    'source',
+    'source_options',
+    'redirect',
+    'redirect_options',
+    'language',
+    'status_code',
+    'count',
+    'access',
+  ])
+  ->values([
+    'rid' => 5,
+    'hash' => 'MwmDbnA65ag646gtEdLqmAqTbF0qQerse63RkQmJK_Y',
+    'type' => 'redirect',
+    'uid' => 5,
+    'source' => 'test/source/url',
+    'source_options' => '',
+    'redirect' => 'test/redirect/url',
+    'redirect_options' => '',
+    'language' => 'und',
+    'status_code' => 301,
+    'count' => 2518,
+    'access' => 1449497138,
+  ])
+  ->values([
+    'rid' => 7,
+    'hash' => 'GvD5bBB71W8qBvp9I9hHmbSoqZfTvUz0mIkEWjlP8M4',
+    'type' => 'redirect',
+    'uid' => 6,
+    'source' => 'test/source/url2',
+    'source_options' => '',
+    'redirect' => 'http://test/external/redirect/url',
+    'redirect_options' => 'a:2:{s:5:"query";a:2:{s:3:"foo";s:3:"bar";s:3:"biz";s:3:"buz";}s:8:"fragment";s:10:"fragment-1";}',
+    'language' => 'und',
+    'status_code' => 0,
+    'count' => 419,
+    'access' => 1449497139,
+  ])
+  ->execute();
+
+$connection->schema()->createTable('variable', [
+  'fields' => [
+    'name' => [
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '128',
+      'default' => '',
+    ],
+    'value' => [
+      'type' => 'blob',
+      'not null' => TRUE,
+      'size' => 'normal',
+    ],
+  ],
+  'primary key' => [
+    'name',
+  ],
+  'mysql_character_set' => 'utf8',
+]);
+
+$connection->schema()->createTable('system', [
+  'fields' => [
+    'filename' => [
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '255',
+      'default' => '',
+    ],
+    'name' => [
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '255',
+      'default' => '',
+    ],
+    'type' => [
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '12',
+      'default' => '',
+    ],
+    'owner' => [
+      'type' => 'varchar',
+      'not null' => TRUE,
+      'length' => '255',
+      'default' => '',
+    ],
+    'status' => [
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '0',
+    ],
+    'bootstrap' => [
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '0',
+    ],
+    'schema_version' => [
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '-1',
+    ],
+    'weight' => [
+      'type' => 'int',
+      'not null' => TRUE,
+      'size' => 'normal',
+      'default' => '0',
+    ],
+    'info' => [
+      'type' => 'blob',
+      'not null' => FALSE,
+      'size' => 'normal',
+    ],
+  ],
+  'primary key' => [
+    'filename',
+  ],
+  'mysql_character_set' => 'utf8',
+]);
+
+$connection->insert('system')
+->fields([
+  'filename',
+  'name',
+  'type',
+  'owner',
+  'status',
+  'bootstrap',
+  'schema_version',
+  'weight',
+  'info',
+])
+->values([
+  'filename' => 'modules/contrib/redirect/redirect.module',
+  'name' => 'redirect',
+  'type' => 'module',
+  'owner' => '',
+  'status' => '1',
+  'bootstrap' => '0',
+  'schema_version' => '7000',
+  'weight' => '0',
+  'info' => 'a:13:{s:4:"name";s:8:"Redirect";s:11:"description";s:51:"Allows users to redirect from old URLs to new URLs.";s:4:"core";s:3:"7.x";s:5:"files";a:11:{i:0;s:15:"redirect.module";i:1;s:18:"redirect.admin.inc";i:2;s:16:"redirect.install";i:3;s:13:"redirect.test";i:4;s:24:"views/redirect.views.inc";i:5;s:47:"views/redirect_handler_filter_redirect_type.inc";i:6;s:48:"views/redirect_handler_field_redirect_source.inc";i:7;s:50:"views/redirect_handler_field_redirect_redirect.inc";i:8;s:52:"views/redirect_handler_field_redirect_operations.inc";i:9;s:51:"views/redirect_handler_field_redirect_link_edit.inc";i:10;s:53:"views/redirect_handler_field_redirect_link_delete.inc";}s:9:"configure";s:37:"admin/config/search/redirect/settings";s:7:"version";s:11:"7.x-1.0-rc1";s:7:"project";s:8:"redirect";s:9:"datestamp";s:10:"1347989995";s:5:"mtime";i:1347989995;s:12:"dependencies";a:0:{}s:7:"package";s:5:"Other";s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}',
+])
+->execute();
diff --git a/web/modules/redirect/tests/modules/redirect_test/redirect_test.info.yml b/web/modules/redirect/tests/modules/redirect_test/redirect_test.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..47d1ba5dd1b1b7ef8ed49f86acff38dac35f507d
--- /dev/null
+++ b/web/modules/redirect/tests/modules/redirect_test/redirect_test.info.yml
@@ -0,0 +1,11 @@
+name: 'Redirect module tests'
+type: module
+description: 'Support module for redirect testing.'
+package: Testing
+dependencies:
+  - drupal:redirect
+
+# Information added by Drupal.org packaging script on 2022-08-29
+version: '8.x-1.8'
+project: 'redirect'
+datestamp: 1661806957
diff --git a/web/modules/redirect/tests/modules/redirect_test/redirect_test.module b/web/modules/redirect/tests/modules/redirect_test/redirect_test.module
new file mode 100644
index 0000000000000000000000000000000000000000..b840e9b695d09efee156b68d3f8fc3032ff524d4
--- /dev/null
+++ b/web/modules/redirect/tests/modules/redirect_test/redirect_test.module
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @file
+ * A test module for testing the redirect module.
+ */
+
+use Drupal\Core\Routing\TrustedRedirectResponse;
+use Drupal\redirect\Entity\Redirect;
+
+/**
+ * Implements hook_redirect_response_alter().
+ */
+function redirect_test_redirect_response_alter(TrustedRedirectResponse $response, Redirect $redirect) {
+  $path = 'test/redirect/2/successful';
+  $replace = 'test/redirect/other';
+  if ($redirect->getRedirect()['uri'] == "internal:/" . $path) {
+    $response->setTargetUrl(str_replace($path, $replace, $redirect->getRedirectUrl()->setAbsolute()->toString()));
+  }
+}
diff --git a/web/modules/redirect/tests/src/Functional/AssertRedirectTrait.php b/web/modules/redirect/tests/src/Functional/AssertRedirectTrait.php
index 6fa229622f491013246c773fc69d56d98e7b5821..a16908cacff745db64c00c359b8436bef5d17789 100644
--- a/web/modules/redirect/tests/src/Functional/AssertRedirectTrait.php
+++ b/web/modules/redirect/tests/src/Functional/AssertRedirectTrait.php
@@ -56,7 +56,7 @@ public function assertRedirect($path, $expected_ending_url, $expected_ending_sta
       $expected_ending_url = NULL;
     }
 
-    $this->assertEqual($expected_ending_url, $ending_url, $message);
+    $this->assertEquals($ending_url, $expected_ending_url, $message);
     return $response;
   }
 
diff --git a/web/modules/redirect/tests/src/Functional/GlobalRedirectTest.php b/web/modules/redirect/tests/src/Functional/GlobalRedirectTest.php
index 6f806d67196d49ca63f0cb42981a37f992f5987c..178959ed526cfdb92a907837676885e0b01759f9 100644
--- a/web/modules/redirect/tests/src/Functional/GlobalRedirectTest.php
+++ b/web/modules/redirect/tests/src/Functional/GlobalRedirectTest.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\Tests\redirect\Functional;
 
-use Behat\Mink\Driver\GoutteDriver;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Language\Language;
 use Drupal\language\Entity\ConfigurableLanguage;
@@ -25,7 +24,7 @@ class GlobalRedirectTest extends BrowserTestBase {
    *
    * @var array
    */
-  public static $modules = [
+  protected static $modules = [
     'path',
     'node',
     'redirect',
@@ -71,18 +70,13 @@ class GlobalRedirectTest extends BrowserTestBase {
    */
   protected $defaultTheme = 'stark';
 
-  /**
-   * {@inheritdoc}
-   */
-  protected $minkDefaultDriverClass = GoutteDriver::class;
-
   /**
    * {@inheritdoc}
    */
   protected function initMink() {
     $session = parent::initMink();
 
-    /** @var \Behat\Mink\Driver\GoutteDriver $driver */
+    /** @var \Behat\Mink\Driver\BrowserKitDriver $driver */
     $driver = $session->getDriver();
     // Since we are testing low-level redirect stuff, the HTTP client should
     // NOT automatically follow redirects sent by the server.
@@ -94,7 +88,7 @@ protected function initMink() {
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  protected function setUp(): void {
     parent::setUp();
 
     $this->config = $this->config('redirect.settings');
@@ -193,7 +187,7 @@ public function testRedirects() {
     // Test a POST request. It should stay on the same path and not try to
     // redirect. Because Mink does not provide methods to do plain POSTs, we
     // need to use the underlying Guzzle HTTP client directly.
-    /** @var \Behat\Mink\Driver\GoutteDriver $driver */
+    /** @var \Behat\Mink\Driver\BrowserKitDriver $driver */
     $driver = $this->getSession()->getDriver();
     $response = $driver->getClient()
       ->getClient()
@@ -262,15 +256,17 @@ public function testLanguageRedirects() {
 
     // Enable URL language detection and selection.
     $edit = ['language_interface[enabled][language-url]' => '1'];
-    $this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
+    $this->drupalGet('admin/config/regional/language/detection');
+    $this->submitForm($edit, 'Save settings');
 
     // Set page content type to use multilingual support.
     $edit = [
       'language_configuration[language_alterable]' => TRUE,
       'language_configuration[content_translation]' => TRUE,
     ];
-    $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
-    $this->assertRaw(t('The content type %type has been updated.', ['%type' => 'Page']));
+    $this->drupalGet('admin/structure/types/manage/page');
+    $this->submitForm($edit, 'Save content type');
+    $this->assertSession()->responseContains('The content type <em class="placeholder">Page</em> has been updated.');
 
     $spanish_node = $this->drupalCreateNode([
       'type' => 'page',
diff --git a/web/modules/redirect/tests/src/Functional/RedirectHooksTest.php b/web/modules/redirect/tests/src/Functional/RedirectHooksTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0d1b246fc69b9be85f75ef196c7b2d99af38f708
--- /dev/null
+++ b/web/modules/redirect/tests/src/Functional/RedirectHooksTest.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Drupal\Tests\redirect\Functional;
+
+use Drupal\redirect\Entity\Redirect;
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Test the functionality of the Redirect module hooks.
+ *
+ * @ingroup redirect_api_hooks
+ *
+ * @group redirect
+ */
+class RedirectHooksTest extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['redirect_test'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp(): void {
+    parent::setUp();
+
+    // Create two redirects.
+    $redirect = Redirect::create();
+    $redirect->setSource('/test/redirect/1');
+    $redirect->setRedirect('/test/redirect/1/successful');
+    $redirect->setStatusCode(301);
+    $redirect->save();
+
+    $redirect = Redirect::create();
+    $redirect->setSource('/test/redirect/2');
+    $redirect->setRedirect('/test/redirect/2/successful');
+    $redirect->setStatusCode(301);
+    $redirect->save();
+  }
+
+  /**
+   * Test the redirects.
+   */
+  public function testRedirectResponseHook() {
+    $this->drupalGet('test/redirect/1');
+    $this->assertSession()->addressEquals('test/redirect/1/successful');
+
+    $this->drupalGet('test/redirect/2');
+    $this->assertSession()->addressEquals('test/redirect/other');
+  }
+
+}
diff --git a/web/modules/redirect/tests/src/Functional/RedirectNodeFormTest.php b/web/modules/redirect/tests/src/Functional/RedirectNodeFormTest.php
index 1bb379bc548b42fa89fefc4ae0a7eb8cc56f77d2..704445292c35d9dd2ee528a0a129d01484cd92ba 100644
--- a/web/modules/redirect/tests/src/Functional/RedirectNodeFormTest.php
+++ b/web/modules/redirect/tests/src/Functional/RedirectNodeFormTest.php
@@ -30,7 +30,7 @@ class RedirectNodeFormTest extends BrowserTestBase {
    *
    * @var array
    */
-  public static $modules = ['node', 'redirect'];
+  protected static $modules = ['node', 'redirect'];
 
   /**
    * {@inheritdoc}
@@ -40,7 +40,7 @@ class RedirectNodeFormTest extends BrowserTestBase {
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  protected function setUp(): void {
     parent::setUp();
 
     // Create Basic page node type.
@@ -82,19 +82,19 @@ public function testNodeForm() {
     $this->drupalGet('node/' . $node->id() . '/edit');
 
     // Make sure the redirect add button is not visible to this regular user.
-    $this->assertNoRaw('Add URL redirect');
+    $this->assertSession()->responseNotContains('Add URL redirect');
 
     // Now edit the same node as an admin user.
     $this->drupalLogin($this->adminUser);
     $this->drupalGet('node/' . $node->id() . '/edit');
 
     // Make sure the redirect add button is visible for the admin user.
-    $this->assertRaw('Add URL redirect');
+    $this->assertSession()->responseContains('Add URL redirect');
 
     // Make sure the link works as expected.
     $this->clickLink('Add URL redirect');
-    $this->assertUrl('admin/config/search/redirect/add');
-    $this->assertFieldsByValue($this->xpath("//input[@id = 'edit-redirect-redirect-0-uri']"), '/node/' . $node->id(), 'To: field correctly pre-filled.');
+    $this->assertSession()->addressEquals('admin/config/search/redirect/add');
+    $this->assertSession()->fieldValueEquals('edit-redirect-redirect-0-uri', '/node/' . $node->id());
   }
 
 }
diff --git a/web/modules/redirect/tests/src/Functional/RedirectUILanguageTest.php b/web/modules/redirect/tests/src/Functional/RedirectUILanguageTest.php
index 372576cab609f8a878bc578a86e5c2ffe8c5ba34..a7dfbe549ae5cc57f94abf97bfdf84c7352c1682 100644
--- a/web/modules/redirect/tests/src/Functional/RedirectUILanguageTest.php
+++ b/web/modules/redirect/tests/src/Functional/RedirectUILanguageTest.php
@@ -17,12 +17,12 @@ class RedirectUILanguageTest extends RedirectUITest {
   /**
    * {@inheritdoc}
    */
-  public static $modules = ['redirect', 'node', 'path', 'dblog', 'views', 'taxonomy', 'language', 'content_translation'];
+  protected static $modules = ['redirect', 'node', 'path', 'dblog', 'views', 'taxonomy', 'language', 'content_translation'];
 
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  protected function setUp(): void {
     parent::setUp();
 
     $language = ConfigurableLanguage::createFromLangcode('de');
@@ -38,29 +38,31 @@ public function testLanguageSpecificRedirects() {
     $this->drupalLogin($this->adminUser);
 
     $this->drupalGet('admin/config/search/redirect/add');
-    $this->assertOption('edit-language-0-value', 'en');
-    $this->assertOption('edit-language-0-value', 'de');
-    $this->assertOption('edit-language-0-value', 'es');
-    $this->assertOption('edit-language-0-value', 'und');
-    $this->assertNoOption('edit-language-0-value', 'zxx');
-    $this->assertOptionByText('edit-language-0-value', 'English');
-    $this->assertOptionByText('edit-language-0-value', 'German');
-    $this->assertOptionByText('edit-language-0-value', 'Spanish');
-    $this->assertOptionByText('edit-language-0-value', '- All languages -');
+    $this->assertSession()->optionExists('edit-language-0-value', 'en');
+    $this->assertSession()->optionExists('edit-language-0-value', 'de');
+    $this->assertSession()->optionExists('edit-language-0-value', 'es');
+    $this->assertSession()->optionExists('edit-language-0-value', 'und');
+    $this->assertSession()->optionNotExists('edit-language-0-value', 'zxx');
+    $this->assertSession()->optionExists('edit-language-0-value', 'English');
+    $this->assertSession()->optionExists('edit-language-0-value', 'German');
+    $this->assertSession()->optionExists('edit-language-0-value', 'Spanish');
+    $this->assertSession()->optionExists('edit-language-0-value', '- All languages -');
 
     // Add a redirect for english.
-    $this->drupalPostForm('admin/config/search/redirect/add', [
+    $this->drupalGet('admin/config/search/redirect/add');
+    $this->submitForm([
       'redirect_source[0][path]' => 'langpath',
       'redirect_redirect[0][uri]' => '/user',
       'language[0][value]' => 'en',
-    ], t('Save'));
+    ], 'Save');
 
     // Add a redirect for germany.
-    $this->drupalPostForm('admin/config/search/redirect/add', [
+    $this->drupalGet('admin/config/search/redirect/add');
+    $this->submitForm([
       'redirect_source[0][path]' => 'langpath',
       'redirect_redirect[0][uri]' => '<front>',
       'language[0][value]' => 'de',
-    ], t('Save'));
+    ], 'Save');
 
     // Check redirect for english.
     $this->assertRedirect('langpath', '/user', 301);
@@ -79,11 +81,12 @@ public function testUndefinedLangugageRedirects() {
     $this->drupalLogin($this->adminUser);
 
     // Add a redirect for english.
-    $this->drupalPostForm('admin/config/search/redirect/add', [
+    $this->drupalGet('admin/config/search/redirect/add');
+    $this->submitForm([
       'redirect_source[0][path]' => 'langpath',
       'redirect_redirect[0][uri]' => '/user',
       'language[0][value]' => 'und',
-    ], t('Save'));
+    ], 'Save');
 
     // Check redirect for english.
     $this->assertRedirect('langpath', '/user', 301);
@@ -99,11 +102,12 @@ public function testEditRedirectLanguage() {
     $this->drupalLogin($this->adminUser);
 
     // Add a redirect for english.
-    $this->drupalPostForm('admin/config/search/redirect/add', [
+    $this->drupalGet('admin/config/search/redirect/add');
+    $this->submitForm([
       'redirect_source[0][path]' => 'langpath',
       'redirect_redirect[0][uri]' => '/user',
       'language[0][value]' => 'en',
-    ], t('Save'));
+    ], 'Save');
 
     // Check redirect for english.
     $this->assertRedirect('langpath', '/user', 301);
@@ -114,7 +118,7 @@ public function testEditRedirectLanguage() {
     // Edit the redirect and change the language.
     $this->drupalGet('admin/config/search/redirect');
     $this->clickLink('Edit');
-    $this->drupalPostForm(NULL, ['language[0][value]' => 'de'], t('Save'));
+    $this->submitForm(['language[0][value]' => 'de'], 'Save');
 
     // Check redirect for english is NOT working now.
     $this->assertRedirect('langpath', NULL, 404);
diff --git a/web/modules/redirect/tests/src/Functional/RedirectUITest.php b/web/modules/redirect/tests/src/Functional/RedirectUITest.php
index 51fb2abde8effe1e261a3bc54a7405ed30db9a1c..e1800e377896c83747ebfdd91119e48a5fca8ce0 100644
--- a/web/modules/redirect/tests/src/Functional/RedirectUITest.php
+++ b/web/modules/redirect/tests/src/Functional/RedirectUITest.php
@@ -37,7 +37,7 @@ class RedirectUITest extends BrowserTestBase {
   /**
    * {@inheritdoc}
    */
-  public static $modules = ['redirect', 'node', 'path', 'dblog', 'views', 'taxonomy'];
+  protected static $modules = ['redirect', 'node', 'path', 'dblog', 'views', 'taxonomy'];
 
   /**
    * {@inheritdoc}
@@ -47,7 +47,7 @@ class RedirectUITest extends BrowserTestBase {
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  protected function setUp(): void {
     parent::setUp();
 
     $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
@@ -80,17 +80,18 @@ public function testAutomaticRedirects() {
       'path' => ['alias' => '/node_test_alias'],
     ]);
     $this->drupalGet('node/' . $node->id() . '/edit');
-    $this->assertText(t('No URL redirects available.'));
-    $this->drupalPostForm('node/' . $node->id() . '/edit', ['path[0][alias]' => '/node_test_alias_updated'], t('Save'));
+    $this->assertSession()->pageTextContains('No URL redirects available.');
+    $this->submitForm(['path[0][alias]' => '/node_test_alias_updated'], 'Save');
 
     $redirect = $this->repository->findMatchingRedirect('node_test_alias', [], Language::LANGCODE_NOT_SPECIFIED);
-    $this->assertEqual($redirect->getRedirectUrl()->toString(), Url::fromUri('base:node_test_alias_updated')->toString());
+    $this->assertEquals(Url::fromUri('base:node_test_alias_updated')->toString(), $redirect->getRedirectUrl()->toString());
     // Test if the automatically created redirect works.
     $this->assertRedirect('node_test_alias', 'node_test_alias_updated');
 
     // Test that changing the path back deletes the first redirect, creates
     // a new one and does not result in a loop.
-    $this->drupalPostForm('node/' . $node->id() . '/edit', ['path[0][alias]' => '/node_test_alias'], t('Save'));
+    $this->drupalGet('node/' . $node->id() . '/edit');
+    $this->submitForm(['path[0][alias]' => '/node_test_alias'], 'Save');
     $redirect = $this->repository->findMatchingRedirect('node_test_alias', [], Language::LANGCODE_NOT_SPECIFIED);
     $this->assertTrue(empty($redirect));
 
@@ -98,25 +99,27 @@ public function testAutomaticRedirects() {
     $redirect = $this->repository->findMatchingRedirect('node_test_alias_updated', [], Language::LANGCODE_NOT_SPECIFIED);
 
     $this->drupalGet('node/' . $node->id() . '/edit');
-    $this->assertText($redirect->getSourcePathWithQuery());
-    $this->assertLinkByHref(Url::fromRoute('entity.redirect.edit_form', ['redirect' => $redirect->id()])->toString());
-    $this->assertLinkByHref(Url::fromRoute('entity.redirect.delete_form', ['redirect' => $redirect->id()])->toString());
+    $this->assertSession()->pageTextContains($redirect->getSourcePathWithQuery());
+    $this->assertSession()->linkByHrefExists(Url::fromRoute('entity.redirect.edit_form', ['redirect' => $redirect->id()])->toString());
+    $this->assertSession()->linkByHrefExists(Url::fromRoute('entity.redirect.delete_form', ['redirect' => $redirect->id()])->toString());
 
-    $this->assertEqual($redirect->getRedirectUrl()->toString(), Url::fromUri('base:node_test_alias')->toString());
+    $this->assertEquals(Url::fromUri('base:node_test_alias')->toString(), $redirect->getRedirectUrl()->toString());
     // Test if the automatically created redirect works.
     $this->assertRedirect('node_test_alias_updated', 'node_test_alias');
 
     // Test that the redirect will be deleted upon node deletion.
-    $this->drupalPostForm('node/' . $node->id() . '/delete', [], t('Delete'));
+    $this->drupalGet('node/' . $node->id() . '/delete');
+    $this->submitForm([], 'Delete');
     $redirect = $this->repository->findMatchingRedirect('node_test_alias_updated', [], Language::LANGCODE_NOT_SPECIFIED);
     $this->assertTrue(empty($redirect));
 
     // Create a term and update its path alias and check if we have a redirect
     // from the previous path alias to the new one.
     $term = $this->createTerm($this->createVocabulary());
-    $this->drupalPostForm('taxonomy/term/' . $term->id() . '/edit', ['path[0][alias]' => '/term_test_alias_updated'], t('Save'));
+    $this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
+    $this->submitForm(['path[0][alias]' => '/term_test_alias_updated'], 'Save');
     $redirect = $this->repository->findMatchingRedirect('term_test_alias');
-    $this->assertEqual($redirect->getRedirectUrl()->toString(), Url::fromUri('base:term_test_alias_updated')->toString());
+    $this->assertEquals(Url::fromUri('base:term_test_alias_updated')->toString(), $redirect->getRedirectUrl()->toString());
     // Test if the automatically created redirect works.
     $this->assertRedirect('term_test_alias', 'term_test_alias_updated');
 
@@ -130,24 +133,25 @@ public function testAutomaticRedirects() {
     }
 
     // Test the path alias update via the admin path form.
-    $this->drupalPostForm('admin/config/search/path/add', [
+    $this->drupalGet('admin/config/search/path/add');
+    $this->submitForm([
       $path_field => '/node',
       $alias_field => '/aaa_path_alias',
-    ], t('Save'));
+    ], 'Save');
     // Note that here we rely on fact that we land on the path alias list page
     // and the default sort is by the alias, which implies that the first edit
     // link leads to the edit page of the aaa_path_alias.
-    $this->clickLink(t('Edit'));
-    $this->drupalPostForm(NULL, [$alias_field => '/aaa_path_alias_updated'], t('Save'));
+    $this->clickLink('Edit');
+    $this->submitForm([$alias_field => '/aaa_path_alias_updated'], 'Save');
     $redirect = $this->repository->findMatchingRedirect('aaa_path_alias', [], 'en');
-    $this->assertEqual($redirect->getRedirectUrl()->toString(), Url::fromUri('base:aaa_path_alias_updated')->toString());
+    $this->assertEquals(Url::fromUri('base:aaa_path_alias_updated')->toString(), $redirect->getRedirectUrl()->toString());
     // Test if the automatically created redirect works.
     $this->assertRedirect('aaa_path_alias', 'aaa_path_alias_updated');
 
     // Test the automatically created redirect shows up in the form correctly.
     $this->drupalGet('admin/config/search/redirect/edit/' . $redirect->id());
-    $this->assertFieldByName('redirect_source[0][path]', 'aaa_path_alias');
-    $this->assertFieldByName('redirect_redirect[0][uri]', '/node');
+    $this->assertSession()->fieldValueEquals('redirect_source[0][path]', 'aaa_path_alias');
+    $this->assertSession()->fieldValueEquals('redirect_redirect[0][uri]', '/node');
   }
 
   /**
@@ -173,8 +177,8 @@ function testRedirectLoop() {
 
     $this->maximumRedirects = 10;
     $this->drupalGet('node');
-    $this->assertText('Service unavailable');
-    $this->assertResponse(503);
+    $this->assertSession()->pageTextContains('Service unavailable');
+    $this->assertSession()->statusCodeEquals(503);
 
     $log = \Drupal::database()->select('watchdog')->fields('watchdog')->condition('type', 'redirect')->execute()->fetchAll();
     if (count($log) == 0) {
@@ -242,19 +246,19 @@ public function testCacheTags() {
     // Note, self::assertCacheTag() cannot be used here since it only looks at
     // the final set of headers.
     $expected = 'http_response ' . implode(' ', $redirect1->getCacheTags());
-    $this->assertEqual($expected, $response->getHeader('x-drupal-cache-tags')[0], 'Redirect cache tags properly set.');
+    $this->assertEquals($expected, $response->getHeader('x-drupal-cache-tags')[0], 'Redirect cache tags properly set.');
 
     // First request should be a cache MISS.
-    $this->assertEqual($response->getHeader('x-drupal-cache')[0], 'MISS', 'First request to the redirect was not cached.');
+    $this->assertEquals('MISS', $response->getHeader('x-drupal-cache')[0], 'First request to the redirect was not cached.');
 
     // Second request should be cached.
     $response = $this->assertRedirect('test-redirect', 'node');
-    $this->assertEqual($response->getHeader('x-drupal-cache')[0], 'HIT', 'The second request to the redirect was cached.');
+    $this->assertEquals('HIT', $response->getHeader('x-drupal-cache')[0], 'The second request to the redirect was cached.');
 
     // Ensure that the redirect has been cleared from cache when deleted.
     $redirect1->delete();
     $this->drupalGet('test-redirect');
-    $this->assertResponse(404, 'Deleted redirect properly clears the internal page cache.');
+    $this->assertSession()->statusCodeEquals(404);
   }
 
   /**
diff --git a/web/modules/redirect/tests/src/FunctionalJavascript/RedirectJavascriptTest.php b/web/modules/redirect/tests/src/FunctionalJavascript/RedirectJavascriptTest.php
index ae8895e54e18342a6a362336263f117319cc33fa..83ee44d67905944d12b98b2264ff50f552cc2d45 100644
--- a/web/modules/redirect/tests/src/FunctionalJavascript/RedirectJavascriptTest.php
+++ b/web/modules/redirect/tests/src/FunctionalJavascript/RedirectJavascriptTest.php
@@ -30,7 +30,7 @@ class RedirectJavascriptTest extends WebDriverTestBase {
   /**
    * {@inheritdoc}
    */
-  public static $modules = ['redirect', 'node', 'path', 'dblog', 'views', 'taxonomy'];
+  protected static $modules = ['redirect', 'node', 'path', 'dblog', 'views', 'taxonomy'];
 
   /**
    * {@inheritdoc}
@@ -40,7 +40,7 @@ class RedirectJavascriptTest extends WebDriverTestBase {
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  protected function setUp(): void {
     parent::setUp();
 
     $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
@@ -78,8 +78,8 @@ public function testRedirectUI() {
       ]
     ]
     );
-    $this->assertFieldByName('redirect_source[0][path]', 'non-existing?key=val&key1=val1');
-    $this->assertFieldByName('redirect_redirect[0][uri]', '/node?key=val&key1=val1');
+    $this->assertSession()->fieldValueEquals('redirect_source[0][path]', 'non-existing?key=val&key1=val1');
+    $this->assertSession()->fieldValueEquals('redirect_redirect[0][uri]', '/node?key=val&key1=val1');
 
     $this->drupalGet('admin/config/search/redirect/add');
     $page = $this->getSession()->getPage();
@@ -90,32 +90,31 @@ public function testRedirectUI() {
 
     // Try to find the redirect we just created.
     $redirect = $this->repository->findMatchingRedirect('non-existing');
-    $this->assertEqual($redirect->getSourceUrl(), Url::fromUri('base:non-existing')->toString());
-    $this->assertEqual($redirect->getRedirectUrl()->toString(), Url::fromUri('base:node')->toString());
+    $this->assertEquals(Url::fromUri('base:non-existing')->toString(), $redirect->getSourceUrl());
+    $this->assertEquals(Url::fromUri('base:node')->toString(), $redirect->getRedirectUrl()->toString());
 
     // After adding the redirect we should end up in the list. Check if the
     // redirect is listed.
-    $this->assertUrl('admin/config/search/redirect');
+    $this->assertSession()->addressEquals('admin/config/search/redirect');
     $this->assertSession()->pageTextContains('non-existing');
-    $this->assertLink(Url::fromUri('base:node')->toString());
-    $this->assertSession()->pageTextContains(t('Not specified'));
+    $this->assertSession()->linkExists(Url::fromUri('base:node')->toString());
+    $this->assertSession()->pageTextContains('Not specified');
 
     // Test the edit form and update action.
-    $this->clickLink(t('Edit'));
-    $this->assertFieldByName('redirect_source[0][path]', 'non-existing');
-    $this->assertFieldByName('redirect_redirect[0][uri]', '/node');
-    $this->assertFieldByName('status_code', $redirect->getStatusCode());
+    $this->clickLink('Edit');
+    $this->assertSession()->fieldValueEquals('redirect_source[0][path]', 'non-existing');
+    $this->assertSession()->fieldValueEquals('redirect_redirect[0][uri]', '/node');
+    $this->assertSession()->fieldValueEquals('status_code', $redirect->getStatusCode());
 
     // Append a query string to see if we handle query data properly.
-    $this->drupalPostForm(
-      NULL, [
+    $this->submitForm([
       'redirect_source[0][path]' => 'non-existing?key=value',
-    ], t('Save')
+    ], 'Save'
     );
 
     // Check the location after update and check if the value has been updated
     // in the list.
-    $this->assertUrl('admin/config/search/redirect');
+    $this->assertSession()->addressEquals('admin/config/search/redirect');
     $this->assertSession()->pageTextContains('non-existing?key=value');
 
     // The path field should not contain the query string and therefore we
@@ -124,7 +123,7 @@ public function testRedirectUI() {
     $this->storage->resetCache();
     $redirects = $this->repository->findBySourcePath('non-existing');
     $redirect = array_shift($redirects);
-    $this->assertEqual($redirect->getSourceUrl(), Url::fromUri('base:non-existing', ['query' => ['key' => 'value']])->toString());
+    $this->assertEquals(Url::fromUri('base:non-existing', ['query' => ['key' => 'value']])->toString(), $redirect->getSourceUrl());
 
     // Test the source url hints.
     // The hint about an existing base path.
@@ -132,11 +131,8 @@ public function testRedirectUI() {
     $page->fillField('redirect_source[0][path]', 'non-existing?key=value');
     $page->fillField('redirect_redirect[0][uri]', '');
     $this->assertSession()->assertWaitOnAjaxRequest();
-    $this->assertRaw(
-      t(
-        'The base source path %source is already being redirected. Do you want to <a href="@edit-page">edit the existing redirect</a>?',
-        ['%source' => 'non-existing?key=value', '@edit-page' => $redirect->toUrl('edit-form')->toString()]
-      )
+    $this->assertSession()->responseContains(
+      'The base source path <em class="placeholder">non-existing?key=value</em> is already being redirected. Do you want to <a href="' . $redirect->toUrl('edit-form')->toString() . '">edit the existing redirect</a>?'
     );
 
     // The hint about a valid path.
@@ -144,11 +140,8 @@ public function testRedirectUI() {
     $page->fillField('redirect_source[0][path]', 'node');
     $page->fillField('redirect_redirect[0][uri]', '');
     $this->assertSession()->assertWaitOnAjaxRequest();
-    $this->assertRaw(
-      t(
-        'The source path %path is likely a valid path. It is preferred to <a href="@url-alias">create URL aliases</a> for existing paths rather than redirects.',
-        ['%path' => 'node', '@url-alias' => Url::fromRoute('entity.path_alias.add_form')->toString()]
-      )
+    $this->assertSession()->responseContains(
+      'The source path <em class="placeholder">node</em> is likely a valid path. It is preferred to <a href="' . Url::fromRoute('entity.path_alias.add_form')->toString() . '">create URL aliases</a> for existing paths rather than redirects.'
     );
 
     // Test validation.
@@ -159,11 +152,8 @@ public function testRedirectUI() {
     $page->fillField('redirect_redirect[0][uri]', '/node');
     $this->assertSession()->assertWaitOnAjaxRequest();
     $page->pressButton('Save');
-    $this->assertRaw(
-      t(
-        'The source path %source is already being redirected. Do you want to <a href="@edit-page">edit the existing redirect</a>?',
-        ['%source' => 'non-existing?key=value', '@edit-page' => $redirect->toUrl('edit-form')->toString()]
-      )
+    $this->assertSession()->responseContains(
+      'The source path <em class="placeholder">non-existing?key=value</em> is already being redirected. Do you want to <a href="' . $redirect->toUrl('edit-form')->toString() . '">edit the existing redirect</a>?'
     );
 
     // Redirecting to itself.
@@ -173,7 +163,7 @@ public function testRedirectUI() {
     $page->fillField('redirect_redirect[0][uri]', '/node');
     $this->assertSession()->assertWaitOnAjaxRequest();
     $page->pressButton('Save');
-    $this->assertRaw(t('You are attempting to redirect the page to itself. This will result in an infinite loop.'));
+    $this->assertSession()->responseContains('You are attempting to redirect the page to itself. This will result in an infinite loop.');
 
     // Redirecting the front page.
     $this->drupalGet('admin/config/search/redirect/add');
@@ -182,7 +172,7 @@ public function testRedirectUI() {
     $page->fillField('redirect_redirect[0][uri]', '/node');
     $this->assertSession()->assertWaitOnAjaxRequest();
     $page->pressButton('Save');
-    $this->assertRaw(t('It is not allowed to create a redirect from the front page.'));
+    $this->assertSession()->responseContains('It is not allowed to create a redirect from the front page.');
 
     // Redirecting a url with fragment.
     $this->drupalGet('admin/config/search/redirect/add');
@@ -191,7 +181,7 @@ public function testRedirectUI() {
     $page->fillField('redirect_redirect[0][uri]', '/node');
     $this->assertSession()->assertWaitOnAjaxRequest();
     $page->pressButton('Save');
-    $this->assertRaw(t('The anchor fragments are not allowed.'));
+    $this->assertSession()->responseContains('The anchor fragments are not allowed.');
 
     // Adding path that starts with /
     $this->drupalGet('admin/config/search/redirect/add');
@@ -201,7 +191,7 @@ public function testRedirectUI() {
     // Wait on ajax is unpredictable, wait for one second.
     $this->assertSession()->assertWaitOnAjaxRequest();
     $page->pressButton('Save');
-    $this->assertRaw(t('The url to redirect from should not start with a forward slash (/).'));
+    $this->assertSession()->responseContains('The url to redirect from should not start with a forward slash (/).');
 
     // Test filters.
     // Add a new redirect.
@@ -257,29 +247,26 @@ public function testRedirectUI() {
       'redirect_bulk_form[0]' => TRUE,
       'redirect_bulk_form[1]' => TRUE,
     ];
-    $this->drupalPostForm(NULL, $edit, t('Apply to selected items'));
+    $this->submitForm($edit, 'Apply to selected items');
     $this->assertSession()->pageTextContains('Are you sure you want to delete these redirects?');
     $this->clickLink('Cancel');
 
     // Test the delete action.
     $page->find('css', '.dropbutton-toggle button')->press();
-    $this->clickLink(t('Delete'));
-    $this->assertRaw(
-      t(
-        'Are you sure you want to delete the URL redirect from %source to %redirect?',
-        ['%source' => Url::fromUri('base:non-existing', ['query' => ['key' => 'value']])->toString(), '%redirect' => Url::fromUri('base:node')->toString()]
-      )
+    $this->clickLink('Delete');
+    $this->assertSession()->responseContains(
+      'Are you sure you want to delete the URL redirect from ' . Url::fromUri('base:non-existing', ['query' => ['key' => 'value']])->toString() . ' to ' . Url::fromUri('base:node')->toString() . '?'
     );
-    $this->drupalPostForm(NULL, [], t('Delete'));
-    $this->assertUrl('admin/config/search/redirect');
+    $this->submitForm([], 'Delete');
+    $this->assertSession()->addressEquals('admin/config/search/redirect');
 
     // Test the bulk delete action.
-    $this->drupalPostForm(NULL, ['redirect_bulk_form[0]' => TRUE], t('Apply to selected items'));
+    $this->submitForm(['redirect_bulk_form[0]' => TRUE], 'Apply to selected items');
     $this->assertSession()->pageTextContains('Are you sure you want to delete this redirect?');
     $this->assertSession()->pageTextContains('test27');
-    $this->drupalPostForm(NULL, [], t('Delete'));
+    $this->submitForm([], 'Delete');
 
-    $this->assertSession()->pageTextContains(t('There is no redirect yet.'));
+    $this->assertSession()->pageTextContains('There is no redirect yet.');
   }
 
 }
diff --git a/web/modules/redirect/tests/src/Kernel/Migrate/d6/PathRedirectTest.php b/web/modules/redirect/tests/src/Kernel/Migrate/d6/PathRedirectTest.php
index c3eebbc788cea85a77749006be8552ef7e2bc8e4..51b8eb6bb1552a7ed2c28f85be384a0511845613 100644
--- a/web/modules/redirect/tests/src/Kernel/Migrate/d6/PathRedirectTest.php
+++ b/web/modules/redirect/tests/src/Kernel/Migrate/d6/PathRedirectTest.php
@@ -16,12 +16,12 @@ class PathRedirectTest extends MigrateDrupalTestBase {
   /**
    * {@inheritdoc}
    */
-  public static $modules = ['redirect', 'link', 'path_alias'];
+  protected static $modules = ['redirect', 'link', 'path_alias'];
 
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  protected function setUp(): void {
     parent::setUp();
     $this->installEntitySchema('redirect');
     $this->loadFixture( __DIR__ . '/../../../../../tests/fixtures/drupal6.php');
diff --git a/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectSourceTest.php b/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectSourceTest.php
index a5f37a8381f829873fddf8ea35d6e2e5309a8889..6708f1c8fa0f1867871850b321ed23e33d8ab554 100644
--- a/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectSourceTest.php
+++ b/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectSourceTest.php
@@ -15,7 +15,7 @@ class PathRedirectSourceTest extends MigrateSqlSourceTestBase {
   /**
    * {@inheritdoc}
    */
-  public static $modules = ['redirect', 'link', 'migrate_drupal', 'path_alias'];
+  protected static $modules = ['redirect', 'link', 'migrate_drupal', 'path_alias'];
 
   /**
    * {@inheritdoc}
diff --git a/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectTest.php b/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectTest.php
index 15134cdcc1f44b098528c51418ae5ff618fe2758..a21d8016ca1ac47369cbf2c011f513101a0a4fe6 100644
--- a/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectTest.php
+++ b/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectTest.php
@@ -7,57 +7,23 @@
 
 namespace Drupal\Tests\redirect\Kernel\Migrate\d7;
 
-use Drupal\redirect\Entity\Redirect;
-use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
-
-
 /**
  * Tests the d7_path_redirect source plugin.
  *
  * @group redirect
  */
-class PathRedirectTest extends MigrateDrupalTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static $modules = ['redirect', 'link', 'path_alias'];
+class PathRedirectTest extends PathRedirectTestBase {
 
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  protected function setUp(): void {
     parent::setUp();
     $this->installEntitySchema('redirect');
     $this->loadFixture(__DIR__ . '/../../../../fixtures/drupal7.php');
-
     $this->executeMigration('d7_path_redirect');
   }
 
-  /**
-   * Asserts various aspects of a redirect entity.
-   *
-   * @param int $id
-   *   The entity ID in the form ENTITY_TYPE.BUNDLE.FIELD_NAME.
-   * @param string $source_url
-   *   The expected source url.
-   * @param string $redirect_url
-   *   The expected redirect url.
-   * @param string $status_code
-   *   The expected status code.
-   */
-  protected function assertEntity($id, $source_url, $redirect_url, $status_code) {
-    /** @var Redirect $redirect */
-    $redirect = Redirect::load($id);
-    $this->assertSame($this->getMigration('d7_path_redirect')
-      ->getIdMap()
-      ->lookupDestinationIds([$id]), [[$redirect->id()]]);
-    $this->assertSame($source_url, $redirect->getSourceUrl());
-    $this->assertSame($redirect_url, $redirect->getRedirectUrl()
-      ->toUriString());
-    $this->assertSame($status_code, $redirect->getStatusCode());
-  }
-
   /**
    * Tests the Drupal 7 path redirect to Drupal 8 migration.
    */
@@ -65,4 +31,5 @@ public function testPathRedirect() {
     $this->assertEntity(5, '/test/source/url', 'base:test/redirect/url', '301');
     $this->assertEntity(7, '/test/source/url2', 'http://test/external/redirect/url?foo=bar&biz=buz#fragment-1', '307');
   }
+
 }
diff --git a/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectTestBase.php b/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectTestBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..00bdef9648fe43c3d143a237e76e67610db2e5d9
--- /dev/null
+++ b/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectTestBase.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\redirect\Kernel\Migrate\d7\PathRedirectTestBase.
+ */
+
+namespace Drupal\Tests\redirect\Kernel\Migrate\d7;
+
+use Drupal\redirect\Entity\Redirect;
+use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
+
+/**
+ * Base for d7_path_redirect source plugin tests.
+ *
+ * @group redirect
+ */
+abstract class PathRedirectTestBase extends MigrateDrupalTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['redirect', 'link', 'path_alias'];
+
+  /**
+   * Asserts various aspects of a redirect entity.
+   *
+   * @param int $id
+   *   The entity ID in the form ENTITY_TYPE.BUNDLE.FIELD_NAME.
+   * @param string $source_url
+   *   The expected source url.
+   * @param string $redirect_url
+   *   The expected redirect url.
+   * @param string $status_code
+   *   The expected status code.
+   */
+  protected function assertEntity($id, $source_url, $redirect_url, $status_code) {
+    /** @var Redirect $redirect */
+    $redirect = Redirect::load($id);
+    $this->assertSame($this->getMigration('d7_path_redirect')
+      ->getIdMap()
+      ->lookupDestinationIds([$id]), [[$redirect->id()]]);
+    $this->assertSame($source_url, $redirect->getSourceUrl());
+    $this->assertSame($redirect_url, $redirect->getRedirectUrl()
+      ->toUriString());
+    $this->assertSame($status_code, $redirect->getStatusCode());
+  }
+
+}
diff --git a/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectWithoutDefaultTest.php b/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectWithoutDefaultTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4622bdec20e2496d619c16075139c7d8bc4c9715
--- /dev/null
+++ b/web/modules/redirect/tests/src/Kernel/Migrate/d7/PathRedirectWithoutDefaultTest.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\redirect\Kernel\Migrate\d7\PathRedirectWithoutDefaultTest.
+ */
+
+namespace Drupal\Tests\redirect\Kernel\Migrate\d7;
+
+/**
+ * Tests the d7_path_redirect source plugin, without d7 default status code.
+ *
+ * @group redirect
+ */
+class PathRedirectWithoutDefaultTest extends PathRedirectTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->installEntitySchema('redirect');
+    $this->loadFixture(__DIR__ . '/../../../../fixtures/drupal7-no-default.php');
+    $this->executeMigration('d7_path_redirect');
+  }
+
+  /**
+   * Tests the Drupal 7 path redirect to Drupal 8 migration.
+   */
+  public function testPathRedirect() {
+    $this->assertEntity(5, '/test/source/url', 'base:test/redirect/url', '301');
+    $this->assertEntity(7, '/test/source/url2', 'http://test/external/redirect/url?foo=bar&biz=buz#fragment-1', '301');
+  }
+
+}
diff --git a/web/modules/redirect/tests/src/Kernel/RedirectAPITest.php b/web/modules/redirect/tests/src/Kernel/RedirectAPITest.php
index a379b12e2513bb8e0c24cb73906d3fbb38d85d6a..bf235ee3d0800fe65090803eb80513ad68d02268 100644
--- a/web/modules/redirect/tests/src/Kernel/RedirectAPITest.php
+++ b/web/modules/redirect/tests/src/Kernel/RedirectAPITest.php
@@ -27,12 +27,12 @@ class RedirectAPITest extends KernelTestBase {
    *
    * @var array
    */
-  public static $modules = ['redirect', 'link', 'field', 'system', 'user', 'language', 'views', 'path_alias'];
+  protected static $modules = ['redirect', 'link', 'field', 'system', 'user', 'language', 'views', 'path_alias'];
 
   /**
    * {@inheritdoc}
    */
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
 
     $this->installEntitySchema('redirect');
@@ -85,7 +85,7 @@ public function testRedirectEntity() {
       $this->assertEquals($redirect->getSourceUrl(), '/another-url?key1=val1');
     }
     else {
-      $this->fail(t('Failed to find matching redirect.'));
+      $this->fail('Failed to find matching redirect.');
     }
 
     // Load the redirect based on url.
@@ -95,7 +95,7 @@ public function testRedirectEntity() {
       $this->assertEquals($redirect->getSourceUrl(), '/another-url?key1=val1');
     }
     else {
-      $this->fail(t('Failed to find redirect by source path.'));
+      $this->fail('Failed to find redirect by source path.');
     }
 
     // Test passthrough_querystring.
@@ -167,7 +167,8 @@ public function testRedirectEntity() {
    */
   public function testDuplicateRedirectEntry() {
     $redirect = $this->storage->create();
-    $redirect->setSource('/foo/foo', []);
+    // The trailing slash should be removed on pre-save.
+    $redirect->setSource('/foo/foo/', []);
     $redirect->setRedirect('foo');
     $redirect->save();
 
@@ -193,7 +194,7 @@ public function testSortRecursive() {
     foreach ($test_cases as $index => $test_case) {
       $output = $test_case['input'];
       redirect_sort_recursive($output, $test_case['callback']);
-      $this->assertIdentical($output, $test_case['expected']);
+      $this->assertSame($test_case['expected'], $output);
     }
   }
 
@@ -236,7 +237,6 @@ public function testLoopDetection() {
       $this->fail('Failed to detect a redirect loop.');
     }
     catch (RedirectLoopException $e) {
-      $this->pass('Properly detected a redirect loop.');
     }
   }
 
diff --git a/web/modules/redirect/tests/src/Unit/RedirectCheckerTest.php b/web/modules/redirect/tests/src/Unit/RedirectCheckerTest.php
index 73aba863838d9383f1678cfb0ce26f14a2b4278b..ccd85f88e0a3d013151827a53ac792661aacb58e 100644
--- a/web/modules/redirect/tests/src/Unit/RedirectCheckerTest.php
+++ b/web/modules/redirect/tests/src/Unit/RedirectCheckerTest.php
@@ -4,7 +4,6 @@
 
 use Drupal\redirect\RedirectChecker;
 use Drupal\Tests\UnitTestCase;
-use PHPUnit_Framework_MockObject_MockObject;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 use Symfony\Component\HttpFoundation\ParameterBag;
 use Symfony\Component\Routing\Route;
@@ -23,19 +22,14 @@ public function testCanRedirect() {
 
     $config = ['redirect.settings' => ['ignore_admin_path' => FALSE, 'access_check' => TRUE]];
 
-    $state = $this->getMockBuilder('Drupal\Core\State\StateInterface')
-      ->getMock();
+    $state = $this->createMock('Drupal\Core\State\StateInterface');
     $state->expects($this->any())
       ->method('get')
       ->with('system.maintenance_mode')
       ->will($this->returnValue(FALSE));
-    $access = $this->getMockBuilder('Drupal\Core\Access\AccessManager')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $account = $this->getMockBuilder('Drupal\Core\Session\AccountInterface')
-      ->getMock();
-    $route_provider = $this->getMockBuilder('Drupal\Core\Routing\RouteProviderInterface')
-      ->getMock();
+    $access = $this->createMock('Drupal\Core\Access\AccessManager');
+    $account = $this->createMock('Drupal\Core\Session\AccountInterface');
+    $route_provider = $this->createMock('Drupal\Core\Routing\RouteProviderInterface');
 
     $route = new Route('/example');
     $route_provider->expects($this->any())
@@ -77,8 +71,7 @@ public function testCanRedirect() {
     $this->assertFalse($checker->canRedirect($request), 'Cannot redirect');
 
     // Maintenance mode is on.
-    $state = $this->getMockBuilder('Drupal\Core\State\StateInterface')
-      ->getMock();
+    $state = $this->createMock('Drupal\Core\State\StateInterface');
     $state->expects($this->any())
       ->method('get')
       ->with('system.maintenance_mode')
@@ -89,9 +82,20 @@ public function testCanRedirect() {
     $request = $this->getRequestStub('index.php', 'GET');
     $this->assertFalse($checker->canRedirect($request), 'Cannot redirect if maintenance mode is on');
 
+    // Maintenance mode is on, but user has access to view site in maintenance mode.
+    $accountWithMaintenanceModeAccess = $this->createMock('Drupal\Core\Session\AccountInterface');
+    $accountWithMaintenanceModeAccess->expects($this->any())
+      ->method('hasPermission')
+      ->with('access site in maintenance mode')
+      ->will($this->returnValue(TRUE));
+
+    $checker = new RedirectChecker($this->getConfigFactoryStub($config), $state, $access, $accountWithMaintenanceModeAccess, $route_provider);
+
+    $request = $this->getRequestStub('index.php', 'GET');
+    $this->assertTrue($checker->canRedirect($request), 'Redirect should have worked, user has maintenance mode access.');
+
     // We are at a admin path.
-    $state = $this->getMockBuilder('Drupal\Core\State\StateInterface')
-      ->getMock();
+    $state = $this->createMock('Drupal\Core\State\StateInterface');
     $state->expects($this->any())
       ->method('get')
       ->with('system.maintenance_mode')
@@ -132,13 +136,11 @@ public function testCanRedirect() {
    * @param array $query
    *   Query paramter to be passed into request->query.
    *
-   * @return PHPUnit_Framework_MockObject_MockObject
+   * @return \PHPUnit\Framework\MockObject\MockObject
    *   Mocked request object.
    */
   protected function getRequestStub($script_name, $method, array $attributes = [], array $query = []) {
-    $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $request = $this->createMock('Symfony\Component\HttpFoundation\Request');
     $request->expects($this->any())
       ->method('getScriptName')
       ->will($this->returnValue($script_name));
diff --git a/web/modules/redirect/tests/src/Unit/RedirectRequestSubscriberTest.php b/web/modules/redirect/tests/src/Unit/RedirectRequestSubscriberTest.php
index 3f384698cb64afec13e9c02aa7539951735b19d4..18c179b380460def824d8d042d7505ff121d14bb 100644
--- a/web/modules/redirect/tests/src/Unit/RedirectRequestSubscriberTest.php
+++ b/web/modules/redirect/tests/src/Unit/RedirectRequestSubscriberTest.php
@@ -8,12 +8,11 @@
 use Drupal\path_alias\AliasManagerInterface;
 use Drupal\redirect\EventSubscriber\RedirectRequestSubscriber;
 use Drupal\Tests\UnitTestCase;
-use PHPUnit_Framework_MockObject_MockObject;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\HttpKernel\Event\PostResponseEvent;
+use Symfony\Component\HttpKernel\Event\RequestEvent;
+use Symfony\Component\HttpKernel\Event\TerminateEvent;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
 
 /**
@@ -35,9 +34,7 @@ public function testRedirectLogicWithQueryRetaining($request_uri, $request_query
     // by the redirect entity and values from the accessed url.
     $final_query = $redirect_query + $request_query;
 
-    $url = $this->getMockBuilder('Drupal\Core\Url')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $url = $this->createMock('Drupal\Core\Url');
 
     $url->expects($this->once())
       ->method('setAbsolute')
@@ -73,9 +70,7 @@ public function testRedirectLogicWithQueryRetaining($request_uri, $request_query
    */
   public function testRedirectLogicWithoutQueryRetaining($request_uri, $request_query, $redirect_uri) {
 
-    $url = $this->getMockBuilder('Drupal\Core\Url')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $url = $this->createMock('Drupal\Core\Url');
 
     $url->expects($this->once())
       ->method('setAbsolute')
@@ -125,7 +120,7 @@ public function getRedirectData() {
    * @param bool $retain_query
    *   Flag if to retain the query through the redirect.
    *
-   * @return \Symfony\Component\HttpKernel\Event\GetResponseEvent
+   * @return \Symfony\Component\HttpKernel\Event\RequestEvent
    *   THe response event.
    */
   protected function callOnKernelRequestCheckRedirect($redirect, $request_uri, $request_query, $retain_query) {
@@ -133,18 +128,14 @@ protected function callOnKernelRequestCheckRedirect($redirect, $request_uri, $re
     $event = $this->getGetResponseEventStub($request_uri, http_build_query($request_query));
     $request = $event->getRequest();
 
-    $checker = $this->getMockBuilder('Drupal\redirect\RedirectChecker')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $checker = $this->createMock('Drupal\redirect\RedirectChecker');
     $checker->expects($this->any())
       ->method('canRedirect')
       ->will($this->returnValue(TRUE));
 
     $context = $this->createMock('Symfony\Component\Routing\RequestContext');
 
-    $inbound_path_processor = $this->getMockBuilder('Drupal\Core\PathProcessor\InboundPathProcessorInterface')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $inbound_path_processor = $this->createMock('Drupal\Core\PathProcessor\InboundPathProcessorInterface');
     $inbound_path_processor->expects($this->any())
       ->method('processInbound')
       ->with($request->getPathInfo(), $request)
@@ -189,13 +180,11 @@ protected function callOnKernelRequestCheckRedirect($redirect, $request_uri, $re
    * @param $redirect
    *   The redirect object to be returned.
    *
-   * @return PHPUnit_Framework_MockObject_MockObject
+   * @return \PHPUnit\Framework\MockObject\MockObject
    *   The redirect repository.
    */
   protected function getRedirectRepositoryStub($method, $redirect) {
-    $repository = $this->getMockBuilder('Drupal\redirect\RedirectRepository')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $repository = $this->createMock('Drupal\redirect\RedirectRepository');
 
     if ($method === 'findMatchingRedirect') {
       $repository->expects($this->any())
@@ -223,13 +212,11 @@ protected function getRedirectRepositoryStub($method, $redirect) {
    * @param int $status_code
    *   The redirect status code.
    *
-   * @return PHPUnit_Framework_MockObject_MockObject
+   * @return \PHPUnit\Framework\MockObject\MockObject
    *   The mocked redirect object.
    */
   protected function getRedirectStub($url, $status_code = 301) {
-    $redirect = $this->getMockBuilder('Drupal\redirect\Entity\Redirect')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $redirect = $this->createMock('Drupal\redirect\Entity\Redirect');
     $redirect->expects($this->once())
       ->method('getRedirectUrl')
       ->will($this->returnValue($url));
@@ -252,19 +239,16 @@ protected function getRedirectStub($url, $status_code = 301) {
    * @param array $headers
    *   Headers to be set into the response.
    *
-   * @return \Symfony\Component\HttpKernel\Event\PostResponseEvent
+   * @return \Symfony\Component\HttpKernel\Event\TerminateEvent
    *   The post response event object.
    */
   protected function getPostResponseEvent($headers = []) {
-    $http_kernel = $this->getMockBuilder('\Symfony\Component\HttpKernel\HttpKernelInterface')
-      ->getMock();
-    $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $http_kernel = $this->createMock('\Symfony\Component\HttpKernel\HttpKernelInterface');
+    $request = $this->createMock('Symfony\Component\HttpFoundation\Request');
 
     $response = new Response('', 301, $headers);
 
-    return new PostResponseEvent($http_kernel, $request, $response);
+    return new TerminateEvent($http_kernel, $request, $response);
   }
 
   /**
@@ -273,24 +257,22 @@ protected function getPostResponseEvent($headers = []) {
    * @param $path_info
    * @param $query_string
    *
-   * @return GetResponseEvent
+   * @return RequestEvent
    */
   protected function getGetResponseEventStub($path_info, $query_string) {
     $request = Request::create($path_info . '?' . $query_string, 'GET', [], [], [], ['SCRIPT_NAME' => 'index.php']);
 
-    $http_kernel = $this->getMockBuilder('\Symfony\Component\HttpKernel\HttpKernelInterface')
-      ->getMock();
-    return new GetResponseEvent($http_kernel, $request, HttpKernelInterface::MASTER_REQUEST);
+    $http_kernel = $this->createMock('\Symfony\Component\HttpKernel\HttpKernelInterface');
+    return new RequestEvent($http_kernel, $request, HttpKernelInterface::MASTER_REQUEST);
   }
 
   /**
    * Gets the language manager mock object.
    *
-   * @return \Drupal\language\ConfigurableLanguageManagerInterface|PHPUnit_Framework_MockObject_MockObject
+   * @return \Drupal\language\ConfigurableLanguageManagerInterface|\PHPUnit\Framework\MockObject\MockObject
    */
   protected function getLanguageManagerStub() {
-    $language_manager = $this->getMockBuilder('Drupal\language\ConfigurableLanguageManagerInterface')
-      ->getMock();
+    $language_manager = $this->createMock('Drupal\language\ConfigurableLanguageManagerInterface');
     $language_manager->expects($this->any())
       ->method('getCurrentLanguage')
       ->will($this->returnValue(new Language(['id' => 'en'])));
diff --git a/web/modules/redirect/tests/src/Unit/RouteNormalizerRequestSubscriberTest.php b/web/modules/redirect/tests/src/Unit/RouteNormalizerRequestSubscriberTest.php
index 69a6682cf6e9f21f7dde7f482f97cb6a9f3d416d..de3d3dda292fba88d74130d9a31e0600ddcf1fd3 100644
--- a/web/modules/redirect/tests/src/Unit/RouteNormalizerRequestSubscriberTest.php
+++ b/web/modules/redirect/tests/src/Unit/RouteNormalizerRequestSubscriberTest.php
@@ -4,7 +4,7 @@
 
 use Drupal\Tests\UnitTestCase;
 use Drupal\redirect\EventSubscriber\RouteNormalizerRequestSubscriber;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\Event\RequestEvent;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
@@ -21,7 +21,7 @@ class RouteNormalizerRequestSubscriberTest extends UnitTestCase {
   /**
    * {@inheritdoc}
    */
-  protected function setUp() {
+  protected function setUp(): void {
     parent::setUp();
 
     $kill_switch = $this->createMock('\Drupal\Core\PageCache\ResponsePolicy\KillSwitch');
@@ -98,7 +98,8 @@ public function getTestUrls() {
     return [
       ['https://example.com/route-to-normalize', [], 'https://example.com/route-to-normalize', FALSE],
       ['https://example.com/route-to-normalize', ['key' => 'value'], 'https://example.com/route-to-normalize?key=value', FALSE],
-      ['https://example.com/index.php/', ['q' => 'node/1'], 'https://example.com/?q=node/1', TRUE],
+      ['https://example.com/index.php/', ['q' => 'node/1'], 'https://example.com/?q=node%2F1', TRUE],
+      ['https://example.com/index.php/', ['q' => 'node/1', 'p' => 'a+b'], 'https://example.com/?q=node%2F1&p=a%2Bb', TRUE],
     ];
   }
 
@@ -139,8 +140,7 @@ protected function getSubscriber($request_uri, $enabled = TRUE, $call_expected =
    * @return \Drupal\Core\Routing\UrlGeneratorInterface|\PHPUnit\Framework\MockObject\MockObject
    */
   protected function getUrlGeneratorStub($request_uri, $call_expected = TRUE) {
-    $url_generator = $this->getMockBuilder('\Drupal\Core\Routing\UrlGeneratorInterface')
-      ->getMock();
+    $url_generator = $this->createMock('\Drupal\Core\Routing\UrlGeneratorInterface');
 
     $options = ['absolute' => TRUE];
 
@@ -162,8 +162,7 @@ protected function getUrlGeneratorStub($request_uri, $call_expected = TRUE) {
    * @return \Drupal\Core\Path\PathMatcherInterface|\PHPUnit\Framework\MockObject\MockObject
    */
   protected function getPathMatcherStub($call_expected = TRUE) {
-    $path_matcher = $this->getMockBuilder('\Drupal\Core\Path\PathMatcherInterface')
-      ->getMock();
+    $path_matcher = $this->createMock('\Drupal\Core\Path\PathMatcherInterface');
 
     $expectation = $call_expected ? $this->once() : $this->never();
 
@@ -183,9 +182,7 @@ protected function getPathMatcherStub($call_expected = TRUE) {
    * @return \Drupal\redirect\RedirectChecker|\PHPUnit\Framework\MockObject\MockObject
    */
   protected function getRedirectCheckerStub($call_expected = TRUE) {
-    $redirect_checker = $this->getMockBuilder('\Drupal\redirect\RedirectChecker')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $redirect_checker = $this->createMock('\Drupal\redirect\RedirectChecker');
 
     $expectation = $call_expected ? $this->once() : $this->never();
 
@@ -208,7 +205,7 @@ protected function getRedirectCheckerStub($call_expected = TRUE) {
    * @param bool $set_request_attribute
    *   If true, the request attribute '_disable_route_normalizer' will be set.
    *
-   * @return \Symfony\Component\HttpKernel\Event\GetResponseEvent
+   * @return \Symfony\Component\HttpKernel\Event\RequestEvent
    */
   protected function getGetResponseEventStub($path_info, $query_string, $request_type = HttpKernelInterface::MASTER_REQUEST, $set_request_attribute = FALSE) {
     $request = Request::create($path_info . '?' . $query_string, 'GET', [], [], [], ['SCRIPT_NAME' => 'index.php', 'SCRIPT_FILENAME' => 'index.php']);
@@ -217,9 +214,8 @@ protected function getGetResponseEventStub($path_info, $query_string, $request_t
       $request->attributes->add(['_disable_route_normalizer' => TRUE]);
     }
 
-    $http_kernel = $this->getMockBuilder('\Symfony\Component\HttpKernel\HttpKernelInterface')
-      ->getMock();
-    return new GetResponseEvent($http_kernel, $request, $request_type);
+    $http_kernel = $this->createMock('\Symfony\Component\HttpKernel\HttpKernelInterface');
+    return new RequestEvent($http_kernel, $request, $request_type);
   }
 
 }