diff --git a/modules/project_browser_source_example/src/Plugin/ProjectBrowserSource/ProjectBrowserSourceExample.php b/modules/project_browser_source_example/src/Plugin/ProjectBrowserSource/ProjectBrowserSourceExample.php
index 5ff23ebdb72c1d19cd354a7a112f6d069fca260c..facbb1891d87a2a2f3ad756820ca528b66488135 100644
--- a/modules/project_browser_source_example/src/Plugin/ProjectBrowserSource/ProjectBrowserSourceExample.php
+++ b/modules/project_browser_source_example/src/Plugin/ProjectBrowserSource/ProjectBrowserSourceExample.php
@@ -80,7 +80,7 @@ final class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
         'short_description' => 'Quick summary to show in the cards.',
         'long_description' => 'Extended project information to show in the detail page',
         'author' => 'Jane Doe',
-        'logo' => $request->getSchemeAndHttpHost() . '/core/misc/logo/drupal-logo.svg',
+        'logo' => $request?->getSchemeAndHttpHost() . '/core/misc/logo/drupal-logo.svg',
         'created_at' => strtotime('1 year ago'),
         'updated_at' => strtotime('1 month ago'),
         'categories' => ['cat_1:Category 1'],
diff --git a/phpstan.neon b/phpstan.neon
index 8676e942c2636fc66ccdc8edd262e47d536dbdc7..7a55e55fd4b88b8a3d7423d52b2f4ec92135aeab 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -1,5 +1,5 @@
 parameters:
-  level: 7
+  level: 8
   universalObjectCratesClasses:
     - Drupal\Core\Extension\Extension
   reportUnmatchedIgnoredErrors: true
diff --git a/src/Drush/Commands/ProjectBrowserCommands.php b/src/Drush/Commands/ProjectBrowserCommands.php
index 34e89aa41fa3013c213c89ea7c48c5aba5b41ed5..89d132808382962c068e41a4f3759d8b0b2c179c 100644
--- a/src/Drush/Commands/ProjectBrowserCommands.php
+++ b/src/Drush/Commands/ProjectBrowserCommands.php
@@ -28,7 +28,7 @@ final class ProjectBrowserCommands extends DrushCommands {
   #[Usage(name: 'project-browser:storage-clear', description: 'Clear stored Project Browser data')]
   public function storageClear(): void {
     $this->enabledSourceHandler->clearStorage();
-    $this->logger()->success(dt('Stored data from Project Browser sources have been cleared.'));
+    $this->logger()?->success(dt('Stored data from Project Browser sources have been cleared.'));
   }
 
 }
diff --git a/src/Element/ProjectBrowser.php b/src/Element/ProjectBrowser.php
index b540544a725276ce77f170f344cd05105a9ac53f..757a955cd7a2c6165f9b6d4193454c606cbb5901 100644
--- a/src/Element/ProjectBrowser.php
+++ b/src/Element/ProjectBrowser.php
@@ -126,7 +126,7 @@ final class ProjectBrowser implements ElementInterface, ContainerFactoryPluginIn
     ];
     // @todo Fix https://www.drupal.org/node/3494512 to avoid adding
     // hard-coded values. #techdebt
