From 70906f5ed43c9fc12dc8dd5de574b596d4955b1b Mon Sep 17 00:00:00 2001
From: Brian Canini <canini.16@osu.edu>
Date: Mon, 15 Jun 2020 13:23:47 -0400
Subject: [PATCH] Updating drupal/google_analytics (2.4.0 => 2.5.0)

---
 composer.json                                 |   2 +-
 composer.lock                                 |  53 ++++---
 vendor/composer/installed.json                |  53 ++++---
 web/modules/google_analytics/README.md        | 134 ++++++++++++++++++
 web/modules/google_analytics/README.txt       |  96 -------------
 web/modules/google_analytics/composer.json    |  18 ++-
 .../install/google_analytics.settings.yml     |   2 +-
 .../google_analytics.info.yml                 |  14 +-
 .../google_analytics/google_analytics.install |  10 ++
 .../google_analytics/google_analytics.module  |  44 +++---
 .../Form/GoogleAnalyticsAdminSettingsForm.php |  44 ++++--
 .../Tests/GoogleAnalyticsPhpFilterTest.php    | 101 -------------
 .../src/Tests/GoogleAnalyticsSearchTest.php   |  95 -------------
 .../GoogleAnalyticsStatusMessagesTest.php     |  71 ----------
 .../google_analytics_test.info.yml            |   8 +-
 .../Functional}/GoogleAnalyticsBasicTest.php  |  99 +++++++------
 ...nalyticsCustomDimensionsAndMetricsTest.php |  49 ++++---
 .../Functional}/GoogleAnalyticsCustomUrls.php |  17 ++-
 .../GoogleAnalyticsJavaScriptTest.js          |   0
 .../Functional}/GoogleAnalyticsRolesTest.php  |  41 +++---
 .../Functional/GoogleAnalyticsSearchTest.php  | 114 +++++++++++++++
 .../GoogleAnalyticsStatusMessagesTest.php     |  76 ++++++++++
 .../GoogleAnalyticsUninstallTest.php          |  24 ++--
 .../GoogleAnalyticsUserFieldsTest.php         |  27 ++--
 24 files changed, 619 insertions(+), 573 deletions(-)
 create mode 100644 web/modules/google_analytics/README.md
 delete mode 100644 web/modules/google_analytics/README.txt
 delete mode 100644 web/modules/google_analytics/src/Tests/GoogleAnalyticsPhpFilterTest.php
 delete mode 100644 web/modules/google_analytics/src/Tests/GoogleAnalyticsSearchTest.php
 delete mode 100644 web/modules/google_analytics/src/Tests/GoogleAnalyticsStatusMessagesTest.php
 rename web/modules/google_analytics/{src/Tests => tests/src/Functional}/GoogleAnalyticsBasicTest.php (62%)
 rename web/modules/google_analytics/{src/Tests => tests/src/Functional}/GoogleAnalyticsCustomDimensionsAndMetricsTest.php (56%)
 rename web/modules/google_analytics/{src/Tests => tests/src/Functional}/GoogleAnalyticsCustomUrls.php (68%)
 rename web/modules/google_analytics/{src/Tests => tests/src/Functional}/GoogleAnalyticsJavaScriptTest.js (100%)
 rename web/modules/google_analytics/{src/Tests => tests/src/Functional}/GoogleAnalyticsRolesTest.php (52%)
 create mode 100644 web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsSearchTest.php
 create mode 100644 web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsStatusMessagesTest.php
 rename web/modules/google_analytics/{src/Tests => tests/src/Functional}/GoogleAnalyticsUninstallTest.php (59%)
 rename web/modules/google_analytics/{src/Tests => tests/src/Functional}/GoogleAnalyticsUserFieldsTest.php (64%)

diff --git a/composer.json b/composer.json
index fcdc5f8e2e..7c229706f7 100644
--- a/composer.json
+++ b/composer.json
@@ -125,7 +125,7 @@
         "drupal/file_browser": "1.1",
         "drupal/focal_point": "1.2",
         "drupal/geolocation": "1.10",
-        "drupal/google_analytics": "2.4",
+        "drupal/google_analytics": "2.5",
         "drupal/google_tag": "1.3",
         "drupal/honeypot": "1.30",
         "drupal/image_popup": "1.1",
