diff --git a/wagtail/admin/templates/wagtailadmin/userbar/base.html b/wagtail/admin/templates/wagtailadmin/userbar/base.html
index ee3629e736..247652249d 100644
--- a/wagtail/admin/templates/wagtailadmin/userbar/base.html
+++ b/wagtail/admin/templates/wagtailadmin/userbar/base.html
@@ -51,7 +51,7 @@
     </template>
     <template id="w-a11y-result-selector-template">
         <button class="w-a11y-result__selector" data-a11y-result-selector type="button">
-            {% icon name="crosshairs" class_name="w-a11y-result__icon" %}
+            {% icon name="crosshairs" classname="w-a11y-result__icon" %}
             <span data-a11y-result-selector-text></span>
         </button>
     </template>
diff --git a/wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_content_types_checkbox.html b/wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_content_types_checkbox.html
index 0005aaec1f..da943a5cde 100644
--- a/wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_content_types_checkbox.html
+++ b/wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_content_types_checkbox.html
@@ -3,7 +3,7 @@
 {% for id, errors in errors_by_id.items %}
     {% if id == widget.value %}
         <div class="w-field__errors" data-field-errors>
-            {% icon name="warning" class_name="w-field__errors-icon" %}
+            {% icon name="warning" classname="w-field__errors-icon" %}
             <p class="error-message">
                 {% for error in errors %}{{ error.message }} {% endfor %}
             </p>
diff --git a/wagtail/admin/templatetags/wagtailadmin_tags.py b/wagtail/admin/templatetags/wagtailadmin_tags.py
index fdb15c5d3c..a94d1a6f1e 100644
--- a/wagtail/admin/templatetags/wagtailadmin_tags.py
+++ b/wagtail/admin/templatetags/wagtailadmin_tags.py
@@ -764,8 +764,8 @@ def icon(name=None, classname=None, title=None, wrapped=False, class_name=None):
 
         warn(
             (
-                "Icon template tag `class_name` has been renamed to `classname`, please adopt the new usage instead.",
-                f'Replace `{{% icon ... class_name="{class_name}" %}}` with `{{% icon ... classname="{class_name}" %}}`',
+                "Icon template tag `class_name` has been renamed to `classname`, please adopt the new usage instead. "
+                f'Replace `{{% icon ... class_name="{class_name}" %}}` with `{{% icon ... classname="{class_name}" %}}`'
             ),
             category=RemovedInWagtail50Warning,
         )

diff --git a/wagtail/admin/tests/test_templatetags.py b/wagtail/admin/tests/test_templatetags.py
index 12aad1683a..a28c2f13ea 100644
--- a/wagtail/admin/tests/test_templatetags.py
+++ b/wagtail/admin/tests/test_templatetags.py
@@ -27,6 +27,7 @@ from wagtail.images.tests.utils import get_test_image_file
 from wagtail.models import Locale
 from wagtail.test.utils import WagtailTestUtils
 from wagtail.users.models import UserProfile
+from wagtail.utils.deprecation import RemovedInWagtail50Warning
 
 
 class TestAvatarTemplateTag(TestCase, WagtailTestUtils):
@@ -483,3 +484,62 @@ class ClassnamesTagTest(TestCase):
         actual = Template(template).render(context)
 
         self.assertEqual(expected.strip(), actual.strip())
+
+
+class IconTagTest(TestCase):
+    def test_basic(self):
+        template = """
+            {% load wagtailadmin_tags %}
+            {% icon "wagtail" %}
+        """
+
+        expected = """
+            <svg aria-hidden="true" class="icon icon-wagtail icon"><use href="#icon-wagtail"></svg>
+        """
+
+        self.assertHTMLEqual(expected, Template(template).render(Context()))
+
+    def test_with_classes_positional(self):
+        template = """
+            {% load wagtailadmin_tags %}
+            {% icon "cogs" "myclass" %}
+        """
+
+        expected = """
+            <svg aria-hidden="true" class="icon icon-cogs myclass"><use href="#icon-cogs"></svg>
+        """
+
+        self.assertHTMLEqual(expected, Template(template).render(Context()))
+
+    def test_with_classes_keyword(self):
+        template = """
+            {% load wagtailadmin_tags %}
+            {% icon "warning" classname="myclass" %}
+        """
+
+        expected = """
+            <svg aria-hidden="true" class="icon icon-warning myclass"><use href="#icon-warning"></svg>
+        """
+
+        self.assertHTMLEqual(expected, Template(template).render(Context()))
+
+    def test_with_classes_obsolete_keyword(self):
+        template = """
+            {% load wagtailadmin_tags %}
+            {% icon "doc-empty" class_name="myclass" %}
+        """
+
+        expected = """
+            <svg aria-hidden="true" class="icon icon-doc-empty myclass"><use href="#icon-doc-empty"></svg>
+        """
+
+        with self.assertWarnsMessage(
+            RemovedInWagtail50Warning,
+            (
+                "Icon template tag `class_name` has been renamed to `classname`, "
+                "please adopt the new usage instead. Replace "
+                '`{% icon ... class_name="myclass" %}` with '
+                '`{% icon ... classname="myclass" %}`'
+            ),
+        ):
+            self.assertHTMLEqual(expected, Template(template).render(Context()))