-    if ($source->getPluginId() !== 'recipes' && $package_manager['available']) {
+    if ($source->getPluginId() !== 'recipes' && $package_manager['available'] && is_object($this->installReadiness)) {
       $package_manager = array_merge($package_manager, $this->installReadiness->validatePackageManager());
       $package_manager['status_checked'] = TRUE;
     }
diff --git a/src/Plugin/ProjectBrowserSource/DrupalCore.php b/src/Plugin/ProjectBrowserSource/DrupalCore.php
index e08871abc4f3289182fe15d0ba748b16601a16cf..2129ede94e950ed4c928e6e54522c9a9abb6a1bb 100644
--- a/src/Plugin/ProjectBrowserSource/DrupalCore.php
+++ b/src/Plugin/ProjectBrowserSource/DrupalCore.php
@@ -181,7 +181,7 @@ final class DrupalCore extends ProjectBrowserSourceBase {
       $returned_list[] = new Project(
         logo: [
           'file' => [
-            'uri' => $request->getSchemeAndHttpHost() . '/core/misc/logo/drupal-logo.svg',
+            'uri' => $request?->getSchemeAndHttpHost() . '/core/misc/logo/drupal-logo.svg',
             'resource' => 'image',
           ],
           'alt' => '',
diff --git a/src/Plugin/ProjectBrowserSource/Recipes.php b/src/Plugin/ProjectBrowserSource/Recipes.php
index 1090c70ff2792f1086dff9e499162a73d2cf0f41..6b671641242309b7f3ac2b57de08500ace4eef81 100644
--- a/src/Plugin/ProjectBrowserSource/Recipes.php
+++ b/src/Plugin/ProjectBrowserSource/Recipes.php
@@ -183,6 +183,7 @@ final class Recipes extends ProjectBrowserSourceBase {
     $contrib_recipe_names = InstalledVersions::getInstalledPackagesByType(Recipe::COMPOSER_PROJECT_TYPE);
     if ($contrib_recipe_names) {
       $path = InstalledVersions::getInstallPath($contrib_recipe_names[0]);
+      assert(is_string($path));
       $path = $this->fileSystem->realpath($path);
       assert(is_string($path));
 
diff --git a/src/RecipeActivator.php b/src/RecipeActivator.php
index ebbaf6ab1828faafc72f9d582cc93c4580a37315..72df6d4afc7dab83bb16425fd59e9235d0c9d64e 100644
--- a/src/RecipeActivator.php
+++ b/src/RecipeActivator.php
@@ -93,6 +93,10 @@ final class RecipeActivator implements ActivatorInterface, EventSubscriberInterf
    */
   public function activate(Project $project): ?Response {
     $path = $this->getPath($project);
+    if (!$path) {
+      return NULL;
+    }
+
     $recipe = Recipe::createFromDirectory($path);
 
     // If the recipe has input, return a response that will instruct the Svelte
diff --git a/tests/modules/project_browser_test/src/DrupalOrgClientMiddleware.php b/tests/modules/project_browser_test/src/DrupalOrgClientMiddleware.php
index c76a7a580b4a686af3af9bcc132863aafe3e4874..4e14e69765d40e0518abfc461c9fdf07c2624dfb 100644
--- a/tests/modules/project_browser_test/src/DrupalOrgClientMiddleware.php
+++ b/tests/modules/project_browser_test/src/DrupalOrgClientMiddleware.php
@@ -123,8 +123,8 @@ class DrupalOrgClientMiddleware {
           $relevant_path = str_replace(DrupalDotOrgJsonApi::JSONAPI_ENDPOINT, '', $actual_api_endpoint);
           // Remove semver query as it is core version dependent.
           // Processed query will act as relevant path to fixtures.
-          $relevant_path = preg_replace('/&filter%5Bcore_semver_minimum%5D%5Bvalue%5D=[0-9]*/', '', $relevant_path);
-          $relevant_path = preg_replace('/&filter%5Bcore_semver_maximum%5D%5Bvalue%5D=[0-9]*/', '', $relevant_path);
+          $relevant_path = (string) preg_replace('/&filter%5Bcore_semver_minimum%5D%5Bvalue%5D=[0-9]*/', '', $relevant_path);
+          $relevant_path = (string) preg_replace('/&filter%5Bcore_semver_maximum%5D%5Bvalue%5D=[0-9]*/', '', $relevant_path);
           $path_to_fixture = self::DRUPALORG_JSONAPI_ENDPOINT_TO_FIXTURE_MAP;
           if (isset($path_to_fixture[$relevant_path])) {
             $module_path = $this->moduleHandler->getModule('project_browser')->getPath();
diff --git a/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php b/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php
index 3b8b8273d4af51a94242a635169601db3849ef4c..6dbe6c8d67bb3282590960026062f0a8c873913d 100644
--- a/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php
+++ b/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php
@@ -461,13 +461,13 @@ final class ProjectBrowserTestMock extends ProjectBrowserSourceBase {
       // projects.
       $total_results = $db_query->countQuery()
         ->execute()
-        ->fetchField();
+        ?->fetchField();
       $offset = $query['page'] ?? 0;
       $limit = $query['limit'] ?? 50;
       $db_query->range($limit * $offset, $limit);
       $result = $db_query
         ->execute()
-        ->fetchAll();
+        ?->fetchAll() ?? [];
       $db_projects = array_map(function ($project_data) {
         $data = (array) $project_data;
         $data['project_data'] = unserialize($project_data->project_data);
diff --git a/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php b/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php
index 71b145438080ef99392528be5753d62c141648ec..d4ea81f0a44cb8eaeded8656680a183614d142d3 100644
--- a/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php
+++ b/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php
@@ -195,7 +195,7 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase {
     $this->assertNotEmpty($download_button);
     $this->assertSame('Install Cream cheese on a bagel', $download_button->getText());
     $this->drupalGet('/admin/config/development/project_browser');
-    $page->find('css', '#edit-allow-ui-install')->click();
+    $page->find('css', '#edit-allow-ui-install')?->click();
     $assert_session->checkboxNotChecked('edit-allow-ui-install');
     $this->submitForm([], 'Save');
     $this->assertTrue($assert_session->waitForText('The configuration options have been saved.'));
@@ -227,7 +227,7 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase {
     // the applying stage.
     $cream_cheese_module_selector = '#project-browser .pb-layout__main ul > li:nth-child(1)';
     $cream_cheese_button = $page->find('css', "$cream_cheese_module_selector button.project__action_button");
-    $cream_cheese_button->click();
+    $cream_cheese_button?->click();
 
     $this->assertTrue($assert_session->waitForText('The process for adding projects is locked, but that lock has expired. Use unlock link to unlock the process and try to add the project again.'));
 
@@ -236,7 +236,7 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase {
     $this->svelteInitHelper('text', 'Cream cheese on a bagel');
     // Try beginning another install after breaking lock.
     $cream_cheese_button = $page->find('css', "$cream_cheese_module_selector button.project__action_button");
-    $cream_cheese_button->click();
+    $cream_cheese_button?->click();
     $installed_action = $assert_session->waitForElementVisible('css', "$cream_cheese_module_selector .project_status-indicator", 30000);
     $assert_session->waitForText('Cream cheese on a bagel is Installed');
     $this->assertSame('Cream cheese on a bagel is Installed', $installed_action->getText());
@@ -267,14 +267,14 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase {
     // the applying stage.
     $cream_cheese_module_selector = '#project-browser .pb-layout__main ul > li:nth-child(1)';
     $cream_cheese_button = $page->find('css', "$cream_cheese_module_selector button.project__action_button");
-    $cream_cheese_button->click();
+    $cream_cheese_button?->click();
     $this->assertTrue($assert_session->waitForText('The process for adding projects is locked, but that lock has expired. Use unlock link to unlock the process and try to add the project again.'));
     // Click Unlock Install Stage link.
     $this->clickWithWait('#ui-id-1 > p > a');
     $this->svelteInitHelper('text', 'Cream cheese on a bagel');
     // Try beginning another install after breaking lock.
     $cream_cheese_button = $page->find('css', "$cream_cheese_module_selector button.project__action_button");
-    $cream_cheese_button->click();
+    $cream_cheese_button?->click();
     $installed_action = $assert_session->waitForElementVisible('css', "$cream_cheese_module_selector .project_status-indicator", 30000);
     $assert_session->waitForText('Cream cheese on a bagel is Installed');
     $this->assertSame('Cream cheese on a bagel is Installed', $installed_action->getText());
@@ -375,7 +375,7 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase {
     $this->assertTrue($was_selected);
 
     $dancing_queen_button = $page->find('css', '#project-browser .pb-layout__main ul > li:nth-child(3) button');
-    $this->assertFalse($dancing_queen_button->hasAttribute('disabled'));
+    $this->assertFalse($dancing_queen_button?->hasAttribute('disabled'));
 
     $this->assertNotEmpty($assert_session->waitForButton('Install selected projects'));
 
diff --git a/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php b/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php
index 252acbd106e2f8f460f7f6ea7a3999a7432f0f40..fbbc5ebbadfc979b83b57fa42bd4499ff2a1252d 100644
--- a/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php
+++ b/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php
@@ -91,7 +91,7 @@ class ProjectBrowserPluginTest extends WebDriverTestBase {
     $this->svelteInitHelper('css', '.pager__item--next');
     $assert_session->elementsCount('css', '.pager__item--next', 1);
 
-    $page->find('css', 'a[aria-label="Next page"]')->click();
+    $page->find('css', 'a[aria-label="Next page"]')?->click();
     $this->assertNotNull($assert_session->waitForElement('css', '.pager__item--previous'));
     $assert_session->elementsCount('css', '.pager__item--previous', 1);
   }
@@ -163,7 +163,7 @@ class ProjectBrowserPluginTest extends WebDriverTestBase {
 
     $assert_session->waitForElementVisible('css', '.pb-project .pb-project__title');
     $first_project_selector = $page->find('css', '.pb-project .pb-project__title .pb-project__link');
-    $first_project_selector->click();
+    $first_project_selector?->click();
     $this->assertTrue($assert_session->waitForText('sites report using this module'));
   }
 
diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php
index d65af3c06423a1bb04e1c5d61f43a16e2bf08c20..b15114f2456ea41cf4682789dd339b2e05686587 100644
--- a/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php
+++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php
@@ -152,13 +152,13 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $this->clickWithWait('#104', '10 Results');
 
     // Use blur event to close drop-down so Clear is visible.
-    $this->assertSession()->elementExists('css', '.pb-filter__multi-dropdown')->blur();
+    $assert_session->elementExists('css', '.pb-filter__multi-dropdown')->blur();
 
     $this->pressWithWait('Clear filters', '25 Results');
 
     // Open category drop-down again by pressing space.
-    $this->assertSession()->elementExists('css', '.pb-filter__multi-dropdown')->keyDown(' ');
-    $this->assertSession()->waitForText('Media');
+    $assert_session->elementExists('css', '.pb-filter__multi-dropdown')->keyDown(' ');
+    $assert_session->waitForText('Media');
 
     // Click 'Media' checkbox.
     $this->clickWithWait('#67');
@@ -222,6 +222,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $download_commands = $page->findAll('css', '.command-box img');
     $this->assertCount(2, $download_commands);
     $this->assertEquals('Copy the download command', $download_commands[0]->getAttribute('alt'));
+    $this->assertIsString($download_commands[1]->getAttribute('alt'));
     $this->assertStringStartsWith('Copy the install command', $download_commands[1]->getAttribute('alt'));
   }
 
@@ -533,6 +534,8 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
    * Tests search with strings that need URI encoding.
    */
   public function testSearchForSpecialChar(): void {
+    $assert_session = $this->assertSession();
+
     // Clear filters.
     $this->drupalGet('admin/modules/browse/project_browser_test_mock');
     $this->svelteInitHelper('text', '10 Results');
@@ -541,7 +544,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     // Fill in the search field.
     $this->inputSearchField('', TRUE);
     $this->inputSearchField('&', TRUE);
-    $this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();
+    $assert_session->waitForElementVisible('css', ".search__search-submit")?->click();
     $this->assertProjectsVisible([
       'Vitamin&C;$?',
       'Unwritten&:/',
@@ -550,7 +553,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     // Fill in the search field.
     $this->inputSearchField('', TRUE);
     $this->inputSearchField('n&', TRUE);
-    $this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();
+    $assert_session->waitForElementVisible('css', ".search__search-submit")?->click();
     $this->assertProjectsVisible([
       'Vitamin&C;$?',
       'Unwritten&:/',
@@ -558,28 +561,28 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
 
     $this->inputSearchField('', TRUE);
     $this->inputSearchField('$', TRUE);
-    $this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();
+    $assert_session->waitForElementVisible('css', ".search__search-submit")?->click();
     $this->assertProjectsVisible([
       'Vitamin&C;$?',
     ]);
 
     $this->inputSearchField('', TRUE);
     $this->inputSearchField('?', TRUE);
-    $this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();
+    $assert_session->waitForElementVisible('css', ".search__search-submit")?->click();
     $this->assertProjectsVisible([
       'Vitamin&C;$?',
     ]);
 
     $this->inputSearchField('', TRUE);
     $this->inputSearchField('&:', TRUE);
-    $this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();
+    $assert_session->waitForElementVisible('css', ".search__search-submit")?->click();
     $this->assertProjectsVisible([
       'Unwritten&:/',
     ]);
 
     $this->inputSearchField('', TRUE);
     $this->inputSearchField('$?', TRUE);
-    $this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();
+    $assert_session->waitForElementVisible('css', ".search__search-submit")?->click();
     $this->assertProjectsVisible([
       'Vitamin&C;$?',
     ]);
@@ -616,7 +619,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $assert_session->waitForButton('Close')?->click();
     $assert_session->elementNotExists('xpath', '//span[contains(@class, "ui-dialog-title") and text()="Helvetica"]');
     // Check that a different module modal can be opened.
-    $assert_session->waitForButton('Octopus')->click();
+    $assert_session->waitForButton('Octopus')?->click();
     $assert_session->waitForElementVisible('xpath', '//span[contains(@class, "ui-dialog-title") and text()="Octopus"]');
     $assert_session->waitForButton('Close')?->click();
     $assert_session->elementNotExists('xpath', '//span[contains(@class, "ui-dialog-title") and text()="Octopus"]');
@@ -644,7 +647,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $this->clickWithWait(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_FIRST_CHILD);
 
     // Open category drop-down.
-    $assert_session->elementExists('css', '.pb-filter__multi-dropdown')->click();
+    $assert_session->elementExists('css', '.pb-filter__multi-dropdown')?->click();
 
     // Select the E-commerce filter.
     $assert_session->waitForElementVisible('css', '#104');
@@ -770,7 +773,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $this->assertSame($second_tab_text, $assert_session->buttonExists('random_data')->getText());
 
     // Use blur event to close drop-down so Clear is visible.
-    $this->assertSession()->elementExists('css', '.pb-filter__multi-dropdown')->blur();
+    $assert_session->elementExists('css', '.pb-filter__multi-dropdown')->blur();
     $this->assertSame('2 categories selected', $page->find('css', '.pb-filter__multi-dropdown__label')->getText());
 
     // Click other tab.
@@ -783,7 +786,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $this->assertEquals($second_tab_text . ' (active tab)', $page->findButton('random_data')->getText());
 
     // Open category drop-down again by pressing space.
-    $this->assertSession()->elementExists('css', '.pb-filter__multi-dropdown')->keyDown(' ');
+    $assert_session->elementExists('css', '.pb-filter__multi-dropdown')->keyDown(' ');
 
     // Apply the second module category filter.
     $second_category_filter_selector = '.pb-filter__multi-dropdown__items > div:nth-child(2) input';
@@ -824,7 +827,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $this->pressWithWait('project_browser_test_mock');
     // Filter by search text.
     $this->inputSearchField('Number', TRUE);
-    $assert_session->waitForElementVisible('css', ".search__search-submit")->click();
+    $assert_session->waitForElementVisible('css', ".search__search-submit")?->click();
     $this->assertTrue($assert_session->waitForText('2 Results'));
     $this->assertProjectsVisible([
       '9 Starts With a Higher Number',
@@ -848,6 +851,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
    * Tests the view mode toggle keeps its state.
    */
   public function testToggleViewState(): void {
+    $page = $this->getSession()->getPage();
     $assert_session = $this->assertSession();
     $viewSwitches = [
       [
@@ -863,12 +867,12 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     foreach ($viewSwitches as $selector) {
       $this->drupalGet('admin/modules/browse/project_browser_test_mock');
       $this->svelteInitHelper('css', $selector['selector']);
-      $this->getSession()->getPage()->pressButton($selector['value']);
+      $page->pressButton($selector['value']);
       $this->svelteInitHelper('text', 'Helvetica');
       $assert_session->waitForButton('Helvetica')?->click();
       $this->svelteInitHelper('text', 'Close');
       $assert_session->waitForButton('Close')?->click();
-      $this->assertSession()->elementExists('css', $selector['selector'] . '.pb-display__button--selected');
+      $assert_session->elementExists('css', $selector['selector'] . '.pb-display__button--selected');
     }
   }
 
@@ -895,7 +899,9 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $this->drupalGet('admin/config/development/project_browser');
     $first_plugin = $page->find('css', '#source--project_browser_test_mock');
     $second_plugin = $page->find('css', '#source--random_data');
-    $first_plugin->find('css', '.handle')->dragTo($second_plugin);
+    $this->assertNotNull($second_plugin);
+    $first_plugin?->find('css', '.handle')?->dragTo($second_plugin);
+    $this->assertNotNull($first_plugin);
     $this->assertTableRowWasDragged($first_plugin);
     $this->submitForm([], 'Save');
 
@@ -907,7 +913,9 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $this->drupalGet('admin/config/development/project_browser');
     $enabled_row = $page->find('css', '#source--project_browser_test_mock');
     $disabled_region_row = $page->find('css', '.status-title-disabled');
-    $enabled_row->find('css', '.handle')->dragTo($disabled_region_row);
+    $this->assertNotNull($disabled_region_row);
+    $enabled_row?->find('css', '.handle')?->dragTo($disabled_region_row);
+    $this->assertNotNull($enabled_row);
     $this->assertTableRowWasDragged($enabled_row);
     $this->submitForm([], 'Save');
     $assert_session->pageTextContains('The configuration options have been saved.');
@@ -932,6 +940,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
    * Tests the visibility of categories in list and grid view.
    */
   public function testCategoriesVisibility(): void {
+    $page = $this->getSession()->getPage();
     $assert_session = $this->assertSession();
     $view_options = [
       [
@@ -948,7 +957,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     foreach ($view_options as $selector) {
       $this->drupalGet('admin/modules/browse/project_browser_test_mock');
       $this->svelteInitHelper('css', $selector['selector']);
-      $this->getSession()->getPage()->pressButton($selector['value']);
+      $page->pressButton($selector['value']);
       $this->svelteInitHelper('text', 'Helvetica');
       $assert_session->elementsCount('css', '#project-browser .pb-layout__main ul li:nth-child(7) .pb-project-categories ul li', 1);
       $grid_text = $this->getElementText('#project-browser .pb-layout__main ul li:nth-child(7) .pb-project-categories ul li:nth-child(1)');
@@ -1012,13 +1021,15 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $this->svelteInitHelper('css', '.pb-project.pb-project--list');
 
     $this->inputSearchField('inline form errors', TRUE);
-    $assert_session->waitForElementVisible('css', ".search__search-submit")->click();
+    $assert_session->waitForElementVisible('css', ".search__search-submit")?->click();
     $this->svelteInitHelper('text', 'Inline Form Errors');
 
     $install_link = $page->find('css', '.pb-layout__main .pb-actions a');
 
-    $this->assertStringContainsString('admin/modules#module-inline-form-errors', $install_link->getAttribute('href'));
-    $this->drupalGet($install_link->getAttribute('href'));
+    $href = $install_link?->getAttribute('href');
+    $this->assertIsString($href);
+    $this->assertStringContainsString('admin/modules#module-inline-form-errors', $href);
+    $this->drupalGet($href);
     $assert_session->waitForElementVisible('css', "#edit-modules-inline-form-errors-enable");
     $assert_session->assertVisibleInViewport('css', '#edit-modules-inline-form-errors-enable');
   }
@@ -1027,9 +1038,11 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
    * Confirms UI install can not be enabled without Package Manager installed.
    */
   public function testUiInstallNeedsPackageManager(): void {
+    $page = $this->getSession()->getPage();
+
     $this->drupalGet('admin/config/development/project_browser');
-    $ui_install_input = $this->getSession()->getPage()->find('css', '[data-drupal-selector="edit-allow-ui-install"]');
-    $this->assertTrue($ui_install_input->getAttribute('disabled') === 'disabled');
+    $ui_install_input = $page->find('css', '[data-drupal-selector="edit-allow-ui-install"]');
+    $this->assertTrue($ui_install_input?->getAttribute('disabled') === 'disabled');
 
     // @todo Remove try/catch in https://www.drupal.org/i/3349193.
     try {
@@ -1039,8 +1052,8 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
       $this->markTestSkipped($e->getMessage());
     }
     $this->drupalGet('admin/config/development/project_browser');
-    $ui_install_input = $this->getSession()->getPage()->find('css', '[data-drupal-selector="edit-allow-ui-install"]');
-    $this->assertFalse($ui_install_input->hasAttribute('disabled'));
+    $ui_install_input = $page->find('css', '[data-drupal-selector="edit-allow-ui-install"]');
+    $this->assertFalse($ui_install_input?->hasAttribute('disabled'));
   }
 
   /**
@@ -1058,7 +1071,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
 
     // Search for something to change it.
     $this->inputSearchField('abcdefghijklmnop', TRUE);
-    $assert_session->waitForElementVisible('css', ".search__search-submit")->click();
+    $assert_session->waitForElementVisible('css', ".search__search-submit")?->click();
     $this->assertTrue($results->waitFor(10, fn (NodeElement $element) => $element->getText() !== $original_text));
 
     // Remove the search text and make sure it auto-updates.
@@ -1074,13 +1087,13 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
    */
   public function testSearchClearNoTabIndex(): void {
     $page = $this->getSession()->getPage();
-    $this->assertSession();
+    $assert_session = $this->assertSession();
     $this->drupalGet('admin/modules/browse/project_browser_test_mock');
     $this->svelteInitHelper('css', '.pb-search-results');
 
     // Search and confirm clear button has no focus after tabbing.
     $this->inputSearchField('abcdefghijklmnop', TRUE);
-    $this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();
+    $assert_session->waitForElementVisible('css', ".search__search-submit")?->click();
 
     $this->getSession()->getDriver()->keyPress($page->getXpath(), '9');
     $has_focus_id = $this->getSession()->evaluateScript('document.activeElement.id');
@@ -1103,7 +1116,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $this->drupalGet('admin/modules/browse/recipes');
     $this->svelteInitHelper('css', '.pb-projects-list');
     $this->inputSearchField('image', TRUE);
-    $assert_session->waitForElementVisible('css', ".search__search-submit")->click();
+    $assert_session->waitForElementVisible('css', ".search__search-submit")?->click();
 
     // Look for a recipe that ships with core.
     $card = $assert_session->waitForElementVisible('css', '.pb-project:contains("Image media type")');
@@ -1152,6 +1165,8 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
    * Tests that each source plugin has its own dedicated route.
    */
   public function testSourcePluginRoutes(): void {
+    $assert_session = $this->assertSession();
+
     // Enable module for extra source plugin.
     $this->container->get('module_installer')->install(['project_browser_devel'], TRUE);
     $this->rebuildContainer();
@@ -1161,7 +1176,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
 
     foreach (array_keys($current_sources) as $plugin_id) {
       $this->drupalGet("/admin/modules/browse/{$plugin_id}");
-      $this->assertNotNull($this->assertSession()->waitForElementVisible('css', '#project-browser .pb-project.pb-project--list'));
+      $this->assertNotNull($assert_session->waitForElementVisible('css', '#project-browser .pb-project.pb-project--list'));
     }
   }
 
@@ -1170,6 +1185,8 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
    */
   public function testWrenchIcon(): void {
     $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+
     $this->getSession()->resizeWindow(1460, 960);
     $this->drupalGet('admin/modules/browse/project_browser_test_mock');
     $this->svelteInitHelper('text', 'Helvetica');
@@ -1179,7 +1196,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $this->assertTrue($assert_session->waitForText('The module is actively maintained by the maintainers'));
     // This asserts that status icon is present in detail's modal.
     $this->assertNotNull($assert_session->waitForElementVisible('css', '.pb-detail-modal__sidebar .pb-project__status-icon-btn'));
-    $this->getSession()->getPage()->find('css', '.ui-dialog-titlebar-close')->click();
+    $page->find('css', '.ui-dialog-titlebar-close')?->click();
 
     $this->clickWithWait(self::MAINTENANCE_OPTION_SELECTOR . self::OPTION_LAST_CHILD);
     $this->assertEquals('Show all', $this->getElementText(self::MAINTENANCE_OPTION_SELECTOR . self::OPTION_LAST_CHILD));
@@ -1206,21 +1223,21 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
 
     // Locate and click the Grapefruit project link.
     $grapefruit_link = $page->find('xpath', '//button[contains(@class, "pb-project__link") and contains(text(), "Grapefruit")]');
-    $grapefruit_link->click();
+    $grapefruit_link?->click();
 
     // Verify the text for Grapefruit (singular case).
     $this->assertTrue($assert_session->waitForText('site reports using this module'));
 
     // Go back to the project list.
     $close_button = $page->find('xpath', '//button[contains(@class, "ui-dialog-titlebar-close") and contains(text(), "Close")]');
-    $close_button->click();
+    $close_button?->click();
 
     // Expect Octopus to have 235 installs.
     $assert_session->elementExists('xpath', '//span[contains(@class, "pb-project__install-count") and text()="235 installs"]');
 
     // Locate and click the Octopus project link.
     $octopus_link = $page->find('xpath', '//button[contains(@class, "pb-project__link") and contains(text(), "Octopus")]');
-    $octopus_link->click();
+    $octopus_link?->click();
 
     // Verify the text for Octopus (plural case).
     $this->assertTrue($assert_session->waitForText('sites report using this module'));
diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php
index 7e829566a26f90240df8fd7f58b6e41e92bceb4a..7154f5b6cdd85d31bbe8ea662aa502eedc100f67 100644
--- a/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php
+++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php
@@ -418,7 +418,9 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase {
     $this->drupalGet('admin/config/development/project_browser');
     $first_plugin = $page->find('css', '#source--drupalorg_jsonapi');
     $second_plugin = $page->find('css', '#source--random_data');
-    $first_plugin->find('css', '.tabledrag-handle')->dragTo($second_plugin);
+    $this->assertNotNull($second_plugin);
+    $first_plugin?->find('css', '.tabledrag-handle')?->dragTo($second_plugin);
+    $this->assertNotNull($first_plugin);
     $this->assertTableRowWasDragged($first_plugin);
     $this->submitForm([], 'Save');
 
@@ -432,7 +434,9 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase {
     $this->drupalGet('admin/config/development/project_browser');
     $enabled_row = $page->find('css', '#source--drupalorg_jsonapi');
     $disabled_region_row = $page->find('css', '.status-title-disabled');
-    $enabled_row->find('css', '.handle')->dragTo($disabled_region_row);
+    $this->assertNotNull($disabled_region_row);
+    $enabled_row?->find('css', '.handle')?->dragTo($disabled_region_row);
+    $this->assertNotNull($enabled_row);
     $this->assertTableRowWasDragged($enabled_row);
     $this->submitForm([], 'Save');
     $assert_session->pageTextContains('The configuration options have been saved.');
diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTestTrait.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTestTrait.php
index 11e1f10c602f5b4db3eb9a4431c1333a11982c2b..b17b3420b452b1736449d5584b4df2a884d3afe0 100644
--- a/tests/src/FunctionalJavascript/ProjectBrowserUiTestTrait.php
+++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTestTrait.php
@@ -153,7 +153,7 @@ trait ProjectBrowserUiTestTrait {
    */
   protected function openAdvancedFilter(): void {
     $filter_icon_selector = $this->getSession()->getPage()->find('css', '.search__filter__toggle');
-    $filter_icon_selector->click();
+    $filter_icon_selector?->click();
     $this->assertSession()->waitForElementVisible('css', '.search__filter__toggle[aria-expanded="true"]');
   }
 
@@ -274,7 +274,7 @@ trait ProjectBrowserUiTestTrait {
    * @param \Behat\Mink\Element\NodeElement|null $container
    *   The container to look within.
    */
-  protected function waitForField(string $locator, ?NodeElement $container = NULL): NodeElement {
+  protected function waitForField(string $locator, ?NodeElement $container = NULL): ?NodeElement {
     $container ??= $this->getSession()->getPage();
     $this->assertTrue(
       $container->waitFor(10, fn ($container) => $container->findField($locator)?->isVisible()),
diff --git a/tests/src/Kernel/CoreNotUpdatedValidatorTest.php b/tests/src/Kernel/CoreNotUpdatedValidatorTest.php
index ee83bd591eef1c98b647a5eeed3443bbfa757732..87dc30f6724effbbcd3792649cd5a62e569184ac 100644
--- a/tests/src/Kernel/CoreNotUpdatedValidatorTest.php
+++ b/tests/src/Kernel/CoreNotUpdatedValidatorTest.php
@@ -73,7 +73,7 @@ class CoreNotUpdatedValidatorTest extends PackageManagerKernelTestBase {
    */
   public function testPreApplyException(bool $core_updated, array $expected_results): void {
     if ($core_updated) {
-      $this->getStageFixtureManipulator()->setCorePackageVersion('9.8.1');
+      $this->getStageFixtureManipulator()?->setCorePackageVersion('9.8.1');
     }
     /** @var \Drupal\project_browser\ComposerInstaller\Installer $installer */
     $installer = $this->container->get(Installer::class);
diff --git a/tests/src/Kernel/DatabaseTablesTest.php b/tests/src/Kernel/DatabaseTablesTest.php
index 6bfef16d23aea321203714e68dac213ccc7bd61d..f77d32ec9ad48a97f8aaa17d001ed6b97489597c 100644
--- a/tests/src/Kernel/DatabaseTablesTest.php
+++ b/tests/src/Kernel/DatabaseTablesTest.php
@@ -46,9 +46,11 @@ class DatabaseTablesTest extends KernelTestBase {
     // Make sure the fixture files do have data in them.
     /** @var \Drupal\Core\Database\Connection $database */
     $database = $this->container->get('database');
-    $rows = $database->select('project_browser_projects')->countQuery()->execute()->fetchCol();
+    $rows = $database->select('project_browser_projects')->countQuery()->execute()?->fetchCol();
+    $this->assertIsArray($rows);
     $this->assertGreaterThan(1, $rows[0]);
-    $rows = $database->select('project_browser_categories')->countQuery()->execute()->fetchCol();
+    $rows = $database->select('project_browser_categories')->countQuery()->execute()?->fetchCol();
+    $this->assertIsArray($rows);
     $this->assertGreaterThan(1, $rows[0]);
 
     $module_installer->uninstall(['project_browser_test']);