diff --git a/composer.lock b/composer.lock
index 6a9667cf32..6034bbcd76 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": "f108b03d13affee27b523a0310a3f20f",
+    "content-hash": "6631bbb40605ad7caaf344c427a9e340",
     "packages": [
         {
             "name": "alchemy/zippy",
@@ -5103,51 +5103,66 @@
         },
         {
             "name": "drupal/google_analytics",
-            "version": "2.4.0",
+            "version": "2.5.0",
             "source": {
                 "type": "git",
                 "url": "https://git.drupalcode.org/project/google_analytics.git",
-                "reference": "8.x-2.4"
+                "reference": "8.x-2.5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://ftp.drupal.org/files/projects/google_analytics-8.x-2.4.zip",
-                "reference": "8.x-2.4",
-                "shasum": "f2e78ec140024ddcd19e027704ba73c33731f656"
+                "url": "https://ftp.drupal.org/files/projects/google_analytics-8.x-2.5.zip",
+                "reference": "8.x-2.5",
+                "shasum": "9e0ff72cc313bf9295fe8bd73a68f5f7688513ab"
             },
             "require": {
-                "drupal/core": "~8.5"
+                "drupal/core": "^8.8.6|^9.0"
             },
             "require-dev": {
-                "drupal/php": "*",
-                "drupal/token": "*"
+                "drupal/token": "^1.7"
             },
             "type": "drupal-module",
             "extra": {
-                "branch-alias": {
-                    "dev-2.x": "2.x-dev"
-                },
                 "drupal": {
-                    "version": "8.x-2.4",
-                    "datestamp": "1548968580",
+                    "version": "8.x-2.5",
+                    "datestamp": "1591298527",
                     "security-coverage": {
                         "status": "covered",
                         "message": "Covered by Drupal's security advisory policy"
                     }
+                },
+                "branch-alias": {
+                    "dev-8.x-2.x": "2.x-dev"
                 }
             },
             "notification-url": "https://packages.drupal.org/8/downloads",
             "license": [
-                "GPL-2.0+"
+                "GPL-2.0-or-later"
             ],
             "authors": [
                 {
-                    "name": "hass",
-                    "homepage": "https://www.drupal.org/u/hass"
+                    "name": "See contributors",
+                    "homepage": "https://www.drupal.org/node/49388/committers"
                 },
                 {
-                    "name": "See other contributors",
-                    "homepage": "https://www.drupal.org/node/49388/committers"
+                    "name": "budda",
+                    "homepage": "https://www.drupal.org/user/13164"
+                },
+                {
+                    "name": "ixismark",
+                    "homepage": "https://www.drupal.org/user/3632333"
+                },
+                {
+                    "name": "japerry",
+                    "homepage": "https://www.drupal.org/user/45640"
+                },
+                {
+                    "name": "pfaocle",
+                    "homepage": "https://www.drupal.org/user/9740"
+                },
+                {
+                    "name": "roberto.rivera.ixis",
+                    "homepage": "https://www.drupal.org/user/3632325"
                 }
             ],
             "description": "Allows your site to be tracked by Google Analytics by adding a Javascript tracking code to every page.",
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index bcbbfd79f6..72ba1d36d2 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -5255,53 +5255,68 @@
     },
     {
         "name": "drupal/google_analytics",
-        "version": "2.4.0",
-        "version_normalized": "2.4.0.0",
+        "version": "2.5.0",
+        "version_normalized": "2.5.0.0",
         "source": {
             "type": "git",
             "url": "https://git.drupalcode.org/project/google_analytics.git",
-            "reference": "8.x-2.4"
+            "reference": "8.x-2.5"
         },
         "dist": {
             "type": "zip",
-            "url": "https://ftp.drupal.org/files/projects/google_analytics-8.x-2.4.zip",
-            "reference": "8.x-2.4",
-            "shasum": "f2e78ec140024ddcd19e027704ba73c33731f656"
+            "url": "https://ftp.drupal.org/files/projects/google_analytics-8.x-2.5.zip",
+            "reference": "8.x-2.5",
+            "shasum": "9e0ff72cc313bf9295fe8bd73a68f5f7688513ab"
         },
         "require": {
-            "drupal/core": "~8.5"
+            "drupal/core": "^8.8.6|^9.0"
         },
         "require-dev": {
-            "drupal/php": "*",
-            "drupal/token": "*"
+            "drupal/token": "^1.7"
         },
         "type": "drupal-module",
         "extra": {
-            "branch-alias": {
-                "dev-2.x": "2.x-dev"
-            },
             "drupal": {
-                "version": "8.x-2.4",
-                "datestamp": "1548968580",
+                "version": "8.x-2.5",
+                "datestamp": "1591298527",
                 "security-coverage": {
                     "status": "covered",
                     "message": "Covered by Drupal's security advisory policy"
                 }
+            },
+            "branch-alias": {
+                "dev-8.x-2.x": "2.x-dev"
             }
         },
         "installation-source": "dist",
         "notification-url": "https://packages.drupal.org/8/downloads",
         "license": [
-            "GPL-2.0+"
+            "GPL-2.0-or-later"
         ],
         "authors": [
             {
-                "name": "hass",
-                "homepage": "https://www.drupal.org/u/hass"
+                "name": "See contributors",
+                "homepage": "https://www.drupal.org/node/49388/committers"
             },
             {
-                "name": "See other contributors",
-                "homepage": "https://www.drupal.org/node/49388/committers"
+                "name": "budda",
+                "homepage": "https://www.drupal.org/user/13164"
+            },
+            {
+                "name": "ixismark",
+                "homepage": "https://www.drupal.org/user/3632333"
+            },
+            {
+                "name": "japerry",
+                "homepage": "https://www.drupal.org/user/45640"
+            },
+            {
+                "name": "pfaocle",
+                "homepage": "https://www.drupal.org/user/9740"
+            },
+            {
+                "name": "roberto.rivera.ixis",
+                "homepage": "https://www.drupal.org/user/3632325"
             }
         ],
         "description": "Allows your site to be tracked by Google Analytics by adding a Javascript tracking code to every page.",
diff --git a/web/modules/google_analytics/README.md b/web/modules/google_analytics/README.md
new file mode 100644
index 0000000000..1042e58f8f
--- /dev/null
+++ b/web/modules/google_analytics/README.md
@@ -0,0 +1,134 @@
+## CONTENTS OF THIS FILE
+
+ * Introduction
+ * Requirements
+ * Installation
+ * Configuration
+ * Page specific tracking
+ * Custom Dimensions And Metrics
+ * Advanced setting
+ * Manual Js Debugging
+ * Usage
+ * Maintainers
+
+
+## INTRODUCTION
+
+The module provides
+
+ * For a full description of the module, visit the project page:
+   https://www.drupal.org/project/google_analytics
+
+ * To submit bug reports and feature suggestions, or to track changes:
+   https://www.drupal.org/project/issues/google_analytics
+
+
+## REQUIREMENTS
+
+This module requires no modules outside of Drupal core.
+
+
+## INSTALLATION
+
+ * Install the Google Analytics module as you would normally install a
+   contributed Drupal module. Visit https://www.drupal.org/node/1897420 for
+   further information.
+
+
+## CONFIGURATION
+
+    1. Navigate to Administration > Extend and enable the module.
+    2. Navigate to Administration > Configuration > System > Google Analytics
+       to configure tracking behavior.
+    3. Enter your Google Analytics account number.
+    4. All pages will now have the required JavaScript added to the HTML footer
+       can confirm this by viewing the page source from the browser.
+
+
+## PAGE SPECIFIC TRACKING
+
+The default is set to "Add to every page except the listed pages". By
+default the following pages are listed for exclusion:
+
+```
+/admin
+/admin/*
+/batch
+/node/add*
+/node/*/*
+/user/*/*
+```
+
+These defaults are changeable by the website administrator or any other
+user with 'Administer Google Analytics' permission.
+
+Like the blocks visibility settings in Drupal core, there is a choice for
+"Add if the following PHP code returns TRUE." Sample PHP snippets that can be
+used in this textarea can be found on the handbook page "Overview-approach to
+block visibility" at https://drupal.org/node/64135.
+
+
+## CUSTOM DIMENSIONS AND METRICS
+
+One example for custom dimensions tracking is the "User roles" tracking.
+
+    1. In the Google Analytics (https://marketingplatform.google.com/about/analytics/)
+       Management Interface you need to setup Dimension #1 with name
+       e.g. "User roles". This step is required. Do not miss it, please.
+
+    2. Enter the below configuration data into the Drupal custom dimensions
+       settings form under admin/config/system/googleanalytics. You can also
+       choose another index, but keep it always in sync with the index used in
+       step #1.
+
+   Index: 1
+   Value: [current-user:role-names]
+
+More details about custom dimensions and metrics can be found in the Google API
+documentation at https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets.
+
+
+## ADVANCED SETTINGS
+
+You can include additional JavaScript snippets in the custom javascript
+code textarea. These can be found on the official Google Analytics pages
+and a few examples at https://drupal.org/node/248699. Support is not
+provided for any customisations you include.
+
+To speed up page loading you may also cache the Google Analytics "analytics.js"
+file locally.
+
+
+## MANUAL JS DEBBUGING
+
+For manual debugging of the JS code you are able to create a test node. This
+is the example HTML code for this test node. You need to enable debugging mode
+in your Drupal configuration of Google Analytics settings to see verbose
+messages in your browsers JS console.
+
+Title: Google Analytics test page
+Body:
+```
+<ul>
+  <li><a href="mailto:foo@example.com">Mailto</a></li>
+  <li><a href="/files/test.txt">Download file</a></li>
+  <li><a class="colorbox" href="#">Open colorbox</a></li>
+  <li><a href="https://example.com/">External link</a></li>
+  <li><a href="/go/test">Go link</a></li>
+</ul>
+```
+
+Text format: Full HTML
+
+
+## USAGE
+
+In the settings page enter your Google Analytics account number.
+
+All pages will now have the required JavaScript added to the HTML footer can
+confirm this by viewing the page source from our browser.
+
+
+## MAINTAINERS
+
+ * Alexander Hass (hass) - https://www.drupal.org/user/85918
diff --git a/web/modules/google_analytics/README.txt b/web/modules/google_analytics/README.txt
deleted file mode 100644
index 4d8765ef67..0000000000
--- a/web/modules/google_analytics/README.txt
+++ /dev/null
@@ -1,96 +0,0 @@
-
-Module: Google Analytics
-Author: Alexander Hass <https://drupal.org/user/85918>
-
-
-Description
-===========
-Adds the Google Analytics tracking system to your website.
-
-Requirements
-============
-
-* Google Analytics user account
-
-
-Installation
-============
-Copy the 'google_analytics' module directory in to your Drupal 'modules'
-directory as usual.
-
-
-Usage
-=====
-In the settings page enter your Google Analytics account number.
-
-All pages will now have the required JavaScript added to the
-HTML footer can confirm this by viewing the page source from
-your browser.
-
-Page specific tracking
-====================================================
-The default is set to "Add to every page except the listed pages". By
-default the following pages are listed for exclusion:
-
-/admin
-/admin/*
-/batch
-/node/add*
-/node/*/*
-/user/*/*
-
-These defaults are changeable by the website administrator or any other
-user with 'Administer Google Analytics' permission.
-
-Like the blocks visibility settings in Drupal core, there is a choice for
-"Add if the following PHP code returns TRUE." Sample PHP snippets that can be
-used in this textarea can be found on the handbook page "Overview-approach to
-block visibility" at https://drupal.org/node/64135.
-
-Custom dimensions and metrics
-=============================
-One example for custom dimensions tracking is the "User roles" tracking.
-
-1. In the Google Analytics (https://marketingplatform.google.com/about/analytics/)
-   Management Interface you need to setup Dimension #1 with name 
-   e.g. "User roles". This step is required. Do not miss it, please.
-
-2. Enter the below configuration data into the Drupal custom dimensions settings
-   form under admin/config/system/googleanalytics. You can also choose another
-   index, but keep it always in sync with the index used in step #1.
-
-   Index: 1
-   Value: [current-user:role-names]
-
-More details about custom dimensions and metrics can be found in the Google API
-documentation at https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets.
-
-Advanced Settings
-=================
-You can include additional JavaScript snippets in the custom javascript
-code textarea. These can be found on the official Google Analytics pages
-and a few examples at https://drupal.org/node/248699. Support is not
-provided for any customisations you include.
-
-To speed up page loading you may also cache the Google Analytics "analytics.js"
-file locally.
-
-Manual JS debugging
-===================
-For manual debugging of the JS code you are able to create a test node. This
-is the example HTML code for this test node. You need to enable debugging mode
-in your Drupal configuration of Google Analytics settings to see verbose
-messages in your browsers JS console.
-
-Title: Google Analytics test page
-
-Body:
-<ul>
-  <li><a href="mailto:foo@example.com">Mailto</a></li>
-  <li><a href="/files/test.txt">Download file</a></li>
-  <li><a class="colorbox" href="#">Open colorbox</a></li>
-  <li><a href="https://example.com/">External link</a></li>
-  <li><a href="/go/test">Go link</a></li>
-</ul>
-
-Text format: Full HTML
diff --git a/web/modules/google_analytics/composer.json b/web/modules/google_analytics/composer.json
index 2204e9a4be..9896261191 100644
--- a/web/modules/google_analytics/composer.json
+++ b/web/modules/google_analytics/composer.json
@@ -5,11 +5,7 @@
   "homepage": "https://www.drupal.org/project/google_analytics",
   "authors": [
     {
-      "name": "hass",
-      "homepage": "https://www.drupal.org/u/hass"
-    },
-    {
-      "name": "See other contributors",
+      "name": "See contributors",
       "homepage":"https://www.drupal.org/node/49388/committers"
     }
   ],
@@ -17,8 +13,16 @@
     "issues": "https://www.drupal.org/project/issues/google_analytics",
     "source": "https://git.drupal.org/project/google_analytics.git"
   },
-  "license": "GPL-2.0+",
+  "license": "GPL-2.0-or-later",
   "require": {
-    "drupal/core": "~8.5"  
+    "drupal/core": "^8.8.6|^9.0"
+  },
+  "require-dev": {
+    "drupal/token": "^1.7"
+  },
+  "extra": {
+    "branch-alias": {
+      "dev-8.x-2.x": "2.x-dev"
+    }
   }
 }
diff --git a/web/modules/google_analytics/config/install/google_analytics.settings.yml b/web/modules/google_analytics/config/install/google_analytics.settings.yml
index 615cb36032..fc9cfdffca 100644
--- a/web/modules/google_analytics/config/install/google_analytics.settings.yml
+++ b/web/modules/google_analytics/config/install/google_analytics.settings.yml
@@ -7,7 +7,7 @@ visibility:
   request_path_pages: "/admin\n/admin/*\n/batch\n/node/add*\n/node/*/*\n/user/*/*"
   user_role_mode: 0
   user_role_roles: {  }
-  user_account_mode: 0
+  user_account_mode: 1
 track:
   outbound: true
   mailto: true
diff --git a/web/modules/google_analytics/google_analytics.info.yml b/web/modules/google_analytics/google_analytics.info.yml
index cd1d387ef1..60bae23d9a 100644
--- a/web/modules/google_analytics/google_analytics.info.yml
+++ b/web/modules/google_analytics/google_analytics.info.yml
@@ -2,16 +2,10 @@ name: 'Google Analytics'
 type: module
 description: 'Allows your site to be tracked by Google Analytics by adding a Javascript tracking code to every page.'
 package: Statistics
-# core: 8.x
+core_version_requirement: ^8.8.6 || ^9
 configure: google_analytics.admin_settings_form
-dependencies:
-  - drupal:system (>= 8.5)
-test_dependencies:
-  - php:php
-  - token:token
 
-# Information added by Drupal.org packaging script on 2019-01-31
-version: '8.x-2.4'
-core: '8.x'
+# Information added by Drupal.org packaging script on 2020-06-04
+version: '8.x-2.5'
 project: 'google_analytics'
-datestamp: 1548968592
+datestamp: 1591298498
diff --git a/web/modules/google_analytics/google_analytics.install b/web/modules/google_analytics/google_analytics.install
index f616f8f9ee..13a558ac08 100644
--- a/web/modules/google_analytics/google_analytics.install
+++ b/web/modules/google_analytics/google_analytics.install
@@ -58,6 +58,16 @@ function google_analytics_requirements($phase) {
         'value' => t('Debugging enabled'),
       ];
     }
+
+    // Raise warning if php code is being used.
+    if ($config->get('visibility.request_path_mode') && $config->get('visibility.request_path_mode') === '2') {
+      $requirements['google_analytics_php'] = [
+        'title' => t('Google Analytics module'),
+        'description' => t('Using PHP code in Google Analytics is deprecated and not available in Drupal 9. You must move your logic into a custom module, and change the <a href=":url">Page Visibility settings</a> to suppress this message.', [':url' => Url::fromRoute('google_analytics.admin_settings_form')->toString()]),
+        'severity' => REQUIREMENT_ERROR,
+        'value' => t('PHP code exists'),
+      ];
+    }
   }
 
   return $requirements;
diff --git a/web/modules/google_analytics/google_analytics.module b/web/modules/google_analytics/google_analytics.module
index 3996b242d8..df3be4bddf 100644
--- a/web/modules/google_analytics/google_analytics.module
+++ b/web/modules/google_analytics/google_analytics.module
@@ -12,8 +12,8 @@
 
 use Drupal\Component\Serialization\Json;
 use Drupal\Component\Utility\Crypt;
-use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\File\FileSystemInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Site\Settings;
@@ -119,8 +119,10 @@ function google_analytics_page_attachments(array &$page) {
       // Add debugging code.
       if ($debug) {
         $page['#attached']['library'][] = 'google_analytics/google_analytics.debug';
+        // phpcs:disable
         // Add the JS test in development to the page.
         // $page['#attached']['library'][] = 'google_analytics/google_analytics.test';
+        // phpcs:enable
       }
       else {
         $page['#attached']['library'][] = 'google_analytics/google_analytics';
@@ -209,7 +211,7 @@ function google_analytics_page_attachments(array &$page) {
           $google_analytics_custom_var['value'] = \Drupal::token()->replace($google_analytics_custom_var['value'], $types, ['clear' => TRUE]);
 
           // Suppress empty values.
-          if (!Unicode::strlen(trim($google_analytics_custom_var['value']))) {
+          if (!mb_strlen(trim($google_analytics_custom_var['value']))) {
             continue;
           }
 
@@ -217,7 +219,7 @@ function google_analytics_page_attachments(array &$page) {
           // A metric has no length limitation. It's not documented if this
           // limit means 150 bytes after url encoding or before.
           // See https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#customs
-          if ($google_analytics_custom_type == 'dimension' && Unicode::strlen($google_analytics_custom_var['value']) > 150) {
+          if ($google_analytics_custom_type == 'dimension' && mb_strlen($google_analytics_custom_var['value']) > 150) {
             $google_analytics_custom_var['value'] = substr($google_analytics_custom_var['value'], 0, 150);
           }
 
@@ -457,15 +459,17 @@ function google_analytics_preprocess_item_list__search_results(&$variables) {
 
   // Only run on search results list.
   if ($config->get('track.site_search')) {
-    // There is no search result $variable available that hold the number of
-    // items found. The variable $variables['items'] has the current page items
-    // only. But the pager item mumber can tell the number of search results.
-    global $pager_total_items;
-
+    // Get the pager manager to give us the number of items returned.
+    /** @var \Drupal\Core\Pager\PagerManagerInterface $pager_manager */
+    $pager_manager = \Drupal::service('pager.manager');
+    $items = 0;
+    if ($pager_manager->getPager()) {
+      $items = $pager_manager->getPager()->getTotalItems();
+    }
     $variables['#attached']['html_head'][] = [
       [
         '#tag' => 'script',
-        '#value' => 'window.google_analytics_search_results = ' . intval($pager_total_items[0]) . ';',
+        '#value' => 'window.google_analytics_search_results = ' . $items . ';',
         '#weight' => JS_LIBRARY - 1,
       ],
       'google_analytics_search_script',
@@ -487,6 +491,7 @@ function google_analytics_preprocess_item_list__search_results(&$variables) {
 function _google_analytics_cache($location, $synchronize = FALSE) {
   $path = 'public://google_analytics';
   $file_destination = $path . '/' . basename($location);
+  $filesystem = \Drupal::service('file_system');
 
   if (!file_exists($file_destination) || $synchronize) {
     // Download the latest tracking code.
@@ -500,12 +505,12 @@ function _google_analytics_cache($location, $synchronize = FALSE) {
         $data_hash_local = Crypt::hashBase64(file_get_contents($file_destination));
         $data_hash_remote = Crypt::hashBase64($data);
         // Check that the files directory is writable.
-        if ($data_hash_local != $data_hash_remote && file_prepare_directory($path)) {
+        if ($data_hash_local != $data_hash_remote &&  $filesystem->prepareDirectory($path)) {
           // Save updated tracking code file to disk.
-          file_unmanaged_save_data($data, $file_destination, FILE_EXISTS_REPLACE);
+          $filesystem->saveData($data, $file_destination, FileSystemInterface::EXISTS_REPLACE);
           // Based on Drupal Core class AssetDumper.
           if (extension_loaded('zlib') && \Drupal::config('system.performance')->get('js.gzip')) {
-            file_unmanaged_save_data(gzencode($data, 9, FORCE_GZIP), $file_destination . '.gz', FILE_EXISTS_REPLACE);
+            $filesystem->saveData(gzencode($data, 9, FORCE_GZIP), $file_destination . '.gz', FileSystemInterface::EXISTS_REPLACE);
           }
           \Drupal::logger('google_analytics')->info('Locally cached tracking code file has been updated.');
 
@@ -516,13 +521,13 @@ function _google_analytics_cache($location, $synchronize = FALSE) {
       }
       else {
         // Check that the files directory is writable.
-        if (file_prepare_directory($path, FILE_CREATE_DIRECTORY)) {
+        if ($filesystem->prepareDirectory($path, FileSystemInterface::CREATE_DIRECTORY)) {
           // There is no need to flush JS here as core refreshes JS caches
           // automatically, if new files are added.
-          file_unmanaged_save_data($data, $file_destination, FILE_EXISTS_REPLACE);
+          $filesystem->saveData($data, $file_destination, FileSystemInterface::EXISTS_REPLACE);
           // Based on Drupal Core class AssetDumper.
           if (extension_loaded('zlib') && \Drupal::config('system.performance')->get('js.gzip')) {
-            file_unmanaged_save_data(gzencode($data, 9, FORCE_GZIP), $file_destination . '.gz', FILE_EXISTS_REPLACE);
+            $filesystem->saveData(gzencode($data, 9, FORCE_GZIP), $file_destination . '.gz', FileSystemInterface::EXISTS_REPLACE);
           }
           \Drupal::logger('google_analytics')->info('Locally cached tracking code file has been saved.');
 
@@ -546,9 +551,8 @@ function _google_analytics_cache($location, $synchronize = FALSE) {
  */
 function google_analytics_clear_js_cache() {
   $path = 'public://google_analytics';
-  if (file_prepare_directory($path)) {
-    file_scan_directory($path, '/.*/', ['callback' => 'file_unmanaged_delete']);
-    \Drupal::service('file_system')->rmdir($path);
+  if (is_dir($path)) {
+    \Drupal::service('file_system')->deleteRecursive($path);
 
     // Change query-strings on css/js files to enforce reload for all users.
     _drupal_flush_css_js();
@@ -649,11 +653,11 @@ function _google_analytics_visibility_pages() {
     if (!empty($visibility_request_path_pages)) {
       // Convert path to lowercase. This allows comparison of the same path
       // with different case. Ex: /Page, /page, /PAGE.
-      $pages = Unicode::strtolower($visibility_request_path_pages);
+      $pages = mb_strtolower($visibility_request_path_pages);
       if ($visibility_request_path_mode < 2) {
         // Compare the lowercase path alias (if any) and internal path.
         $path = \Drupal::service('path.current')->getPath();
-        $path_alias = Unicode::strtolower(\Drupal::service('path.alias_manager')->getAliasByPath($path));
+        $path_alias = mb_strtolower(\Drupal::service('path_alias.manager')->getAliasByPath($path));
         $page_match = \Drupal::service('path.matcher')->matchPath($path_alias, $pages) || (($path != $path_alias) && \Drupal::service('path.matcher')->matchPath($path, $pages));
         // When $visibility_request_path_mode has a value of 0, the tracking
         // code is displayed on all pages except those listed in $pages. When
diff --git a/web/modules/google_analytics/src/Form/GoogleAnalyticsAdminSettingsForm.php b/web/modules/google_analytics/src/Form/GoogleAnalyticsAdminSettingsForm.php
index 639184b4de..a892b3b0ec 100644
--- a/web/modules/google_analytics/src/Form/GoogleAnalyticsAdminSettingsForm.php
+++ b/web/modules/google_analytics/src/Form/GoogleAnalyticsAdminSettingsForm.php
@@ -2,9 +2,8 @@
 
 namespace Drupal\google_analytics\Form;
 
-use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Extension\ModuleHandler;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\ConfigFormBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
@@ -17,14 +16,31 @@
  */
 class GoogleAnalyticsAdminSettingsForm extends ConfigFormBase {
 
+  /**
+   * The manages modules.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
   protected $moduleHandler;
 
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
   protected $currentUser;
 
   /**
-   * {@inheritdoc}
+   * The constructor method.
+   *
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The config factory.
+   * @param \Drupal\Core\Session\AccountInterface $currentUser
+   *   The current user.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
+   *   The manages modules.
    */
-  public function __construct(ConfigFactoryInterface $config_factory, AccountInterface $currentUser, ModuleHandler $moduleHandler) {
+  public function __construct(ConfigFactoryInterface $config_factory, AccountInterface $currentUser, ModuleHandlerInterface $moduleHandler) {
     parent::__construct($config_factory);
     $this->currentUser = $currentUser;
     $this->moduleHandler = $moduleHandler;
@@ -174,7 +190,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       $description = $this->t("Specify pages by using their paths. Enter one path per line. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", ['%blog' => '/blog', '%blog-wildcard' => '/blog/*', '%front' => '<front>']);
 
       if ($this->moduleHandler->moduleExists('php') && $php_access) {
-        $options[] = $this->t('Pages on which this PHP code returns <code>TRUE</code> (experts only)');
+        $options[] = $this->t('Pages on which this PHP code returns <code>TRUE</code> (not supported in Drupal 9, experts only)');
         $title = $this->t('Pages or PHP code');
         $description .= ' ' . $this->t('If the PHP option is chosen, enter PHP code between %php. Note that executing incorrect PHP code can break your Drupal site.', ['%php' => '<?php ?>']);
       }
@@ -236,9 +252,9 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#type' => 'radios',
       '#title' => $this->t('Allow users to customize tracking on their account page'),
       '#options' => [
-        $this->t('No customization allowed'),
-        $this->t('Tracking on by default, users with %permission permission can opt out', $t_permission),
-        $this->t('Tracking off by default, users with %permission permission can opt in', $t_permission),
+        0 => $this->t('No customization allowed'),
+        1 => $this->t('Tracking on by default, users with %permission permission can opt out', $t_permission),
+        2 => $this->t('Tracking off by default, users with %permission permission can opt in', $t_permission),
       ],
       '#default_value' => !empty($visibility_user_account_mode) ? $visibility_user_account_mode : 0,
     ];
@@ -565,7 +581,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
     foreach ($form_state->getValue(['google_analytics_custom_dimension', 'indexes']) as $dimension) {
       $form_state->setValue(['google_analytics_custom_dimension', 'indexes', $dimension['index'], 'value'], trim($dimension['value']));
       // Remove empty values from the array.
-      if (!Unicode::strlen($form_state->getValue(['google_analytics_custom_dimension', 'indexes', $dimension['index'], 'value']))) {
+      if (!mb_strlen($form_state->getValue(['google_analytics_custom_dimension', 'indexes', $dimension['index'], 'value']))) {
         $form_state->unsetValue(['google_analytics_custom_dimension', 'indexes', $dimension['index']]);
       }
     }
@@ -574,7 +590,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
     foreach ($form_state->getValue(['google_analytics_custom_metric', 'indexes']) as $metric) {
       $form_state->setValue(['google_analytics_custom_metric', 'indexes', $metric['index'], 'value'], trim($metric['value']));
       // Remove empty values from the array.
-      if (!Unicode::strlen($form_state->getValue(['google_analytics_custom_metric', 'indexes', $metric['index'], 'value']))) {
+      if (!mb_strlen($form_state->getValue(['google_analytics_custom_metric', 'indexes', $metric['index'], 'value']))) {
         $form_state->unsetValue(['google_analytics_custom_metric', 'indexes', $metric['index']]);
       }
     }
@@ -703,7 +719,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
   public static function tokenElementValidate(&$element, FormStateInterface $form_state) {
     $value = isset($element['#value']) ? $element['#value'] : $element['#default_value'];
 
-    if (!Unicode::strlen($value)) {
+    if (!mb_strlen($value)) {
       // Empty value needs no further validation since the element should depend
       // on using the '#required' FAPI property.
       return $element;
@@ -924,10 +940,10 @@ protected static function validateCreateFieldName($name) {
    *   The error message if the specified value is invalid, NULL otherwise.
    */
   protected static function validateCreateFieldValue($value) {
-    if (!is_bool($value) && !Unicode::strlen($value)) {
+    if (!is_bool($value) && !mb_strlen($value)) {
       return t('A create only field requires a value.');
     }
-    if (Unicode::strlen($value) > 255) {
+    if (mb_strlen($value) > 255) {
       return t('The value of a create only field must be a string at most 255 characters long.');
     }
   }
@@ -972,7 +988,7 @@ protected static function convertFormValueDataTypes(array $values) {
 
     foreach ($values as $name => $value) {
       // Convert data types.
-      $match = Unicode::strtolower($value);
+      $match = mb_strtolower($value);
       if ($match == 'true') {
         $value = TRUE;
       }
diff --git a/web/modules/google_analytics/src/Tests/GoogleAnalyticsPhpFilterTest.php b/web/modules/google_analytics/src/Tests/GoogleAnalyticsPhpFilterTest.php
deleted file mode 100644
index df4af7617e..0000000000
--- a/web/modules/google_analytics/src/Tests/GoogleAnalyticsPhpFilterTest.php
+++ /dev/null
@@ -1,101 +0,0 @@
-<?php
-
-namespace Drupal\google_analytics\Tests;
-
-use Drupal\Component\Utility\Html;
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Test php filter functionality of Google Analytics module.
- *
- * @group Google Analytics
- *
- * @dependencies php
- */
-class GoogleAnalyticsPhpFilterTest extends WebTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = ['google_analytics', 'php'];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    // Administrator with all permissions.
-    $permissions_admin_user = [
-      'access administration pages',
-      'administer google analytics',
-      'use PHP for google analytics tracking visibility',
-    ];
-    $this->admin_user = $this->drupalCreateUser($permissions_admin_user);
-
-    // Administrator who cannot configure tracking visibility with PHP.
-    $permissions_delegated_admin_user = [
-      'access administration pages',
-      'administer google analytics',
-    ];
-    $this->delegated_admin_user = $this->drupalCreateUser($permissions_delegated_admin_user);
-  }
-
-  /**
-   * Tests if PHP module integration works.
-   */
-  public function testGoogleAnalyticsPhpFilter() {
-    $ua_code = 'UA-123456-1';
-    $this->drupalLogin($this->admin_user);
-
-    $edit = [];
-    $edit['google_analytics_account'] = $ua_code;
-    $edit['google_analytics_visibility_request_path_mode'] = 2;
-    $edit['google_analytics_visibility_request_path_pages'] = '<?php return 0; ?>';
-    $this->drupalPostForm('admin/config/system/google-analytics', $edit, t('Save configuration'));
-
-    // Compare saved setting with posted setting.
-    $google_analytics_pages = \Drupal::config('google_analytics.settings')->get('visibility.request_path_pages');
-    $this->assertEqual('<?php return 0; ?>', $google_analytics_pages, '[testGoogleAnalyticsPhpFilter]: PHP code snippet is intact.');
-
-    // Check tracking code visibility.
-    $this->config('google_analytics.settings')->set('visibility.request_path_pages', '<?php return TRUE; ?>')->save();
-    $this->drupalGet('');
-    $this->assertRaw('https://www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPhpFilter]: Tracking is displayed on frontpage page.');
-    $this->drupalGet('admin');
-    $this->assertRaw('https://www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPhpFilter]: Tracking is displayed on admin page.');
-
-    $this->config('google_analytics.settings')->set('visibility.request_path_pages', '<?php return FALSE; ?>')->save();
-    $this->drupalGet('');
-    $this->assertNoRaw('https://www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPhpFilter]: Tracking is not displayed on frontpage page.');
-
-    // Test administration form.
-    $this->config('google_analytics.settings')->set('visibility.request_path_pages', '<?php return TRUE; ?>')->save();
-    $this->drupalGet('admin/config/system/google-analytics');
-    $this->assertRaw(t('Pages on which this PHP code returns <code>TRUE</code> (experts only)'), '[testGoogleAnalyticsPhpFilter]: Permission to administer PHP for tracking visibility.');
-    $this->assertRaw(Html::escape('<?php return TRUE; ?>'), '[testGoogleAnalyticsPhpFilter]: PHP code snippted is displayed.');
-
-    // Login the delegated user and check if fields are visible.
-    $this->drupalLogin($this->delegated_admin_user);
-    $this->drupalGet('admin/config/system/google-analytics');
-    $this->assertNoRaw(t('Pages on which this PHP code returns <code>TRUE</code> (experts only)'), '[testGoogleAnalyticsPhpFilter]: No permission to administer PHP for tracking visibility.');
-    $this->assertNoRaw(Html::escape('<?php return TRUE; ?>'), '[testGoogleAnalyticsPhpFilter]: No permission to view PHP code snippted.');
-
-    // Set a different value and verify that this is still the same after the
-    // post.
-    $this->config('google_analytics.settings')->set('visibility.request_path_pages', '<?php return 0; ?>')->save();
-
-    $edit = [];
-    $edit['google_analytics_account'] = $ua_code;
-    $this->drupalPostForm('admin/config/system/google-analytics', $edit, t('Save configuration'));
-
-    // Compare saved setting with posted setting.
-    $google_analytics_visibility_pages = \Drupal::config('google_analytics.settings')->get('visibility.request_path_mode');
-    $google_analytics_pages = \Drupal::config('google_analytics.settings')->get('visibility.request_path_pages');
-    $this->assertEqual(2, $google_analytics_visibility_pages, '[testGoogleAnalyticsPhpFilter]: Pages on which this PHP code returns TRUE is selected.');
-    $this->assertEqual('<?php return 0; ?>', $google_analytics_pages, '[testGoogleAnalyticsPhpFilter]: PHP code snippet is intact.');
-  }
-
-}
diff --git a/web/modules/google_analytics/src/Tests/GoogleAnalyticsSearchTest.php b/web/modules/google_analytics/src/Tests/GoogleAnalyticsSearchTest.php
deleted file mode 100644
index 898ecd0e3b..0000000000
--- a/web/modules/google_analytics/src/Tests/GoogleAnalyticsSearchTest.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-
-namespace Drupal\google_analytics\Tests;
-
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Test search functionality of Google Analytics module.
- *
- * @group Google Analytics
- */
-class GoogleAnalyticsSearchTest extends WebTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = ['google_analytics', 'search', 'node'];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
-
-    $permissions = [
-      'access administration pages',
-      'administer google analytics',
-      'search content',
-      'create page content',
-      'edit own page content',
-    ];
-
-    // User to set up google_analytics.
-    $this->admin_user = $this->drupalCreateUser($permissions);
-    $this->drupalLogin($this->admin_user);
-  }
-
-  /**
-   * Tests if search tracking is properly added to the page.
-   */
-  public function testGoogleAnalyticsSearchTracking() {
-    $ua_code = 'UA-123456-1';
-    $this->config('google_analytics.settings')->set('account', $ua_code)->save();
-
-    // Check tracking code visibility.
-    $this->drupalGet('');
-    $this->assertRaw($ua_code, '[testGoogleAnalyticsSearch]: Tracking code is displayed for authenticated users.');
-
-    $this->drupalGet('search/node');
-    $this->assertNoRaw('ga("set", "page",', '[testGoogleAnalyticsSearch]: Custom url not set.');
-
-    // Enable site search support.
-    $this->config('google_analytics.settings')->set('track.site_search', 1)->save();
-
-    // Search for random string.
-    $search = [];
-    $search['keys'] = $this->randomMachineName(8);
-
-    // Create a node to search for.
-    $edit = [];
-    $edit['title[0][value]'] = 'This is a test title';
-    $edit['body[0][value]'] = 'This test content contains ' . $search['keys'] . ' string.';
-
-    // Fire a search, it's expected to get 0 results.
-    $this->drupalPostForm('search/node', $search, t('Search'));
-    $this->assertRaw('ga("set", "page", (window.google_analytics_search_results) ?', '[testGoogleAnalyticsSearch]: Search results tracker is displayed.');
-    $this->assertRaw('window.google_analytics_search_results = 0;', '[testGoogleAnalyticsSearch]: Search yielded no results.');
-
-    // Save the node.
-    $this->drupalPostForm('node/add/page', $edit, t('Save'));
-    $this->assertText(t('@type @title has been created.', ['@type' => 'Basic page', '@title' => $edit['title[0][value]']]), 'Basic page created.');
-
-    // Index the node or it cannot found.
-    $this->cronRun();
-
-    $this->drupalPostForm('search/node', $search, t('Search'));
-    $this->assertRaw('ga("set", "page", (window.google_analytics_search_results) ?', '[testGoogleAnalyticsSearch]: Search results tracker is displayed.');
-    $this->assertRaw('window.google_analytics_search_results = 1;', '[testGoogleAnalyticsSearch]: One search result found.');
-
-    $this->drupalPostForm('node/add/page', $edit, t('Save'));
-    $this->assertText(t('@type @title has been created.', ['@type' => 'Basic page', '@title' => $edit['title[0][value]']]), 'Basic page created.');
-
-    // Index the node or it cannot found.
-    $this->cronRun();
-
-    $this->drupalPostForm('search/node', $search, t('Search'));
-    $this->assertRaw('ga("set", "page", (window.google_analytics_search_results) ?', '[testGoogleAnalyticsSearch]: Search results tracker is displayed.');
-    $this->assertRaw('window.google_analytics_search_results = 2;', '[testGoogleAnalyticsSearch]: Two search results found.');
-  }
-
-}
diff --git a/web/modules/google_analytics/src/Tests/GoogleAnalyticsStatusMessagesTest.php b/web/modules/google_analytics/src/Tests/GoogleAnalyticsStatusMessagesTest.php
deleted file mode 100644
index 2e0488a4c5..0000000000
--- a/web/modules/google_analytics/src/Tests/GoogleAnalyticsStatusMessagesTest.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-namespace Drupal\google_analytics\Tests;
-
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Test status messages functionality of Google Analytics module.
- *
- * @group Google Analytics
- */
-class GoogleAnalyticsStatusMessagesTest extends WebTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = ['google_analytics', 'google_analytics_test'];
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $permissions = [
-      'access administration pages',
-      'administer google analytics',
-    ];
-
-    // User to set up google_analytics.
-    $this->admin_user = $this->drupalCreateUser($permissions);
-  }
-
-  /**
-   * Tests if status messages tracking is properly added to the page.
-   */
-  public function testGoogleAnalyticsStatusMessages() {
-    $ua_code = 'UA-123456-4';
-    $this->config('google_analytics.settings')->set('account', $ua_code)->save();
-
-    // Enable logging of errors only.
-    $this->config('google_analytics.settings')->set('track.messages', ['error' => 'error'])->save();
-
-    $this->drupalPostForm('user/login', [], t('Log in'));
-    $this->assertRaw('ga("send", "event", "Messages", "Error message", "Username field is required.");', '[testGoogleAnalyticsStatusMessages]: Event message "Username field is required." is shown.');
-    $this->assertRaw('ga("send", "event", "Messages", "Error message", "Password field is required.");', '[testGoogleAnalyticsStatusMessages]: Event message "Password field is required." is shown.');
-
-    // Testing this drupal_set_message() requires an extra test module.
-    $this->drupalGet('google-analytics-test/drupal-messenger-add-message');
-    $this->assertNoRaw('ga("send", "event", "Messages", "Status message", "Example status message.");', '[testGoogleAnalyticsStatusMessages]: Example status message is not enabled for tracking.');
-    $this->assertNoRaw('ga("send", "event", "Messages", "Warning message", "Example warning message.");', '[testGoogleAnalyticsStatusMessages]: Example warning message is not enabled for tracking.');
-    $this->assertRaw('ga("send", "event", "Messages", "Error message", "Example error message.");', '[testGoogleAnalyticsStatusMessages]: Example error message is shown.');
-    $this->assertRaw('ga("send", "event", "Messages", "Error message", "Example error message with html tags and link.");', '[testGoogleAnalyticsStatusMessages]: HTML has been stripped successful from Example error message with html tags and link.');
-
-    // Enable logging of status, warnings and errors.
-    $this->config('google_analytics.settings')->set('track.messages', [
-      'status' => 'status',
-      'warning' => 'warning',
-      'error' => 'error',
-    ])->save();
-
-    $this->drupalGet('google-analytics-test/drupal-messenger-add-message');
-    $this->assertRaw('ga("send", "event", "Messages", "Status message", "Example status message.");', '[testGoogleAnalyticsStatusMessages]: Example status message is enabled for tracking.');
-    $this->assertRaw('ga("send", "event", "Messages", "Warning message", "Example warning message.");', '[testGoogleAnalyticsStatusMessages]: Example warning message is enabled for tracking.');
-    $this->assertRaw('ga("send", "event", "Messages", "Error message", "Example error message.");', '[testGoogleAnalyticsStatusMessages]: Example error message is shown.');
-    $this->assertRaw('ga("send", "event", "Messages", "Error message", "Example error message with html tags and link.");', '[testGoogleAnalyticsStatusMessages]: HTML has been stripped successful from Example error message with html tags and link.');
-  }
-
-}
diff --git a/web/modules/google_analytics/tests/modules/google_analytics_test/google_analytics_test.info.yml b/web/modules/google_analytics/tests/modules/google_analytics_test/google_analytics_test.info.yml
index 533669e45b..eb378b90c7 100644
--- a/web/modules/google_analytics/tests/modules/google_analytics_test/google_analytics_test.info.yml
+++ b/web/modules/google_analytics/tests/modules/google_analytics_test/google_analytics_test.info.yml
@@ -2,10 +2,8 @@ name: 'Google Analytics test'
 type: module
 description: 'Support module for Google Analytics testing.'
 package: Testing
-# core: 8.x
 
-# Information added by Drupal.org packaging script on 2019-01-31
-version: '8.x-2.4'
-core: '8.x'
+# Information added by Drupal.org packaging script on 2020-06-04
+version: '8.x-2.5'
 project: 'google_analytics'
-datestamp: 1548968592
+datestamp: 1591298498
diff --git a/web/modules/google_analytics/src/Tests/GoogleAnalyticsBasicTest.php b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsBasicTest.php
similarity index 62%
rename from web/modules/google_analytics/src/Tests/GoogleAnalyticsBasicTest.php
rename to web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsBasicTest.php
index 04926f183d..1054a8b89d 100644
--- a/web/modules/google_analytics/src/Tests/GoogleAnalyticsBasicTest.php
+++ b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsBasicTest.php
@@ -1,17 +1,17 @@
 <?php
 
-namespace Drupal\google_analytics\Tests;
+namespace Drupal\Tests\google_analytics\Functional;
 
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Url;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Test basic functionality of Google Analytics module.
  *
  * @group Google Analytics
  */
-class GoogleAnalyticsBasicTest extends WebTestBase {
+class GoogleAnalyticsBasicTest extends BrowserTestBase {
 
   /**
    * User without permissions to use snippets.
@@ -31,6 +31,11 @@ class GoogleAnalyticsBasicTest extends WebTestBase {
     'help',
   ];
 
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
   /**
    * {@inheritdoc}
    */
@@ -61,22 +66,22 @@ public function testGoogleAnalyticsConfiguration() {
     // Check if Configure link is available on 'Extend' page.
     // Requires 'administer modules' permission.
     $this->drupalGet('admin/modules');
-    $this->assertRaw('admin/config/system/google-analytics', '[testGoogleAnalyticsConfiguration]: Configure link from Extend page to Google Analytics Settings page exists.');
+    $this->assertSession()->responseContains('admin/config/system/google-analytics');
 
     // Check if Configure link is available on 'Status Reports' page.
     // NOTE: Link is only shown without UA code configured.
     // Requires 'administer site configuration' permission.
     $this->drupalGet('admin/reports/status');
-    $this->assertRaw('admin/config/system/google-analytics', '[testGoogleAnalyticsConfiguration]: Configure link from Status Reports page to Google Analytics Settings page exists.');
+    $this->assertSession()->responseContains('admin/config/system/google-analytics');
 
     // Check for setting page's presence.
     $this->drupalGet('admin/config/system/google-analytics');
-    $this->assertRaw(t('Web Property ID'), '[testGoogleAnalyticsConfiguration]: Settings page displayed.');
+    $this->assertSession()->responseContains(t('Web Property ID'));
 
     // Check for account code validation.
     $edit['google_analytics_account'] = $this->randomMachineName(2);
     $this->drupalPostForm('admin/config/system/google-analytics', $edit, t('Save configuration'));
-    $this->assertRaw(t('A valid Google Analytics Web Property ID is case sensitive and formatted like UA-xxxxxxx-yy.'), '[testGoogleAnalyticsConfiguration]: Invalid Web Property ID number validated.');
+    $this->assertSession()->responseContains(t('A valid Google Analytics Web Property ID is case sensitive and formatted like UA-xxxxxxx-yy.'));
 
     // User should have access to code snippets.
     $this->assertFieldByName('google_analytics_codesnippet_create');
@@ -105,11 +110,11 @@ public function testGoogleAnalyticsConfiguration() {
   public function testGoogleAnalyticsHelp() {
     // Requires help and block module and help block placement.
     $this->drupalGet('admin/config/system/google-analytics');
-    $this->assertText('Google Analytics is a free (registration required) website traffic and marketing effectiveness service.', '[testGoogleAnalyticsHelp]: Google Analytics help text shown on module settings page.');
+    $this->assertText('Google Analytics is a free (registration required) website traffic and marketing effectiveness service.');
 
     // Requires help.module.
     $this->drupalGet('admin/help/google_analytics');
-    $this->assertText('Google Analytics adds a web statistics tracking system to your website.', '[testGoogleAnalyticsHelp]: Google Analytics help text shown in help section.');
+    $this->assertText('Google Analytics adds a web statistics tracking system to your website.');
   }
 
   /**
@@ -119,7 +124,7 @@ public function testGoogleAnalyticsPageVisibility() {
     // Verify that no tracking code is embedded into the webpage; if there is
     // only the module installed, but UA code not configured. See #2246991.
     $this->drupalGet('');
-    $this->assertNoRaw('https://www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPageVisibility]: Tracking code is not displayed without UA code configured.');
+    $this->assertSession()->responseNotContains('https://www.google-analytics.com/analytics.js');
 
     $ua_code = 'UA-123456-1';
     $this->config('google_analytics.settings')->set('account', $ua_code)->save();
@@ -133,29 +138,29 @@ public function testGoogleAnalyticsPageVisibility() {
 
     // Check tracking code visibility.
     $this->drupalGet('');
-    $this->assertRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is displayed for authenticated users.');
+    $this->assertSession()->responseContains($ua_code);
 
     // Test whether tracking code is not included on pages to omit.
     $this->drupalGet('admin');
-    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is not displayed on admin page.');
+    $this->assertSession()->responseNotContains($ua_code);
     $this->drupalGet('admin/config/system/google-analytics');
     // Checking for tracking URI here, as $ua_code is displayed in the form.
-    $this->assertNoRaw('https://www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPageVisibility]: Tracking code is not displayed on admin subpage.');
+    $this->assertSession()->responseNotContains('https://www.google-analytics.com/analytics.js');
 
     // Test whether tracking code display is properly flipped.
     $this->config('google_analytics.settings')->set('visibility.request_path_mode', 1)->save();
     $this->drupalGet('admin');
-    $this->assertRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is displayed on admin page.');
+    $this->assertSession()->responseContains($ua_code);
     $this->drupalGet('admin/config/system/google-analytics');
     // Checking for tracking URI here, as $ua_code is displayed in the form.
-    $this->assertRaw('https://www.google-analytics.com/analytics.js', '[testGoogleAnalyticsPageVisibility]: Tracking code is displayed on admin subpage.');
+    $this->assertSession()->responseContains('https://www.google-analytics.com/analytics.js');
     $this->drupalGet('');
-    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is NOT displayed on front page.');
+    $this->assertSession()->responseNotContains($ua_code);
 
     // Test whether tracking code is not display for anonymous.
     $this->drupalLogout();
     $this->drupalGet('');
-    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is NOT displayed for anonymous.');
+    $this->assertSession()->responseNotContains($ua_code);
 
     // Switch back to every page except the listed pages.
     $this->config('google_analytics.settings')->set('visibility.request_path_mode', 0)->save();
@@ -166,13 +171,13 @@ public function testGoogleAnalyticsPageVisibility() {
 
     // Test whether 403 forbidden tracking code is shown if user has no access.
     $this->drupalGet('admin');
-    $this->assertResponse(403);
-    $this->assertRaw($base_path . '403.html', '[testGoogleAnalyticsPageVisibility]: 403 Forbidden tracking code shown if user has no access.');
+    $this->assertSession()->statusCodeEquals(403);
+    $this->assertSession()->responseContains($base_path . '403.html');
 
     // Test whether 404 not found tracking code is shown on non-existent pages.
     $this->drupalGet($this->randomMachineName(64));
-    $this->assertResponse(404);
-    $this->assertRaw($base_path . '404.html', '[testGoogleAnalyticsPageVisibility]: 404 Not Found tracking code shown on non-existent page.');
+    $this->assertSession()->statusCodeEquals(404);
+    $this->assertSession()->responseContains($base_path . '404.html');
   }
 
   /**
@@ -204,60 +209,60 @@ public function testGoogleAnalyticsTrackingCode() {
     // Test whether tracking code uses latest JS.
     $this->config('google_analytics.settings')->set('cache', 0)->save();
     $this->drupalGet('');
-    $this->assertRaw('https://www.google-analytics.com/analytics.js', '[testGoogleAnalyticsTrackingCode]: Latest tracking code used.');
+    $this->assertSession()->responseContains('https://www.google-analytics.com/analytics.js');
 
     // Test whether anonymize visitors IP address feature has been enabled.
     $this->config('google_analytics.settings')->set('privacy.anonymizeip', 0)->save();
     $this->drupalGet('');
-    $this->assertNoRaw('ga("set", "anonymizeIp", true);', '[testGoogleAnalyticsTrackingCode]: Anonymize visitors IP address not found on frontpage.');
+    $this->assertSession()->responseNotContains('ga("set", "anonymizeIp", true);');
     // Enable anonymizing of IP addresses.
     $this->config('google_analytics.settings')->set('privacy.anonymizeip', 1)->save();
     $this->drupalGet('');
-    $this->assertRaw('ga("set", "anonymizeIp", true);', '[testGoogleAnalyticsTrackingCode]: Anonymize visitors IP address found on frontpage.');
+    $this->assertSession()->responseContains('ga("set", "anonymizeIp", true);');
 
     // Test if track Enhanced Link Attribution is enabled.
     $this->config('google_analytics.settings')->set('track.linkid', 1)->save();
     $this->drupalGet('');
-    $this->assertRaw('ga("require", "linkid", "linkid.js");', '[testGoogleAnalyticsTrackingCode]: Tracking code for Enhanced Link Attribution is enabled.');
+    $this->assertSession()->responseContains('ga("require", "linkid", "linkid.js");');
 
     // Test if track Enhanced Link Attribution is disabled.
     $this->config('google_analytics.settings')->set('track.linkid', 0)->save();
     $this->drupalGet('');
-    $this->assertNoRaw('ga("require", "linkid", "linkid.js");', '[testGoogleAnalyticsTrackingCode]: Tracking code for Enhanced Link Attribution is not enabled.');
+    $this->assertSession()->responseNotContains('ga("require", "linkid", "linkid.js");');
 
     // Test if tracking of url fragments is enabled.
     $this->config('google_analytics.settings')->set('track.urlfragments', 1)->save();
     $this->drupalGet('');
-    $this->assertRaw('ga("set", "page", location.pathname + location.search + location.hash);', '[testGoogleAnalyticsTrackingCode]: Tracking code for url fragments is enabled.');
+    $this->assertSession()->responseContains('ga("set", "page", location.pathname + location.search + location.hash);');
 
     // Test if tracking of url fragments is disabled.
     $this->config('google_analytics.settings')->set('track.urlfragments', 0)->save();
     $this->drupalGet('');
-    $this->assertNoRaw('ga("set", "page", location.pathname + location.search + location.hash);', '[testGoogleAnalyticsTrackingCode]: Tracking code for url fragments is not enabled.');
+    $this->assertSession()->responseNotContains('ga("set", "page", location.pathname + location.search + location.hash);');
 
     // Test if tracking of User ID is enabled.
     $this->config('google_analytics.settings')->set('track.userid', 1)->save();
     $this->drupalGet('');
-    $this->assertRaw(', {"cookieDomain":"auto","userId":"', '[testGoogleAnalyticsTrackingCode]: Tracking code for User ID is enabled.');
+    $this->assertSession()->responseContains(', {"cookieDomain":"auto","userId":"');
 
     // Test if tracking of User ID is disabled.
     $this->config('google_analytics.settings')->set('track.userid', 0)->save();
     $this->drupalGet('');
-    $this->assertNoRaw(', {"cookieDomain":"auto","userId":"', '[testGoogleAnalyticsTrackingCode]: Tracking code for User ID is disabled.');
+    $this->assertSession()->responseNotContains(', {"cookieDomain":"auto","userId":"');
 
     // Test if track display features is enabled.
     $this->config('google_analytics.settings')->set('track.displayfeatures', 1)->save();
     $this->drupalGet('');
-    $this->assertRaw('ga("require", "displayfeatures");', '[testGoogleAnalyticsTrackingCode]: Tracking code for display features is enabled.');
+    $this->assertSession()->responseContains('ga("require", "displayfeatures");');
 
     // Test if track display features is disabled.
     $this->config('google_analytics.settings')->set('track.displayfeatures', 0)->save();
     $this->drupalGet('');
-    $this->assertNoRaw('ga("require", "displayfeatures");', '[testGoogleAnalyticsTrackingCode]: Tracking code for display features is not enabled.');
+    $this->assertSession()->responseNotContains('ga("require", "displayfeatures");');
 
     // Test whether single domain tracking is active.
     $this->drupalGet('');
-    $this->assertRaw('{"cookieDomain":"auto"}', '[testGoogleAnalyticsTrackingCode]: Single domain tracking is active.');
+    $this->assertSession()->responseContains('{"cookieDomain":"auto"}');
 
     // Enable "One domain with multiple subdomains".
     $this->config('google_analytics.settings')->set('domain_mode', 1)->save();
@@ -268,11 +273,11 @@ public function testGoogleAnalyticsTrackingCode() {
     // reliable.
     global $cookie_domain;
     if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
-      $this->assertRaw('{"cookieDomain":"' . $cookie_domain . '"}', '[testGoogleAnalyticsTrackingCode]: One domain with multiple subdomains is active on real host.');
+      $this->assertSession()->responseContains('{"cookieDomain":"' . $cookie_domain . '"}');
     }
     else {
       // Special cases, Localhost and IP addresses don't show 'cookieDomain'.
-      $this->assertNoRaw('{"cookieDomain":"' . $cookie_domain . '"}', '[testGoogleAnalyticsTrackingCode]: One domain with multiple subdomains may be active on localhost (test result is not reliable).');
+      $this->assertSession()->responseNotContains('{"cookieDomain":"' . $cookie_domain . '"}');
     }
 
     // Enable "Multiple top-level domains" tracking.
@@ -281,27 +286,27 @@ public function testGoogleAnalyticsTrackingCode() {
       ->set('cross_domains', "www.example.com\nwww.example.net")
       ->save();
     $this->drupalGet('');
-    $this->assertRaw('ga("create", "' . $ua_code . '", {"cookieDomain":"auto","allowLinker":true', '[testGoogleAnalyticsTrackingCode]: "allowLinker" has been found. Cross domain tracking is active.');
-    $this->assertRaw('ga("require", "linker");', '[testGoogleAnalyticsTrackingCode]: Require linker has been found. Cross domain tracking is active.');
-    $this->assertRaw('ga("linker:autoLink", ["www.example.com","www.example.net"]);', '[testGoogleAnalyticsTrackingCode]: "linker:autoLink" has been found. Cross domain tracking is active.');
-    $this->assertRaw('"trackDomainMode":2,', '[testGoogleAnalyticsTrackingCode]: Domain mode value is of type integer.');
-    $this->assertRaw('"trackCrossDomains":["www.example.com","www.example.net"]', '[testGoogleAnalyticsTrackingCode]: Cross domain tracking with www.example.com and www.example.net is active.');
+    $this->assertSession()->responseContains('ga("create", "' . $ua_code . '", {"cookieDomain":"auto","allowLinker":true');
+    $this->assertSession()->responseContains('ga("require", "linker");');
+    $this->assertSession()->responseContains('ga("linker:autoLink", ["www.example.com","www.example.net"]);');
+    $this->assertSession()->responseContains('"trackDomainMode":2,');
+    $this->assertSession()->responseContains('"trackCrossDomains":["www.example.com","www.example.net"]');
     $this->config('google_analytics.settings')->set('domain_mode', 0)->save();
 
     // Test whether debugging script has been enabled.
     $this->config('google_analytics.settings')->set('debug', 1)->save();
     $this->drupalGet('');
-    $this->assertRaw('https://www.google-analytics.com/analytics_debug.js', '[testGoogleAnalyticsTrackingCode]: Google debugging script has been enabled.');
+    $this->assertSession()->responseContains('https://www.google-analytics.com/analytics_debug.js');
 
     // Check if text and link is shown on 'Status Reports' page.
     // Requires 'administer site configuration' permission.
     $this->drupalGet('admin/reports/status');
-    $this->assertRaw(t('Google Analytics module has debugging enabled. Please disable debugging setting in production sites from the <a href=":url">Google Analytics settings page</a>.', [':url' => Url::fromRoute('google_analytics.admin_settings_form')->toString()]), '[testGoogleAnalyticsConfiguration]: Debugging enabled is shown on Status Reports page.');
+    $this->assertSession()->responseContains(t('Google Analytics module has debugging enabled. Please disable debugging setting in production sites from the <a href=":url">Google Analytics settings page</a>.', [':url' => Url::fromRoute('google_analytics.admin_settings_form')->toString()]));
 
     // Test whether debugging script has been disabled.
     $this->config('google_analytics.settings')->set('debug', 0)->save();
     $this->drupalGet('');
-    $this->assertRaw('https://www.google-analytics.com/analytics.js', '[testGoogleAnalyticsTrackingCode]: Google debugging script has been disabled.');
+    $this->assertSession()->responseContains('https://www.google-analytics.com/analytics.js');
 
     // Test whether the CREATE and BEFORE and AFTER code is added to the
     // tracking code.
@@ -318,10 +323,10 @@ public function testGoogleAnalyticsTrackingCode() {
       ->set('codesnippet.after', 'ga("create", "UA-123456-3", {"name": "newTracker"});if(1 == 1 && 2 < 3 && 2 > 1){console.log("Google Analytics: Custom condition works.");}ga("newTracker.send", "pageview");')
       ->save();
     $this->drupalGet('');
-    $this->assertRaw('ga("create", "' . $ua_code . '", {"cookieDomain":"foo.example.com","cookieName":"myNewName","cookieExpires":20000,"allowAnchor":true,"sampleRate":4.3});', '[testGoogleAnalyticsTrackingCode]: Create only fields have been found.');
-    $this->assertRaw('ga("set", "forceSSL", true);', '[testGoogleAnalyticsTrackingCode]: Before codesnippet will force http pages to also send all beacons using https.');
-    $this->assertRaw('ga("create", "UA-123456-3", {"name": "newTracker"});', '[testGoogleAnalyticsTrackingCode]: After codesnippet with "newTracker" tracker has been found.');
-    $this->assertRaw('if(1 == 1 && 2 < 3 && 2 > 1){console.log("Google Analytics: Custom condition works.");}', '[testGoogleAnalyticsTrackingCode]: JavaScript code is not HTML escaped.');
+    $this->assertSession()->responseContains('ga("create", "' . $ua_code . '", {"cookieDomain":"foo.example.com","cookieName":"myNewName","cookieExpires":20000,"allowAnchor":true,"sampleRate":4.3});');
+    $this->assertSession()->responseContains('ga("set", "forceSSL", true);');
+    $this->assertSession()->responseContains('ga("create", "UA-123456-3", {"name": "newTracker"});');
+    $this->assertSession()->responseContains('if(1 == 1 && 2 < 3 && 2 > 1){console.log("Google Analytics: Custom condition works.");}');
   }
 
 }
diff --git a/web/modules/google_analytics/src/Tests/GoogleAnalyticsCustomDimensionsAndMetricsTest.php b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsCustomDimensionsAndMetricsTest.php
similarity index 56%
rename from web/modules/google_analytics/src/Tests/GoogleAnalyticsCustomDimensionsAndMetricsTest.php
rename to web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsCustomDimensionsAndMetricsTest.php
index 9404debc01..143f5c7143 100644
--- a/web/modules/google_analytics/src/Tests/GoogleAnalyticsCustomDimensionsAndMetricsTest.php
+++ b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsCustomDimensionsAndMetricsTest.php
@@ -1,9 +1,9 @@
 <?php
 
-namespace Drupal\google_analytics\Tests;
+namespace Drupal\Tests\google_analytics\Functional;
 
 use Drupal\Component\Serialization\Json;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Test custom dimensions and metrics functionality of Google Analytics module.
@@ -12,7 +12,7 @@
  *
  * @dependencies token
  */
-class GoogleAnalyticsCustomDimensionsAndMetricsTest extends WebTestBase {
+class GoogleAnalyticsCustomDimensionsAndMetricsTest extends BrowserTestBase {
 
   /**
    * Modules to enable.
@@ -21,6 +21,11 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends WebTestBase {
    */
   public static $modules = ['google_analytics', 'token', 'node'];
 
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
   /**
    * {@inheritdoc}
    */
@@ -82,7 +87,7 @@ public function testGoogleAnalyticsCustomDimensions() {
     $this->drupalGet('');
 
     foreach ($google_analytics_custom_dimension as $dimension) {
-      $this->assertRaw('ga("set", ' . Json::encode('dimension' . $dimension['index']) . ', ' . Json::encode($dimension['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Dimension #' . $dimension['index'] . ' is shown.');
+      $this->assertSession()->responseContains('ga("set", ' . Json::encode('dimension' . $dimension['index']) . ', ' . Json::encode($dimension['value']) . ');');
     }
 
     // Test whether tokens are replaced in custom dimension values.
@@ -127,18 +132,18 @@ public function testGoogleAnalyticsCustomDimensions() {
 
     // Test on frontpage.
     $this->drupalGet('');
-    $this->assertRaw('ga("set", ' . Json::encode('dimension1') . ', ' . Json::encode("Value: $site_slogan") . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Tokens have been replaced in dimension value.');
-    $this->assertRaw('ga("set", ' . Json::encode('dimension2') . ', ' . Json::encode($google_analytics_custom_dimension['2']['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Random value is shown.');
-    $this->assertNoRaw('ga("set", ' . Json::encode('dimension3') . ', ' . Json::encode('') . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Empty value is not shown.');
-    $this->assertRaw('ga("set", ' . Json::encode('dimension4') . ', ' . Json::encode('0') . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Value 0 is shown.');
-    $this->assertNoRaw('ga("set", ' . Json::encode('dimension5') . ', ' . Json::encode('article') . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Node tokens are shown.');
-    $this->assertRaw('ga("set", ' . Json::encode('dimension6') . ', ' . Json::encode(implode(',', \Drupal::currentUser()->getRoles())) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: List of roles shown.');
-    $this->assertRaw('ga("set", ' . Json::encode('dimension7') . ', ' . Json::encode(implode(',', array_keys(\Drupal::currentUser()->getRoles()))) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: List of role IDs shown.');
+    $this->assertSession()->responseContains('ga("set", ' . Json::encode('dimension1') . ', ' . Json::encode("Value: $site_slogan") . ');');
+    $this->assertSession()->responseContains('ga("set", ' . Json::encode('dimension2') . ', ' . Json::encode($google_analytics_custom_dimension['2']['value']) . ');');
+    $this->assertSession()->responseNotContains('ga("set", ' . Json::encode('dimension3') . ', ' . Json::encode('') . ');');
+    $this->assertSession()->responseContains('ga("set", ' . Json::encode('dimension4') . ', ' . Json::encode('0') . ');');
+    $this->assertSession()->responseNotContains('ga("set", ' . Json::encode('dimension5') . ', ' . Json::encode('article') . ');');
+    $this->assertSession()->responseContains('ga("set", ' . Json::encode('dimension6') . ', ' . Json::encode(implode(',', \Drupal::currentUser()->getRoles())) . ');');
+    $this->assertSession()->responseContains('ga("set", ' . Json::encode('dimension7') . ', ' . Json::encode(implode(',', array_keys(\Drupal::currentUser()->getRoles()))) . ');');
 
     // Test on a node.
     $this->drupalGet('node/' . $node->id());
     $this->assertText($node->getTitle());
-    $this->assertRaw('ga("set", ' . Json::encode('dimension5') . ', ' . Json::encode('article') . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Node tokens are shown.');
+    $this->assertSession()->responseContains('ga("set", ' . Json::encode('dimension5') . ', ' . Json::encode('article') . ');');
   }
 
   /**
@@ -176,7 +181,7 @@ public function testGoogleAnalyticsCustomMetrics() {
     $this->drupalGet('');
 
     foreach ($google_analytics_custom_metric as $metric) {
-      $this->assertRaw('ga("set", ' . Json::encode('metric' . $metric['index']) . ', ' . Json::encode((float) $metric['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Metric #' . $metric['index'] . ' is shown.');
+      $this->assertSession()->responseContains('ga("set", ' . Json::encode('metric' . $metric['index']) . ', ' . Json::encode((float) $metric['value']) . ');');
     }
 
     // Test whether tokens are replaced in custom metric values.
@@ -204,10 +209,10 @@ public function testGoogleAnalyticsCustomMetrics() {
     $this->verbose('<pre>' . print_r($google_analytics_custom_metric, TRUE) . '</pre>');
 
     $this->drupalGet('');
-    $this->assertRaw('ga("set", ' . Json::encode('metric1') . ', ', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Tokens have been replaced in metric value.');
-    $this->assertRaw('ga("set", ' . Json::encode('metric2') . ', ' . Json::encode($google_analytics_custom_metric['2']['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Random value is shown.');
-    $this->assertNoRaw('ga("set", ' . Json::encode('metric3') . ', ' . Json::encode('') . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Empty value is not shown.');
-    $this->assertRaw('ga("set", ' . Json::encode('metric4') . ', ' . Json::encode(0) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Value 0 is shown.');
+    $this->assertSession()->responseContains('ga("set", ' . Json::encode('metric1') . ', ');
+    $this->assertSession()->responseContains('ga("set", ' . Json::encode('metric2') . ', ' . Json::encode($google_analytics_custom_metric['2']['value']) . ');');
+    $this->assertSession()->responseNotContains('ga("set", ' . Json::encode('metric3') . ', ' . Json::encode('') . ');');
+    $this->assertSession()->responseContains('ga("set", ' . Json::encode('metric4') . ', ' . Json::encode(0) . ');');
   }
 
   /**
@@ -226,12 +231,12 @@ public function testGoogleAnalyticsCustomDimensionsTokenFormValidation() {
 
     $this->drupalPostForm('admin/config/system/google-analytics', $edit, t('Save configuration'));
 
-    $this->assertRaw(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', ['%element-title' => t('Custom dimension value #@index', ['@index' => 1]), '@invalid-tokens' => implode(', ', ['[current-user:name]'])]));
-    $this->assertRaw(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', ['%element-title' => t('Custom dimension value #@index', ['@index' => 2]), '@invalid-tokens' => implode(', ', ['[current-user:edit-url]'])]));
-    $this->assertRaw(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', ['%element-title' => t('Custom dimension value #@index', ['@index' => 3]), '@invalid-tokens' => implode(', ', ['[user:name]'])]));
+    $this->assertSession()->responseContains(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', ['%element-title' => t('Custom dimension value #@index', ['@index' => 1]), '@invalid-tokens' => implode(', ', ['[current-user:name]'])]));
+    $this->assertSession()->responseContains(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', ['%element-title' => t('Custom dimension value #@index', ['@index' => 2]), '@invalid-tokens' => implode(', ', ['[current-user:edit-url]'])]));
+    $this->assertSession()->responseContains(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', ['%element-title' => t('Custom dimension value #@index', ['@index' => 3]), '@invalid-tokens' => implode(', ', ['[user:name]'])]));
     // BUG #2037595
-    //$this->assertNoRaw(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', ['%element-title' => t('Custom dimension value #@index', ['@index' => 4]), '@invalid-tokens' => implode(', ', ['[term:name]'])]));
-    //$this->assertNoRaw(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', ['%element-title' => t('Custom dimension value #@index', ['@index' => 5]), '@invalid-tokens' => implode(', ', ['[term:tid]'])]));
+    //$this->assertSession()->responseNotContains(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', ['%element-title' => t('Custom dimension value #@index', ['@index' => 4]), '@invalid-tokens' => implode(', ', ['[term:name]'])]));
+    //$this->assertSession()->responseNotContains(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', ['%element-title' => t('Custom dimension value #@index', ['@index' => 5]), '@invalid-tokens' => implode(', ', ['[term:tid]'])]));
   }
 
 }
diff --git a/web/modules/google_analytics/src/Tests/GoogleAnalyticsCustomUrls.php b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsCustomUrls.php
similarity index 68%
rename from web/modules/google_analytics/src/Tests/GoogleAnalyticsCustomUrls.php
rename to web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsCustomUrls.php
index da9c6558b9..07faca58df 100644
--- a/web/modules/google_analytics/src/Tests/GoogleAnalyticsCustomUrls.php
+++ b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsCustomUrls.php
@@ -1,15 +1,15 @@
 <?php
 
-namespace Drupal\google_analytics\Tests;
+namespace Drupal\Tests\google_analytics\Functional;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Test custom url functionality of Google Analytics module.
  *
  * @group Google Analytics
  */
-class GoogleAnalyticsCustomUrls extends WebTestBase {
+class GoogleAnalyticsCustomUrls extends BrowserTestBase {
 
   /**
    * Modules to enable.
@@ -18,6 +18,11 @@ class GoogleAnalyticsCustomUrls extends WebTestBase {
    */
   public static $modules = ['google_analytics'];
 
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
   /**
    * {@inheritdoc}
    */
@@ -44,13 +49,13 @@ public function testGoogleAnalyticsUserPasswordPage() {
     $this->config('google_analytics.settings')->set('account', $ua_code)->save();
 
     $this->drupalGet('user/password', ['query' => ['name' => 'foo']]);
-    $this->assertRaw('ga("set", "page", "' . $base_path . 'user/password"');
+    $this->assertSession()->responseContains('ga("set", "page", "' . $base_path . 'user/password"');
 
     $this->drupalGet('user/password', ['query' => ['name' => 'foo@example.com']]);
-    $this->assertRaw('ga("set", "page", "' . $base_path . 'user/password"');
+    $this->assertSession()->responseContains('ga("set", "page", "' . $base_path . 'user/password"');
 
     $this->drupalGet('user/password');
-    $this->assertNoRaw('ga("set", "page",', '[testGoogleAnalyticsCustomUrls]: Custom url not set.');
+    $this->assertSession()->responseNotContains('ga("set", "page",');
   }
 
 }
diff --git a/web/modules/google_analytics/src/Tests/GoogleAnalyticsJavaScriptTest.js b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsJavaScriptTest.js
similarity index 100%
rename from web/modules/google_analytics/src/Tests/GoogleAnalyticsJavaScriptTest.js
rename to web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsJavaScriptTest.js
diff --git a/web/modules/google_analytics/src/Tests/GoogleAnalyticsRolesTest.php b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsRolesTest.php
similarity index 52%
rename from web/modules/google_analytics/src/Tests/GoogleAnalyticsRolesTest.php
rename to web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsRolesTest.php
index f0390aedf3..4202b0f272 100644
--- a/web/modules/google_analytics/src/Tests/GoogleAnalyticsRolesTest.php
+++ b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsRolesTest.php
@@ -1,16 +1,16 @@
 <?php
 
-namespace Drupal\google_analytics\Tests;
+namespace Drupal\Tests\google_analytics\Functional;
 
 use Drupal\Core\Session\AccountInterface;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Test roles functionality of Google Analytics module.
  *
  * @group Google Analytics
  */
-class GoogleAnalyticsRolesTest extends WebTestBase {
+class GoogleAnalyticsRolesTest extends BrowserTestBase {
 
   /**
    * Modules to enable.
@@ -19,6 +19,11 @@ class GoogleAnalyticsRolesTest extends WebTestBase {
    */
   public static $modules = ['google_analytics'];
 
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
   /**
    * {@inheritdoc}
    */
@@ -49,28 +54,28 @@ public function testGoogleAnalyticsRolesTracking() {
 
     // Check tracking code visibility.
     $this->drupalGet('');
-    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is displayed for anonymous users on frontpage with default settings.');
+    $this->assertSession()->responseContains($ua_code);
     $this->drupalGet('admin');
-    $this->assertResponse(403);
-    $this->assertRaw('/403.html', '[testGoogleAnalyticsRoleVisibility]: 403 Forbidden tracking code is displayed for anonymous users in admin section with default settings.');
+    $this->assertSession()->statusCodeEquals(403);
+    $this->assertSession()->responseContains('/403.html');
 
     $this->drupalLogin($this->admin_user);
 
     $this->drupalGet('');
-    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is displayed for authenticated users on frontpage with default settings.');
+    $this->assertSession()->responseContains($ua_code);
     $this->drupalGet('admin');
-    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is NOT displayed for authenticated users in admin section with default settings.');
+    $this->assertSession()->responseNotContains($ua_code);
 
     // Test if the non-default settings are working as expected.
     // Enable tracking only for authenticated users.
     $this->config('google_analytics.settings')->set('visibility.user_role_roles', [AccountInterface::AUTHENTICATED_ROLE => AccountInterface::AUTHENTICATED_ROLE])->save();
 
     $this->drupalGet('');
-    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is displayed for authenticated users only on frontpage.');
+    $this->assertSession()->responseContains($ua_code);
 
     $this->drupalLogout();
     $this->drupalGet('');
-    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is NOT displayed for anonymous users on frontpage.');
+    $this->assertSession()->responseNotContains($ua_code);
 
     // Add to every role except the selected ones.
     $this->config('google_analytics.settings')->set('visibility.user_role_mode', 1)->save();
@@ -79,29 +84,29 @@ public function testGoogleAnalyticsRolesTracking() {
 
     // Check tracking code visibility.
     $this->drupalGet('');
-    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is added to every role and displayed for anonymous users.');
+    $this->assertSession()->responseContains($ua_code);
     $this->drupalGet('admin');
-    $this->assertResponse(403);
-    $this->assertRaw('/403.html', '[testGoogleAnalyticsRoleVisibility]: 403 Forbidden tracking code is shown for anonymous users if every role except the selected ones is selected.');
+    $this->assertSession()->statusCodeEquals(403);
+    $this->assertSession()->responseContains('/403.html');
 
     $this->drupalLogin($this->admin_user);
 
     $this->drupalGet('');
-    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is added to every role and displayed on frontpage for authenticated users.');
+    $this->assertSession()->responseContains($ua_code);
     $this->drupalGet('admin');
-    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is added to every role and NOT displayed in admin section for authenticated users.');
+    $this->assertSession()->responseNotContains($ua_code);
 
     // Disable tracking for authenticated users.
     $this->config('google_analytics.settings')->set('visibility.user_role_roles', [AccountInterface::AUTHENTICATED_ROLE => AccountInterface::AUTHENTICATED_ROLE])->save();
 
     $this->drupalGet('');
-    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is NOT displayed on frontpage for excluded authenticated users.');
+    $this->assertSession()->responseNotContains($ua_code);
     $this->drupalGet('admin');
-    $this->assertNoRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is NOT displayed in admin section for excluded authenticated users.');
+    $this->assertSession()->responseNotContains($ua_code);
 
     $this->drupalLogout();
     $this->drupalGet('');
-    $this->assertRaw($ua_code, '[testGoogleAnalyticsRoleVisibility]: Tracking code is displayed on frontpage for included anonymous users.');
+    $this->assertSession()->responseContains($ua_code);
   }
 
 }
diff --git a/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsSearchTest.php b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsSearchTest.php
new file mode 100644
index 0000000000..de4542d3e2
--- /dev/null
+++ b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsSearchTest.php
@@ -0,0 +1,114 @@
+<?php
+
+namespace Drupal\Tests\google_analytics\Functional;
+
+use Drupal\search\SearchIndexInterface;
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Test search functionality of Google Analytics module.
+ *
+ * @group Google Analytics
+ */
+class GoogleAnalyticsSearchTest extends BrowserTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['google_analytics', 'search', 'node'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
+
+    $permissions = [
+      'access administration pages',
+      'administer google analytics',
+      'search content',
+      'create page content',
+      'edit own page content',
+    ];
+
+    // User to set up google_analytics.
+    $this->admin_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($this->admin_user);
+  }
+
+  /**
+   * Tests if search tracking is properly added to the page.
+   */
+  public function testGoogleAnalyticsSearchTracking() {
+    $ua_code = 'UA-123456-1';
+    $this->config('google_analytics.settings')->set('account', $ua_code)->save();
+
+    // Check tracking code visibility.
+    $this->drupalGet('');
+    $this->assertRaw($ua_code);
+
+    $this->drupalGet('search/node');
+    $this->assertNoRaw('ga("set", "page",');
+
+    // Enable site search support.
+    $this->config('google_analytics.settings')->set('track.site_search', 1)->save();
+
+    // Search for random string.
+    $search = ['keys' => $this->randomMachineName(8)];
+
+    // Fire a search, it's expected to get 0 results.
+    $this->drupalPostForm('search/node', $search, t('Search'));
+    $this->assertSession()->responseContains('ga("set", "page", (window.google_analytics_search_results) ?');
+    $this->assertSession()->responseContains('window.google_analytics_search_results = 0;');
+
+    // Create a node and reindex.
+    $this->createNodeAndIndex($search['keys']);
+    $this->drupalPostForm('search/node', $search, t('Search'));
+    $this->assertSession()->responseContains('ga("set", "page", (window.google_analytics_search_results) ?');
+    $this->assertSession()->responseContains('window.google_analytics_search_results = 1;');
+
+    // Create a second node with same values and reindex.
+    $this->createNodeAndIndex($search['keys']);
+    $this->drupalPostForm('search/node', $search, t('Search'));
+    $this->assertSession()->responseContains('ga("set", "page", (window.google_analytics_search_results) ?');
+    $this->assertSession()->responseContains('window.google_analytics_search_results = 2;');
+  }
+
+  /**
+   * Helper function to create the node and reindex search.
+   *
+   * @param string $test_string
+   *   Some unique identifying string to add to the text of the node.
+   *
+   * @return \Drupal\node\NodeInterface
+   *   The created node.
+   * @internal
+   */
+  protected function createNodeAndIndex($test_string) {
+    // Create the node.
+    $node = $this->drupalCreateNode([
+      'title' => "Someone who says $test_string!",
+      'body' => [['value' => "We are the knights who say $test_string!"]],
+      'type' => 'page',
+    ]);
+
+    // Index the node or it cannot found.
+    $node_search_plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
+    // Update the search index.
+    $node_search_plugin->updateIndex();
+    $search_index = \Drupal::service('search.index');
+    assert($search_index instanceof SearchIndexInterface);
+
+    return $node;
+  }
+
+}
diff --git a/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsStatusMessagesTest.php b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsStatusMessagesTest.php
new file mode 100644
index 0000000000..e1ac0cfd05
--- /dev/null
+++ b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsStatusMessagesTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Drupal\Tests\google_analytics\Functional;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Test status messages functionality of Google Analytics module.
+ *
+ * @group Google Analytics
+ */
+class GoogleAnalyticsStatusMessagesTest extends BrowserTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['google_analytics', 'google_analytics_test'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $permissions = [
+      'access administration pages',
+      'administer google analytics',
+    ];
+
+    // User to set up google_analytics.
+    $this->admin_user = $this->drupalCreateUser($permissions);
+  }
+
+  /**
+   * Tests if status messages tracking is properly added to the page.
+   */
+  public function testGoogleAnalyticsStatusMessages() {
+    $ua_code = 'UA-123456-4';
+    $this->config('google_analytics.settings')->set('account', $ua_code)->save();
+
+    // Enable logging of errors only.
+    $this->config('google_analytics.settings')->set('track.messages', ['error' => 'error'])->save();
+
+    $this->drupalPostForm('user/login', [], t('Log in'));
+    $this->assertSession()->responseContains('ga("send", "event", "Messages", "Error message", "Username field is required.");');
+    $this->assertSession()->responseContains('ga("send", "event", "Messages", "Error message", "Password field is required.");');
+
+    // Testing this drupal_set_message() requires an extra test module.
+    $this->drupalGet('google-analytics-test/drupal-messenger-add-message');
+    $this->assertSession()->responseNotContains('ga("send", "event", "Messages", "Status message", "Example status message.");');
+    $this->assertSession()->responseNotContains('ga("send", "event", "Messages", "Warning message", "Example warning message.");');
+    $this->assertSession()->responseContains('ga("send", "event", "Messages", "Error message", "Example error message.");');
+    $this->assertSession()->responseContains('ga("send", "event", "Messages", "Error message", "Example error message with html tags and link.");');
+
+    // Enable logging of status, warnings and errors.
+    $this->config('google_analytics.settings')->set('track.messages', [
+      'status' => 'status',
+      'warning' => 'warning',
+      'error' => 'error',
+    ])->save();
+
+    $this->drupalGet('google-analytics-test/drupal-messenger-add-message');
+    $this->assertSession()->responseContains('ga("send", "event", "Messages", "Status message", "Example status message.");');
+    $this->assertSession()->responseContains('ga("send", "event", "Messages", "Warning message", "Example warning message.");');
+    $this->assertSession()->responseContains('ga("send", "event", "Messages", "Error message", "Example error message.");');
+    $this->assertSession()->responseContains('ga("send", "event", "Messages", "Error message", "Example error message with html tags and link.");');
+  }
+
+}
diff --git a/web/modules/google_analytics/src/Tests/GoogleAnalyticsUninstallTest.php b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsUninstallTest.php
similarity index 59%
rename from web/modules/google_analytics/src/Tests/GoogleAnalyticsUninstallTest.php
rename to web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsUninstallTest.php
index f73f0a7c42..47e34e1b6c 100644
--- a/web/modules/google_analytics/src/Tests/GoogleAnalyticsUninstallTest.php
+++ b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsUninstallTest.php
@@ -1,15 +1,15 @@
 <?php
 
-namespace Drupal\google_analytics\Tests;
+namespace Drupal\Tests\google_analytics\Functional;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Test uninstall functionality of Google Analytics module.
  *
  * @group Google Analytics
  */
-class GoogleAnalyticsUninstallTest extends WebTestBase {
+class GoogleAnalyticsUninstallTest extends BrowserTestBase {
 
   /**
    * Modules to enable.
@@ -18,6 +18,11 @@ class GoogleAnalyticsUninstallTest extends WebTestBase {
    */
   public static $modules = ['google_analytics'];
 
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
   /**
    * {@inheritdoc}
    */
@@ -52,21 +57,20 @@ public function testGoogleAnalyticsUninstall() {
     $this->drupalGet('');
 
     // Test if the directory and analytics.js exists.
-    $this->assertTrue(file_prepare_directory($cache_path), 'Cache directory "public://google_analytics" has been found.');
-    $this->assertTrue(file_exists($cache_path . '/analytics.js'), 'Cached analytics.js tracking file has been found.');
-    $this->assertTrue(file_exists($cache_path . '/analytics.js.gz'), 'Cached analytics.js.gz tracking file has been found.');
+    $this->assertDirectoryExists($cache_path, 'Cache directory "public://google_analytics" has been found.');
+    $this->assertFileExists($cache_path . '/analytics.js', 'Cached analytics.js tracking file has been found.');
+    $this->assertFileExists($cache_path . '/analytics.js.gz', 'Cached analytics.js.gz tracking file has been found.');
 
     // Uninstall the module.
     $edit = [];
     $edit['uninstall[google_analytics]'] = TRUE;
     $this->drupalPostForm('admin/modules/uninstall', $edit, t('Uninstall'));
-    $this->assertNoText(\Drupal::translation()->translate('Configuration deletions'), 'No configuration deletions listed on the module install confirmation page.');
+    $this->assertSession()->pageTextNotContains(\Drupal::translation()->translate('Configuration deletions'));
     $this->drupalPostForm(NULL, NULL, t('Uninstall'));
-    $this->assertText(t('The selected modules have been uninstalled.'), 'Modules status has been updated.');
+    $this->assertSession()->pageTextContains(t('The selected modules have been uninstalled.'));
 
     // Test if the directory and all files have been removed.
-    $this->assertFalse(file_scan_directory($cache_path, '/.*/'), 'Cached JavaScript files have been removed.');
-    $this->assertFalse(file_prepare_directory($cache_path), 'Cache directory "public://google_analytics" has been removed.');
+    $this->assertDirectoryNotExists($cache_path);
   }
 
 }
diff --git a/web/modules/google_analytics/src/Tests/GoogleAnalyticsUserFieldsTest.php b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsUserFieldsTest.php
similarity index 64%
rename from web/modules/google_analytics/src/Tests/GoogleAnalyticsUserFieldsTest.php
rename to web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsUserFieldsTest.php
index eb1e7dfd19..1ab12846d5 100644
--- a/web/modules/google_analytics/src/Tests/GoogleAnalyticsUserFieldsTest.php
+++ b/web/modules/google_analytics/tests/src/Functional/GoogleAnalyticsUserFieldsTest.php
@@ -1,15 +1,15 @@
 <?php
 
-namespace Drupal\google_analytics\Tests;
+namespace Drupal\Tests\google_analytics\Functional;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Test user fields functionality of Google Analytics module.
  *
  * @group Google Analytics
  */
-class GoogleAnalyticsUserFieldsTest extends WebTestBase {
+class GoogleAnalyticsUserFieldsTest extends BrowserTestBase {
 
   /**
    * Modules to enable.
@@ -18,6 +18,11 @@ class GoogleAnalyticsUserFieldsTest extends WebTestBase {
    */
   public static $modules = ['google_analytics', 'field_ui'];
 
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
   /**
    * {@inheritdoc}
    */
@@ -44,28 +49,28 @@ public function testGoogleAnalyticsUserFields() {
 
     // Check if the pseudo field is shown on account forms.
     $this->drupalGet('admin/config/people/accounts/form-display');
-    $this->assertResponse(200);
-    $this->assertRaw(t('Google Analytics settings'), '[testGoogleAnalyticsUserFields]: Google Analytics settings field exists on Manage form display.');
+    $this->assertSession()->statusCodeEquals(200);
+    $this->assertSession()->responseContains(t('Google Analytics settings'));
 
     // No customization allowed.
     $this->config('google_analytics.settings')->set('visibility.user_account_mode', 0)->save();
     $this->drupalGet('user/' . $this->admin_user->id() . '/edit');
-    $this->assertResponse(200);
-    $this->assertNoRaw(t('Google Analytics settings'), '[testGoogleAnalyticsUserFields]: Google Analytics settings field does not exist on user edit page.');
+    $this->assertSession()->statusCodeEquals(200);
+    $this->assertSession()->responseNotContains(t('Google Analytics settings'));
 
     // Tracking on by default, users with opt-in or out of tracking permission
     // can opt out.
     $this->config('google_analytics.settings')->set('visibility.user_account_mode', 1)->save();
     $this->drupalGet('user/' . $this->admin_user->id() . '/edit');
-    $this->assertResponse(200);
-    $this->assertRaw(t('Users are tracked by default, but you are able to opt out.'), '[testGoogleAnalyticsUserFields]: Google Analytics settings field exists on on user edit page');
+    $this->assertSession()->statusCodeEquals(200);
+    $this->assertSession()->responseContains(t('Users are tracked by default, but you are able to opt out.'));
 
     // Tracking off by default, users with opt-in or out of tracking permission
     // can opt in.
     $this->config('google_analytics.settings')->set('visibility.user_account_mode', 2)->save();
     $this->drupalGet('user/' . $this->admin_user->id() . '/edit');
-    $this->assertResponse(200);
-    $this->assertRaw(t('Users are <em>not</em> tracked by default, but you are able to opt in.'), '[testGoogleAnalyticsUserFields]: Google Analytics settings field exists on on user edit page.');
+    $this->assertSession()->statusCodeEquals(200);
+    $this->assertSession()->responseContains(t('Users are <em>not</em> tracked by default, but you are able to opt in.'));
   }
 
 }
-- 
GitLab