Tests failing on latest `main`
<!--
Found a bug? Please fill out the sections below. 👍
-->

### Issue Summary

Some tests for the ~~legacy~~ moderation feature seems to be failing on latest `main` after #9817. Weirdly, they passed when the CI was run on the PR: https://github.com/wagtail/wagtail/actions/runs/3956994621

Will investigate later today.

<!--
A summary of the issue.
-->

### Steps to Reproduce

1. (for example) Start a new project with `wagtail start myproject`
2. Edit models.py as follows...
3. ...

Any other relevant information. For example, why do you consider this a bug and what did you expect to happen instead?

-   I have confirmed that this issue can be reproduced as described on a fresh Wagtail project: (yes / no)

### Technical details

-   Python version: Run `python --version`.
-   Django version: Look in your requirements.txt, or run `pip show django | grep Version`.
-   Wagtail version: Look at the bottom of the Settings menu in the Wagtail admin, or run `pip show wagtail | grep Version:`.
-   Browser version: You can use https://www.whatsmybrowser.org/ to find this out.

wagtail/admin/tests/test_templatetags.py::IconTagTest::test_with_classes_obsolete_keyword
wagtail/admin/tests/test_templatetags.py::TestNotificationStaticTemplateTag::test_local_notification_static wagtail/admin/tests/test_templatetags.py::TestNotificationStaticTemplateTag::test_local_notification_static_baseurl wagtail/admin/tests/test_templatetags.py::TestNotificationStaticTemplateTag::test_remote_notification_static wagtail/admin/tests/test_templatetags.py::TestVersionedStatic::test_versioned_static wagtail/admin/tests/test_templatetags.py::TestVersionedStatic::test_versioned_static_absolute_path wagtail/admin/tests/test_templatetags.py::TestVersionedStatic::test_versioned_static_url wagtail/admin/tests/test_templatetags.py::TestVersionedStatic::test_versioned_static_version_string wagtail/admin/tests/test_templatetags.py::TestTimesinceTags::test_human_readable_date wagtail/admin/tests/test_templatetags.py::TestTimesinceTags::test_timesince_last_update_before_today_shows_timeago wagtail/admin/tests/test_templatetags.py::TestTimesinceTags::test_timesince_last_update_today_shows_time wagtail/admin/tests/test_templatetags.py::TestTimesinceTags::test_timesince_simple wagtail/admin/tests/test_templatetags.py::TestComponentTag::test_component_escapes_unsafe_strings wagtail/admin/tests/test_templatetags.py::TestComponentTag::test_error_on_rendering_non_component wagtail/admin/tests/test_templatetags.py::TestComponentTag::test_passing_context_to_component wagtail/admin/tests/test_templatetags.py::ComponentTest::test_kwargs_with_filters wagtail/admin/tests/test_templatetags.py::ComponentTest::test_render_as_variable wagtail/admin/tests/test_templatetags.py::ComponentTest::test_render_block_component wagtail/admin/tests/test_templatetags.py::ComponentTest::test_render_nested wagtail/admin/tests/test_templatetags.py::FragmentTagTest::test_basic wagtail/admin/tests/test_templatetags.py::FragmentTagTest::test_syntax_error wagtail/admin/tests/test_templatetags.py::FragmentTagTest::test_with_variables wagtail/admin/tests/test_templatetags.py::ClassnamesTagTest::test_with_args_with_extra_whitespace wagtail/admin/tests/test_templatetags.py::ClassnamesTagTest::test_with_falsy_args wagtail/admin/tests/test_templatetags.py::ClassnamesTagTest::test_with_multiple_args wagtail/admin/tests/test_templatetags.py::ClassnamesTagTest::test_with_single_arg wagtail/admin/tests/test_templatetags.py::IconTagTest::test_basic wagtail/admin/tests/test_templatetags.py::IconTagTest::test_with_classes_keyword wagtail/admin/tests/test_templatetags.py::IconTagTest::test_with_classes_positional