Title: [276680] trunk
Revision
276680
Author
pan...@apple.com
Date
2021-04-27 16:53:42 -0700 (Tue, 27 Apr 2021)

Log Message

Web Inspector: Default Audits script are minified in release builds
https://bugs.webkit.org/show_bug.cgi?id=225009

Reviewed by BJ Burg.

Source/WebInspectorUI:

Covered by new test:
- inspector/audit/non-minified-default-audits.html

The default audits have been moved out of `AuditManager.js` and into a special `DefaultAudits.js` in the new
`NonMinified` directory, which contains _javascript_ sources that should be included in `Main.js` and
`TestCombined.js`, but should not have whitespace stripped from their contents because the whitespace is
important to the script. For example, the source for the default audits are visible to the user, and therefore
we want to present well-formatted source in those contexts.

* Scripts/combine-resources.pl:
- Added `NonMinified` directory to list of default `inputDirectoryPattern` exceptions for combining resources.
- Added `--skip-concatenate-tag` so that we don't add tags for script we will eventually append to another script.
* Scripts/copy-user-interface-resources.pl:
- Handle `NonMinified` directory for sources that will be appended to Main.js, but should not be minified.
- Handle `NonMinified` directory for sources that will be appended to TestCombined.js.
(combineOrStripResourcesForWebKitAdditions):
- Drive-by fix for typo in combineOrStripResourcesForWebKitAdditions that caused errors to be emitted during builds.
* UserInterface/Controllers/AuditManager.js:
(WI.AuditManager.prototype._addDefaultTests):
(WI.AuditManager):
(WI.AuditManager.prototype._addDefaultTests.const.levelPass): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.levelWarn): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.levelFail): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.levelError): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.levelUnsupported): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.dataDOMNodes): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.dataDOMAttributes): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.dataErrors): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.dataCustom): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getElementsByComputedRole): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getActiveDescendant): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getChildNodes): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getComputedProperties): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getControlledNodes): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getFlowedNodes): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getMouseEventNode): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getOwnedNodes): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getParentNode): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getSelectedChildNodes): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.hasEventListeners): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.hasEventListenersClick): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getResources): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.getResourceContent): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.unsupported): Deleted.
(WI.AuditManager.prototype._addDefaultTests.hasChildWithRole): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testMenuRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testGridRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testForAriaLabelledBySpelling): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testForMultipleBanners): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testForLinkLabels): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testRowGroupRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testTableRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testForMultipleLiveRegions): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testListBoxRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testImageLabels): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testForAriaHiddenFalse): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testTreeRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testRadioGroupRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testFeedRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testTabListRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testButtonLabels): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testRowRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testListRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testComboBoxRoleForRequiredChildren): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testForMultipleMainContentSections): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testDialogsForLabels): Deleted.
(WI.AuditManager.prototype._addDefaultTests.const.testForInvalidAriaHiddenValue): Deleted.
(WI.AuditManager.prototype._addDefaultTests.removeWhitespace): Deleted.
* UserInterface/Main.html:
* UserInterface/NonMinified/DefaultAudits.js: Added.
(WI.DefaultAudits.levelPass):
(WI.DefaultAudits.levelWarn):
(WI.DefaultAudits.levelFail):
(WI.DefaultAudits.levelError):
(WI.DefaultAudits.levelUnsupported):
(WI.DefaultAudits.dataDOMNodes):
(WI.DefaultAudits.dataDOMAttributes):
(WI.DefaultAudits.dataErrors):
(WI.DefaultAudits.dataCustom):
(WI.DefaultAudits.getElementsByComputedRole):
(WI.DefaultAudits.getActiveDescendant):
(WI.DefaultAudits.getChildNodes):
(WI.DefaultAudits.getComputedProperties):
(WI.DefaultAudits.getControlledNodes):
(WI.DefaultAudits.getFlowedNodes):
(WI.DefaultAudits.getMouseEventNode):
(WI.DefaultAudits.getOwnedNodes):
(WI.DefaultAudits.getParentNode):
(WI.DefaultAudits.getSelectedChildNodes):
(WI.DefaultAudits.hasEventListeners):
(WI.DefaultAudits.hasEventListenersClick):
(WI.DefaultAudits.getResources):
(WI.DefaultAudits.getResourceContent):
(WI.DefaultAudits.unsupported):
(hasChildWithRole):
(WI.DefaultAudits.testMenuRoleForRequiredChildren):
(WI.DefaultAudits.testGridRoleForRequiredChildren):
(WI.DefaultAudits.testForAriaLabelledBySpelling):
(WI.DefaultAudits.testForMultipleBanners):
(WI.DefaultAudits.testForLinkLabels):
(WI.DefaultAudits.testRowGroupRoleForRequiredChildren):
(WI.DefaultAudits.testTableRoleForRequiredChildren):
(WI.DefaultAudits.testForMultipleLiveRegions):
(WI.DefaultAudits.testListBoxRoleForRequiredChildren):
(WI.DefaultAudits.testImageLabels):
(WI.DefaultAudits.testForAriaHiddenFalse):
(WI.DefaultAudits.testTreeRoleForRequiredChildren):
(WI.DefaultAudits.testRadioGroupRoleForRequiredChildren):
(WI.DefaultAudits.testFeedRoleForRequiredChildren):
(WI.DefaultAudits.testTabListRoleForRequiredChildren):
(WI.DefaultAudits.testButtonLabels):
(WI.DefaultAudits.testRowRoleForRequiredChildren):
(WI.DefaultAudits.testListRoleForRequiredChildren):
(WI.DefaultAudits.testComboBoxRoleForRequiredChildren):
(WI.DefaultAudits.testForMultipleMainContentSections):
(WI.DefaultAudits.testDialogsForLabels):
(WI.DefaultAudits.testForInvalidAriaHiddenValue):
* UserInterface/Test.html:

LayoutTests:

Added test to check that whitespace is preserved in default audits.

* inspector/audit/non-minified-default-audits-expected.txt: Added.
* inspector/audit/non-minified-default-audits.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (276679 => 276680)


--- trunk/LayoutTests/ChangeLog	2021-04-27 23:40:17 UTC (rev 276679)
+++ trunk/LayoutTests/ChangeLog	2021-04-27 23:53:42 UTC (rev 276680)
@@ -1,3 +1,15 @@
+2021-04-27  Patrick Angle  <pan...@apple.com>
+
+        Web Inspector: Default Audits script are minified in release builds
+        https://bugs.webkit.org/show_bug.cgi?id=225009
+
+        Reviewed by BJ Burg.
+
+        Added test to check that whitespace is preserved in default audits.
+
+        * inspector/audit/non-minified-default-audits-expected.txt: Added.
+        * inspector/audit/non-minified-default-audits.html: Added.
+
 2021-04-27  Alex Christensen  <achristen...@webkit.org>
 
         charset in contentType used in Blob.prototype.slice(start, end, contentType) is lost

Added: trunk/LayoutTests/inspector/audit/non-minified-default-audits-expected.txt (0 => 276680)


--- trunk/LayoutTests/inspector/audit/non-minified-default-audits-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/audit/non-minified-default-audits-expected.txt	2021-04-27 23:53:42 UTC (rev 276680)
@@ -0,0 +1,8 @@
+Tests to make sure that default audits are not minified.
+
+
+== Running test suite: Audit.NonMinifiedDefaultAudits
+-- Running test case: Audit.NonMinifiedDefaultAudits.IndentationPreserved
+PASS: Expect that default audits source is present.
+PASS: Expect that the testPass test case has correct number of spaces and indentation.
+

Added: trunk/LayoutTests/inspector/audit/non-minified-default-audits.html (0 => 276680)


--- trunk/LayoutTests/inspector/audit/non-minified-default-audits.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/audit/non-minified-default-audits.html	2021-04-27 23:53:42 UTC (rev 276680)
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("Audit.NonMinifiedDefaultAudits");
+
+    suite.addTestCase({
+        name: "Audit.NonMinifiedDefaultAudits.IndentationPreserved",
+        description: "Ensure that indentation is preserved in default audit function source.",
+        async test() {
+            InspectorTest.expectTrue(WI.DefaultAudits, "Expect that default audits source is present.");
+
+            const expectedLevelPassString = `function () {\n    return {level: "pass"};\n}`;
+            InspectorTest.expectEqual(WI.DefaultAudits.levelPass.toString(), expectedLevelPassString, "Expect that the testPass test case has correct number of spaces and indentation.");
+        },
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+    <p>Tests to make sure that default audits are not minified.</p>
+</body>
+</html>

Modified: trunk/Source/WebInspectorUI/ChangeLog (276679 => 276680)


--- trunk/Source/WebInspectorUI/ChangeLog	2021-04-27 23:40:17 UTC (rev 276679)
+++ trunk/Source/WebInspectorUI/ChangeLog	2021-04-27 23:53:42 UTC (rev 276680)
@@ -1,3 +1,129 @@
+2021-04-27  Patrick Angle  <pan...@apple.com>
+
+        Web Inspector: Default Audits script are minified in release builds
+        https://bugs.webkit.org/show_bug.cgi?id=225009
+
+        Reviewed by BJ Burg.
+
+        Covered by new test:
+        - inspector/audit/non-minified-default-audits.html
+
+        The default audits have been moved out of `AuditManager.js` and into a special `DefaultAudits.js` in the new
+        `NonMinified` directory, which contains _javascript_ sources that should be included in `Main.js` and
+        `TestCombined.js`, but should not have whitespace stripped from their contents because the whitespace is
+        important to the script. For example, the source for the default audits are visible to the user, and therefore
+        we want to present well-formatted source in those contexts.
+
+        * Scripts/combine-resources.pl:
+        - Added `NonMinified` directory to list of default `inputDirectoryPattern` exceptions for combining resources.
+        - Added `--skip-concatenate-tag` so that we don't add tags for script we will eventually append to another script.
+        * Scripts/copy-user-interface-resources.pl:
+        - Handle `NonMinified` directory for sources that will be appended to Main.js, but should not be minified.
+        - Handle `NonMinified` directory for sources that will be appended to TestCombined.js.
+        (combineOrStripResourcesForWebKitAdditions):
+        - Drive-by fix for typo in combineOrStripResourcesForWebKitAdditions that caused errors to be emitted during builds.
+        * UserInterface/Controllers/AuditManager.js:
+        (WI.AuditManager.prototype._addDefaultTests):
+        (WI.AuditManager):
+        (WI.AuditManager.prototype._addDefaultTests.const.levelPass): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.levelWarn): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.levelFail): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.levelError): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.levelUnsupported): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.dataDOMNodes): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.dataDOMAttributes): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.dataErrors): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.dataCustom): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getElementsByComputedRole): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getActiveDescendant): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getChildNodes): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getComputedProperties): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getControlledNodes): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getFlowedNodes): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getMouseEventNode): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getOwnedNodes): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getParentNode): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getSelectedChildNodes): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.hasEventListeners): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.hasEventListenersClick): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getResources): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.getResourceContent): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.unsupported): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.hasChildWithRole): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testMenuRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testGridRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testForAriaLabelledBySpelling): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testForMultipleBanners): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testForLinkLabels): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testRowGroupRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testTableRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testForMultipleLiveRegions): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testListBoxRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testImageLabels): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testForAriaHiddenFalse): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testTreeRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testRadioGroupRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testFeedRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testTabListRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testButtonLabels): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testRowRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testListRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testComboBoxRoleForRequiredChildren): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testForMultipleMainContentSections): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testDialogsForLabels): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.const.testForInvalidAriaHiddenValue): Deleted.
+        (WI.AuditManager.prototype._addDefaultTests.removeWhitespace): Deleted.
+        * UserInterface/Main.html:
+        * UserInterface/NonMinified/DefaultAudits.js: Added.
+        (WI.DefaultAudits.levelPass):
+        (WI.DefaultAudits.levelWarn):
+        (WI.DefaultAudits.levelFail):
+        (WI.DefaultAudits.levelError):
+        (WI.DefaultAudits.levelUnsupported):
+        (WI.DefaultAudits.dataDOMNodes):
+        (WI.DefaultAudits.dataDOMAttributes):
+        (WI.DefaultAudits.dataErrors):
+        (WI.DefaultAudits.dataCustom):
+        (WI.DefaultAudits.getElementsByComputedRole):
+        (WI.DefaultAudits.getActiveDescendant):
+        (WI.DefaultAudits.getChildNodes):
+        (WI.DefaultAudits.getComputedProperties):
+        (WI.DefaultAudits.getControlledNodes):
+        (WI.DefaultAudits.getFlowedNodes):
+        (WI.DefaultAudits.getMouseEventNode):
+        (WI.DefaultAudits.getOwnedNodes):
+        (WI.DefaultAudits.getParentNode):
+        (WI.DefaultAudits.getSelectedChildNodes):
+        (WI.DefaultAudits.hasEventListeners):
+        (WI.DefaultAudits.hasEventListenersClick):
+        (WI.DefaultAudits.getResources):
+        (WI.DefaultAudits.getResourceContent):
+        (WI.DefaultAudits.unsupported):
+        (hasChildWithRole):
+        (WI.DefaultAudits.testMenuRoleForRequiredChildren):
+        (WI.DefaultAudits.testGridRoleForRequiredChildren):
+        (WI.DefaultAudits.testForAriaLabelledBySpelling):
+        (WI.DefaultAudits.testForMultipleBanners):
+        (WI.DefaultAudits.testForLinkLabels):
+        (WI.DefaultAudits.testRowGroupRoleForRequiredChildren):
+        (WI.DefaultAudits.testTableRoleForRequiredChildren):
+        (WI.DefaultAudits.testForMultipleLiveRegions):
+        (WI.DefaultAudits.testListBoxRoleForRequiredChildren):
+        (WI.DefaultAudits.testImageLabels):
+        (WI.DefaultAudits.testForAriaHiddenFalse):
+        (WI.DefaultAudits.testTreeRoleForRequiredChildren):
+        (WI.DefaultAudits.testRadioGroupRoleForRequiredChildren):
+        (WI.DefaultAudits.testFeedRoleForRequiredChildren):
+        (WI.DefaultAudits.testTabListRoleForRequiredChildren):
+        (WI.DefaultAudits.testButtonLabels):
+        (WI.DefaultAudits.testRowRoleForRequiredChildren):
+        (WI.DefaultAudits.testListRoleForRequiredChildren):
+        (WI.DefaultAudits.testComboBoxRoleForRequiredChildren):
+        (WI.DefaultAudits.testForMultipleMainContentSections):
+        (WI.DefaultAudits.testDialogsForLabels):
+        (WI.DefaultAudits.testForInvalidAriaHiddenValue):
+        * UserInterface/Test.html:
+
 2021-04-27  Don Olmstead  <don.olmst...@sony.com>
 
         [CMake] Don't use FORWARDING_HEADERS_DIR for GTK WebKit headers

Modified: trunk/Source/WebInspectorUI/Scripts/combine-resources.pl (276679 => 276680)


--- trunk/Source/WebInspectorUI/Scripts/combine-resources.pl	2021-04-27 23:40:17 UTC (rev 276679)
+++ trunk/Source/WebInspectorUI/Scripts/combine-resources.pl	2021-04-27 23:53:42 UTC (rev 276680)
@@ -1,6 +1,6 @@
 #!/usr/bin/env perl
 
-# Copyright (C) 2015-2018 Apple Inc. All rights reserved.
+# Copyright (C) 2015-2021 Apple Inc. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -38,6 +38,7 @@
 our $htmlFile;
 our $strip;
 our $verbose;
+our $skipConcatenateTag;
 
 GetOptions('output-dir=s' => \$outputDirectory,
            'output-script-name=s' => \$outputScriptName,
@@ -47,10 +48,11 @@
            'input-html-dir=s' => \$htmlDirectory,
            'input-html=s' => \$htmlFile,
            'verbose' => \$verbose,
-           'strip' => \$strip);
+           'strip' => \$strip,
+           'skip-concatenate-tag' => \$skipConcatenateTag);
 
 unless (defined $htmlFile and defined $derivedSourcesDirectory and defined $outputDirectory and (defined $strip or defined $outputScriptName or defined $outputStylesheetName)) {
-    print "Usage: $0 --input-html <path> --derived-sources-dir <path> --output-dir <path> [--output-script-name <name>] [--output-style-name <name>] [--strip]\n";
+    print "Usage: $0 --input-html <path> --derived-sources-dir <path> --output-dir <path> [--output-script-name <name>] [--output-style-name <name>] [--strip] [--skip-concatenate-tag]\n";
     exit;
 }
 
@@ -118,7 +120,7 @@
     $headContents =~ s/$whitespaceConsumingTagPattern//gi;
 }
 
-my $inputDirectoryPattern = "(?!WebKitAdditions\/)(?!External\/)(?!Workers\/)[^\"]*";
+my $inputDirectoryPattern = "(?!WebKitAdditions\/)(?!External\/)(?!Workers\/)(?!NonMinified\/)[^\"]*";
 $inputDirectoryPattern = $inputDirectory . "\/[^\"]*" if $inputDirectory;
 
 if (defined($strip)) {
@@ -125,8 +127,8 @@
     stripIncludedFilesMatchingPattern("<link rel=\"stylesheet\" href=""
     stripIncludedFilesMatchingPattern("<script src=""
 } else {
-    concatenateIncludedFilesMatchingPattern($outputStylesheetName, "<link rel=\"stylesheet\" href="" "<link rel=\"stylesheet\" href="" if defined $outputStylesheetName;
-    concatenateIncludedFilesMatchingPattern($outputScriptName, "<script src="" "<script src="" if defined $outputScriptName;
+    concatenateIncludedFilesMatchingPattern($outputStylesheetName, "<link rel=\"stylesheet\" href="" defined $skipConcatenateTag ? "" : "<link rel=\"stylesheet\" href="" if defined $outputStylesheetName;
+    concatenateIncludedFilesMatchingPattern($outputScriptName, "<script src="" defined $skipConcatenateTag ? "" : "<script src="" if defined $outputScriptName;
 }
 
 $htmlContents =~ s/<head>.*<\/head>/<head>$headContents<\/head>/si;

Modified: trunk/Source/WebInspectorUI/Scripts/copy-user-interface-resources.pl (276679 => 276680)


--- trunk/Source/WebInspectorUI/Scripts/copy-user-interface-resources.pl	2021-04-27 23:40:17 UTC (rev 276679)
+++ trunk/Source/WebInspectorUI/Scripts/copy-user-interface-resources.pl	2021-04-27 23:53:42 UTC (rev 276680)
@@ -1,6 +1,6 @@
 #!/usr/bin/env perl
 
-# Copyright (C) 2015-2018 Apple Inc. All rights reserved.
+# Copyright (C) 2015-2021 Apple Inc. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -112,7 +112,7 @@
 
 my $inspectorLicense = <<'EOF';
 /*
- * Copyright (C) 2007-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2021 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Matt Lilek. All rights reserved.
  * Copyright (C) 2008-2009 Anthony Ricaud <r...@webkit.org>
  * Copyright (C) 2009-2010 Joseph Pecoraro. All rights reserved.
@@ -238,7 +238,7 @@
         my $foundJSFile = 0;
         my $foundCSSFile = 0;
         foreach my $file (@files) {
-            my $path = File::Spec->catdir($$webInspectorUIAdditionsDir, $file);
+            my $path = File::Spec->catdir($webInspectorUIAdditionsDir, $file);
             next if -d $path;
             if ($file =~ /\.js$/) {
                 debugLog("Found a _javascript_ file to combine: $file");
@@ -346,6 +346,17 @@
        '--output-dir', $derivedSourcesDir,
        '--output-script-name', 'Three.js');
 
+    # Combine non-minified _javascript_ files in Production builds into a single file (NonMinified.js), which will be
+    # appended to Main.js after Main.js has been minified.
+    system($perl, $combineResourcesCmd,
+       '--input-dir', 'NonMinified',
+       '--input-html', $derivedSourcesMainHTML,
+       '--input-html-dir', $uiRoot,
+       '--derived-sources-dir', $derivedSourcesDir,
+       '--output-dir', $derivedSourcesDir,
+       '--output-script-name', 'NonMinified.js',
+       '--skip-concatenate-tag');
+
     # Remove console.assert calls from the Main.js file.
     my $derivedSourcesMainJS = File::Spec->catfile($derivedSourcesDir, 'Main.js');
     system($perl, File::Spec->catfile($scriptsRoot, 'remove-console-asserts.pl'),
@@ -352,6 +363,12 @@
         '--input-script', $derivedSourcesMainJS,
         '--output-script', $derivedSourcesMainJS);
 
+    # Remove console.assert calls from the NonMinified.js file.
+    my $derivedSourcesNonMinifiedJS = File::Spec->catfile($derivedSourcesDir, 'NonMinified.js');
+    system($perl, File::Spec->catfile($scriptsRoot, 'remove-console-asserts.pl'),
+        '--input-script', $derivedSourcesNonMinifiedJS,
+        '--output-script', $derivedSourcesNonMinifiedJS);
+
     # Fix Image URLs in the Main.css file by removing the "../".
     my $derivedSourcesMainCSS = File::Spec->catfile($derivedSourcesDir, 'Main.css');
     if (open(INPUT_MAIN, '<', $derivedSourcesMainCSS)) {
@@ -406,6 +423,9 @@
     my $derivedSourcesThreejsJS = File::Spec->catfile($derivedSourcesDir, 'Three.js');
     system(qq("$python" "$jsMinScript" < "$derivedSourcesThreejsJS" >> "$targetThreejsJS")) and die "Failed to minify $derivedSourcesThreejsJS: $!";
 
+    # Append non-minified _javascript_ to Main.js.
+    appendFile($targetMainJS, $derivedSourcesNonMinifiedJS);
+
     # Copy over the Images directory.
     ditto(File::Spec->catdir($uiRoot, 'Images'), File::Spec->catdir($targetResourcePath, 'Images'));
 
@@ -443,6 +463,19 @@
 
     my $derivedSourcesTestHTML = File::Spec->catfile($derivedSourcesDir, 'Test.html');
     my $derivedSourcesTestJS = File::Spec->catfile($derivedSourcesDir, 'TestCombined.js');
+
+    # Combine non-minified _javascript_ files in Production builds into the same TestCombined.js, because test files are not minified.
+    system($perl, $combineResourcesCmd,
+       '--input-dir', 'NonMinified',
+       '--input-html', $derivedSourcesTestHTML,
+       '--input-html-dir', $uiRoot,
+       '--derived-sources-dir', $derivedSourcesDir,
+       '--output-dir', $derivedSourcesDir,
+       '--output-script-name', 'NonMinifiedTestCombined.js',
+       '--skip-concatenate-tag');
+
+    my $derivedSourcesNonMinifiedTestJS = File::Spec->catfile($derivedSourcesDir, 'NonMinifiedTestCombined.js');
+
     # Combine the CodeMirror _javascript_ files into single file (TestCodeMirror.js).
     system($perl, $combineResourcesCmd,
         '--input-dir', 'External/CodeMirror',
@@ -476,6 +509,9 @@
     # Append TestCombined.js to the license that was exported above.
     appendFile($targetTestJS, $derivedSourcesTestJS);
 
+    # Append the non-minified sources to TestCombined.js.
+    appendFile($targetTestJS, $derivedSourcesNonMinifiedTestJS);
+
     # Append CodeMirror.js to the license that was exported above.
     my $derivedSourcesCodeMirrorJS = File::Spec->catfile($derivedSourcesDir, 'TestCodeMirror.js');
     appendFile($targetCodeMirrorJS, $derivedSourcesCodeMirrorJS);

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js (276679 => 276680)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js	2021-04-27 23:40:17 UTC (rev 276679)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js	2021-04-27 23:53:42 UTC (rev 276680)
@@ -341,728 +341,72 @@
 
     _addDefaultTests()
     {
-        const levelPass = function() {
-            return {level: "pass"};
-        };
+        console.assert(WI.DefaultAudits, "Default audits not loaded.");
+        if (!WI.DefaultAudits)
+            return;
 
-        const levelWarn = function() {
-            return {level: "warn"};
-        };
-
-        const levelFail = function() {
-            return {level: "fail"};
-        };
-
-        const levelError = function() {
-            return {level: "error"};
-        };
-
-        const levelUnsupported = function() {
-            return {level: "unsupported"};
-        };
-
-        const dataDOMNodes = function() {
-            return {level: "pass", domNodes: [document.body]};
-        };
-
-        const dataDOMAttributes = function() {
-            return {level: "pass", domNodes: Array.from(document.querySelectorAll("[id]")), domAttributes: ["id"]};
-        };
-
-        const dataErrors = function() {
-            throw Error("this error was thrown from inside the audit test code.");
-        };
-
-        const dataCustom = function() {
-            return {level: "pass", a: 1, b: [2], c: {key: 3}};
-        };
-
-        const getElementsByComputedRole = function() {
-            return {level: "pass", domNodes: WebInspectorAudit.Accessibility.getElementsByComputedRole("link"), domAttributes: ["role"]};
-        };
-
-        const getActiveDescendant = function() {
-            let result = {level: "pass"};
-            let activeDescendant = WebInspectorAudit.Accessibility.getActiveDescendant(document.body);
-            if (activeDescendant)
-                result.domNodes = [activeDescendant];
-            return result;
-        };
-
-        const getChildNodes = function() {
-            let childNodes = WebInspectorAudit.Accessibility.getChildNodes(document.body);
-            return {level: "pass", domNodes: childNodes || []};
-        };
-
-        const getComputedProperties = function() {
-            let domAttributes = ["alt", "aria-atomic", "aria-busy", "aria-checked", "aria-current", "aria-disabled", "aria-expanded", "aria-haspopup", "aria-hidden", "aria-invalid", "aria-label", "aria-labelledby", "aria-level", "aria-live", "aria-pressed", "aria-readonly", "aria-relevant", "aria-required", "aria-selected", "role", "title"].filter((attribute) => document.body.hasAttribute(attribute));
-            let computedProperties = WebInspectorAudit.Accessibility.getComputedProperties(document.body);
-            return {level: "pass", domNodes: [document.body], domAttributes, ...(computedProperties || {})};
-        };
-
-        const getControlledNodes = function() {
-            let controlledNodes = WebInspectorAudit.Accessibility.getControlledNodes(document.body);
-            return {level: "pass", domNodes: controlledNodes || []};
-        };
-
-        const getFlowedNodes = function() {
-            let flowedNodes = WebInspectorAudit.Accessibility.getFlowedNodes(document.body);
-            return {level: "pass", domNodes: flowedNodes || []};
-        };
-
-        const getMouseEventNode = function() {
-            let result = {level: "pass"};
-            let mouseEventNode = WebInspectorAudit.Accessibility.getMouseEventNode(document.body);
-            if (mouseEventNode)
-                result.domNodes = [mouseEventNode];
-            return result;
-        };
-
-        const getOwnedNodes = function() {
-            let ownedNodes = WebInspectorAudit.Accessibility.getOwnedNodes(document.body);
-            return {level: "pass", domNodes: ownedNodes || []};
-        };
-
-        const getParentNode = function() {
-            let result = {level: "pass"};
-            let parentNode = WebInspectorAudit.Accessibility.getParentNode(document.body);
-            if (parentNode)
-                result.domNodes = [parentNode];
-            return result;
-        };
-
-        const getSelectedChildNodes = function() {
-            let selectedChildNodes = WebInspectorAudit.Accessibility.getSelectedChildNodes(document.body);
-            return {level: "pass", domNodes: selectedChildNodes || []};
-        };
-
-        const hasEventListeners = function() {
-            let domAttributes = Array.from(document.body.attributes).filter((attribute) => attribute.name.startsWith("on"));
-            return {level: "pass", domNodes: [document.body], domAttributes, hasEventListeners: WebInspectorAudit.DOM.hasEventListeners(document.body)};
-        };
-
-        const hasEventListenersClick = function() {
-            let domAttributes = ["onclick"].filter((attribute) => document.body.hasAttribute(attribute));
-            return {level: "pass", domNodes: [document.body], domAttributes, hasClickEventListener: WebInspectorAudit.DOM.hasEventListeners(document.body, "click")};
-        };
-
-        const getResources = function() {
-            return {level: "pass", resources: WebInspectorAudit.Resources.getResources()};
-        };
-
-        const getResourceContent = function() {
-            let resources = WebInspectorAudit.Resources.getResources();
-            let mainResource = resources.find((resource) => resource.url ="" window.location.href);
-            return {level: "pass", mainResource, resourceContent: WebInspectorAudit.Resources.getResourceContent(mainResource.id)};
-        };
-
-        const unsupported = function() {
-            throw Error("this test should not be supported.");
-        };
-
-        const testMenuRoleForRequiredChildren = function() {
-            const relationships = {
-                menu: ["menuitem", "menuitemcheckbox", "menuitemradio"],
-                menubar: ["menuitem", "menuitemcheckbox", "menuitemradio"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testGridRoleForRequiredChildren = function() {
-            const relationships = {
-                grid: ["row", "rowgroup"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testForAriaLabelledBySpelling = function() {
-            let domNodes = Array.from(document.querySelectorAll("[aria-labeledby]"));
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-labeledby"]};
-        };
-
-        const testForMultipleBanners = function() {
-            let domNodes = [];
-            let banners = WebInspectorAudit.Accessibility.getElementsByComputedRole("banner");
-            if (banners.length > 1)
-                domNodes = banners;
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testForLinkLabels = function() {
-            let links = WebInspectorAudit.Accessibility.getElementsByComputedRole("link");
-            let domNodes = links.filter((link) => !WebInspectorAudit.Accessibility.getComputedProperties(link).label);
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-label", "aria-labelledby", "title"]};
-        };
-
-        const testRowGroupRoleForRequiredChildren = function() {
-            const relationships = {
-                rowgroup: ["row"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testTableRoleForRequiredChildren = function() {
-            const relationships = {
-                table: ["row", "rowgroup"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testForMultipleLiveRegions = function() {
-            const liveRegionRoles = ["alert", "log", "status", "marquee", "timer"];
-            let domNodes = [];
-            let liveRegions = liveRegionRoles.reduce((a, b) => {
-                return a.concat(WebInspectorAudit.Accessibility.getElementsByComputedRole(b));
-            }, []);
-            liveRegions = liveRegions.concat(Array.from(document.querySelectorAll(`[aria-live="polite"], [aria-live="assertive"]`)));
-            if (liveRegions.length > 1)
-                domNodes = liveRegions;
-            return {level: domNodes.length ? "warn" : "pass", domNodes, domAttributes: ["aria-live"]};
-        };
-
-        const testListBoxRoleForRequiredChildren = function() {
-            const relationships = {
-                listbox: ["option"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testImageLabels = function() {
-            let images = WebInspectorAudit.Accessibility.getElementsByComputedRole("img");
-            let domNodes = images.filter((image) => !WebInspectorAudit.Accessibility.getComputedProperties(image).label);
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-label", "aria-labelledby", "title", "alt"]};
-        };
-
-        const testForAriaHiddenFalse = function() {
-            let domNodes = Array.from(document.querySelectorAll(`[aria-hidden="false"]`));
-            return {level: domNodes.length ? "warn" : "pass", domNodes, domAttributes: ["aria-hidden"]};
-        };
-
-        const testTreeRoleForRequiredChildren = function() {
-            const relationships = {
-                tree: ["treeitem", "group"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testRadioGroupRoleForRequiredChildren = function() {
-            const relationships = {
-                radiogroup: ["radio"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testFeedRoleForRequiredChildren = function() {
-            const relationships = {
-                feed: ["article"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testTabListRoleForRequiredChildren = function() {
-            const relationships = {
-                tablist: ["tab"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testButtonLabels = function() {
-            let buttons = WebInspectorAudit.Accessibility.getElementsByComputedRole("button");
-            let domNodes = buttons.filter((button) => !WebInspectorAudit.Accessibility.getComputedProperties(button).label);
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-label", "aria-labelledby", "title"]};
-        };
-
-        const testRowRoleForRequiredChildren = function() {
-            const relationships = {
-                row: ["cell", "gridcell", "columnheader", "rowheader"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testListRoleForRequiredChildren = function() {
-            const relationships = {
-                list: ["listitem", "group"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "warn" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testComboBoxRoleForRequiredChildren = function() {
-            const relationships = {
-                combobox: ["textbox", "listbox", "tree", "grid", "dialog"],
-            };
-            let domNodes = [];
-            let visitedParents = new Set;
-            function hasChildWithRole(node, expectedRoles) {
-                let childNode = node;
-                if (!childNode)
-                    return false;
-
-                if (childNode.parentNode)
-                    visitedParents.add(childNode.parentNode);
-
-                while (childNode) {
-                    let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
-                    if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
-                        if (expectedRoles.includes(properties.role))
-                            return true;
-
-                        if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
-                            return true;
-                    }
-                    childNode = childNode.nextSibling;
-                }
-                return false;
-            }
-            for (let role in relationships) {
-                for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
-                    if (visitedParents.has(parentNode))
-                        continue;
-
-                    if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
-                        domNodes.push(parentNode);
-                }
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testForMultipleMainContentSections = function() {
-            let domNodes = [];
-            let mainContentElements = WebInspectorAudit.Accessibility.getElementsByComputedRole("main");
-            if (mainContentElements.length > 1) {
-                domNodes = mainContentElements;
-            }
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
-        };
-
-        const testDialogsForLabels = function() {
-          let dialogs = WebInspectorAudit.Accessibility.getElementsByComputedRole("dialog");
-          let domNodes = dialogs.filter((dialog) => !WebInspectorAudit.Accessibility.getComputedProperties(dialog).label);
-          return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-label", "aria-labelledby", "title"]};
-        };
-
-        const testForInvalidAriaHiddenValue = function() {
-            let domNodes = Array.from(document.querySelectorAll(`[aria-hidden]:not([aria-hidden="true"], [aria-hidden="false"])`));
-            return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-hidden"]};
-        };
-
-        function removeWhitespace(func) {
-            return WI.AuditTestCase.stringifyFunction(func, 8);
-        }
-
         const defaultTests = [
             new WI.AuditTestGroup(WI.UIString("Demo Audit"), [
                 new WI.AuditTestGroup(WI.UIString("Result Levels"), [
-                    new WI.AuditTestCase("level-pass", removeWhitespace(levelPass), {description: WI.UIString("This is what the result of a passing test with no data looks like.")}),
-                    new WI.AuditTestCase("level-warn", removeWhitespace(levelWarn), {description: WI.UIString("This is what the result of a warning test with no data looks like.")}),
-                    new WI.AuditTestCase("level-fail", removeWhitespace(levelFail), {description: WI.UIString("This is what the result of a failing test with no data looks like.")}),
-                    new WI.AuditTestCase("level-error", removeWhitespace(levelError), {description: WI.UIString("This is what the result of a test that threw an error with no data looks like.")}),
-                    new WI.AuditTestCase("level-unsupported", removeWhitespace(levelUnsupported), {description: WI.UIString("This is what the result of an unsupported test with no data looks like.")}),
+                    new WI.AuditTestCase("level-pass", WI.DefaultAudits.levelPass.toString(), {description: WI.UIString("This is what the result of a passing test with no data looks like.")}),
+                    new WI.AuditTestCase("level-warn", WI.DefaultAudits.levelWarn.toString(), {description: WI.UIString("This is what the result of a warning test with no data looks like.")}),
+                    new WI.AuditTestCase("level-fail", WI.DefaultAudits.levelFail.toString(), {description: WI.UIString("This is what the result of a failing test with no data looks like.")}),
+                    new WI.AuditTestCase("level-error", WI.DefaultAudits.levelError.toString(), {description: WI.UIString("This is what the result of a test that threw an error with no data looks like.")}),
+                    new WI.AuditTestCase("level-unsupported", WI.DefaultAudits.levelUnsupported.toString(), {description: WI.UIString("This is what the result of an unsupported test with no data looks like.")}),
                 ], {description: WI.UIString("These are all of the different test result levels.")}),
                 new WI.AuditTestGroup(WI.UIString("Result Data"), [
-                    new WI.AuditTestCase("data-domNodes", removeWhitespace(dataDOMNodes), {description: WI.UIString("This is an example of how result DOM nodes are shown. It will pass with the <body> element.")}),
-                    new WI.AuditTestCase("data-domAttributes", removeWhitespace(dataDOMAttributes), {description: WI.UIString("This is an example of how result DOM attributes are highlighted on any returned DOM nodes. It will pass with all elements with an id attribute.")}),
-                    new WI.AuditTestCase("data-errors", removeWhitespace(dataErrors), {description: WI.UIString("This is an example of how errors are shown. The error was thrown manually, but execution errors will appear in the same way.")}),
-                    new WI.AuditTestCase("data-custom", removeWhitespace(dataCustom), {description: WI.UIString("This is an example of how custom result data is shown."), supports: 3}),
+                    new WI.AuditTestCase("data-domNodes", WI.DefaultAudits.dataDOMNodes.toString(), {description: WI.UIString("This is an example of how result DOM nodes are shown. It will pass with the <body> element.")}),
+                    new WI.AuditTestCase("data-domAttributes", WI.DefaultAudits.dataDOMAttributes.toString(), {description: WI.UIString("This is an example of how result DOM attributes are highlighted on any returned DOM nodes. It will pass with all elements with an id attribute.")}),
+                    new WI.AuditTestCase("data-errors", WI.DefaultAudits.dataErrors.toString(), {description: WI.UIString("This is an example of how errors are shown. The error was thrown manually, but execution errors will appear in the same way.")}),
+                    new WI.AuditTestCase("data-custom", WI.DefaultAudits.dataCustom.toString(), {description: WI.UIString("This is an example of how custom result data is shown."), supports: 3}),
                 ], {description: WI.UIString("These are example tests that demonstrate all of the different types of data that can be returned with the test result.")}),
                 new WI.AuditTestGroup(WI.UIString("Specially Exposed Data"), [
                     new WI.AuditTestGroup(WI.UIString("Accessibility"), [
-                        new WI.AuditTestCase("getElementsByComputedRole", removeWhitespace(getElementsByComputedRole), {description: WI.UIString("This is an example test that uses %s to find elements with a computed role of \u0022link\u0022.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getElementsByComputedRole")), supports: 1}),
-                        new WI.AuditTestCase("getActiveDescendant", removeWhitespace(getActiveDescendant), {description: WI.UIString("This is an example test that uses %s to find any element that meets criteria for active descendant (\u0022%s\u0022) of the <body> element, if it exists.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getActiveDescendant"), WI.unlocalizedString("aria-activedescendant")), supports: 1}),
-                        new WI.AuditTestCase("getChildNodes", removeWhitespace(getChildNodes), {description: WI.UIString("This is an example test that uses %s to find child nodes of the <body> element in the accessibility tree.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getChildNodes")), supports: 1}),
-                        new WI.AuditTestCase("getComputedProperties", removeWhitespace(getComputedProperties), {description: WI.UIString("This is an example test that uses %s to find a variety of accessibility information about the <body> element.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getComputedProperties")), supports: 3}),
-                        new WI.AuditTestCase("getControlledNodes", removeWhitespace(getControlledNodes), {description: WI.UIString("This is an example test that uses %s to find all nodes controlled (\u0022%s\u0022) by the <body> element, if any exist.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getControlledNodes"), WI.unlocalizedString("aria-controls")), supports: 1}),
-                        new WI.AuditTestCase("getFlowedNodes", removeWhitespace(getFlowedNodes), {description: WI.UIString("This is an example test that uses %s to find all nodes flowed to (\u0022%s\u0022) from the <body> element, if any exist.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getFlowedNodes"), WI.unlocalizedString("aria-flowto")), supports: 1}),
-                        new WI.AuditTestCase("getMouseEventNode", removeWhitespace(getMouseEventNode), {description: WI.UIString("This is an example test that uses %s to find the node that would handle mouse events for the <body> element, if applicable.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getMouseEventNode")), supports: 1}),
-                        new WI.AuditTestCase("getOwnedNodes", removeWhitespace(getOwnedNodes), {description: WI.UIString("This is an example test that uses %s to find all nodes owned (\u0022%s\u0022) by the <body> element, if any exist.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getOwnedNodes"), WI.unlocalizedString("aria-owns")), supports: 1}),
-                        new WI.AuditTestCase("getParentNode", removeWhitespace(getParentNode), {description: WI.UIString("This is an example test that uses %s to find the parent node of the <body> element in the accessibility tree.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getParentNode")), supports: 1}),
-                        new WI.AuditTestCase("getSelectedChildNodes", removeWhitespace(getSelectedChildNodes), {description: WI.UIString("This is an example test that uses %s to find all child nodes that are selected (\u0022%s\u0022) of the <body> element in the accessibility tree.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getSelectedChildNodes"), WI.unlocalizedString("aria-selected")), supports: 1}),
+                        new WI.AuditTestCase("getElementsByComputedRole", WI.DefaultAudits.getElementsByComputedRole.toString(), {description: WI.UIString("This is an example test that uses %s to find elements with a computed role of \u0022link\u0022.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getElementsByComputedRole")), supports: 1}),
+                        new WI.AuditTestCase("getActiveDescendant", WI.DefaultAudits.getActiveDescendant.toString(), {description: WI.UIString("This is an example test that uses %s to find any element that meets criteria for active descendant (\u0022%s\u0022) of the <body> element, if it exists.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getActiveDescendant"), WI.unlocalizedString("aria-activedescendant")), supports: 1}),
+                        new WI.AuditTestCase("getChildNodes", WI.DefaultAudits.getChildNodes.toString(), {description: WI.UIString("This is an example test that uses %s to find child nodes of the <body> element in the accessibility tree.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getChildNodes")), supports: 1}),
+                        new WI.AuditTestCase("getComputedProperties", WI.DefaultAudits.getComputedProperties.toString(), {description: WI.UIString("This is an example test that uses %s to find a variety of accessibility information about the <body> element.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getComputedProperties")), supports: 3}),
+                        new WI.AuditTestCase("getControlledNodes", WI.DefaultAudits.getControlledNodes.toString(), {description: WI.UIString("This is an example test that uses %s to find all nodes controlled (\u0022%s\u0022) by the <body> element, if any exist.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getControlledNodes"), WI.unlocalizedString("aria-controls")), supports: 1}),
+                        new WI.AuditTestCase("getFlowedNodes", WI.DefaultAudits.getFlowedNodes.toString(), {description: WI.UIString("This is an example test that uses %s to find all nodes flowed to (\u0022%s\u0022) from the <body> element, if any exist.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getFlowedNodes"), WI.unlocalizedString("aria-flowto")), supports: 1}),
+                        new WI.AuditTestCase("getMouseEventNode", WI.DefaultAudits.getMouseEventNode.toString(), {description: WI.UIString("This is an example test that uses %s to find the node that would handle mouse events for the <body> element, if applicable.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getMouseEventNode")), supports: 1}),
+                        new WI.AuditTestCase("getOwnedNodes", WI.DefaultAudits.getOwnedNodes.toString(), {description: WI.UIString("This is an example test that uses %s to find all nodes owned (\u0022%s\u0022) by the <body> element, if any exist.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getOwnedNodes"), WI.unlocalizedString("aria-owns")), supports: 1}),
+                        new WI.AuditTestCase("getParentNode", WI.DefaultAudits.getParentNode.toString(), {description: WI.UIString("This is an example test that uses %s to find the parent node of the <body> element in the accessibility tree.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getParentNode")), supports: 1}),
+                        new WI.AuditTestCase("getSelectedChildNodes", WI.DefaultAudits.getSelectedChildNodes.toString(), {description: WI.UIString("This is an example test that uses %s to find all child nodes that are selected (\u0022%s\u0022) of the <body> element in the accessibility tree.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getSelectedChildNodes"), WI.unlocalizedString("aria-selected")), supports: 1}),
                     ], {description: WI.UIString("These are example tests that demonstrate how to use %s to get information about the accessibility tree.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility")), supports: 1}),
                     new WI.AuditTestGroup(WI.UIString("DOM"), [
-                        new WI.AuditTestCase("hasEventListeners", removeWhitespace(hasEventListeners), {description: WI.UIString("This is an example test that uses %s to find data indicating whether the <body> element has any event listeners.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.hasEventListeners")), supports: 3}),
-                        new WI.AuditTestCase("hasEventListeners-click", removeWhitespace(hasEventListenersClick), {description: WI.UIString("This is an example test that uses %s to find data indicating whether the <body> element has any click event listeners.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.hasEventListenersClick")), supports: 3}),
+                        new WI.AuditTestCase("hasEventListeners", WI.DefaultAudits.hasEventListeners.toString(), {description: WI.UIString("This is an example test that uses %s to find data indicating whether the <body> element has any event listeners.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.hasEventListeners")), supports: 3}),
+                        new WI.AuditTestCase("hasEventListeners-click", WI.DefaultAudits.hasEventListenersClick.toString(), {description: WI.UIString("This is an example test that uses %s to find data indicating whether the <body> element has any click event listeners.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.hasEventListenersClick")), supports: 3}),
                     ], {description: WI.UIString("These are example tests that demonstrate how to use %s to get information about DOM nodes.").format(WI.unlocalizedString("WebInspectorAudit.DOM")), supports: 1}),
                     new WI.AuditTestGroup(WI.UIString("Resources"), [
-                        new WI.AuditTestCase("getResources", removeWhitespace(getResources), {description: WI.UIString("This is an example test that uses %s to find basic information about each resource.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getResources")), supports: 3}),
-                        new WI.AuditTestCase("getResourceContent", removeWhitespace(getResourceContent), {description: WI.UIString("This is an example test that uses %s to find the contents of the main resource.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getResourceContent")), supports: 3}),
+                        new WI.AuditTestCase("getResources", WI.DefaultAudits.getResources.toString(), {description: WI.UIString("This is an example test that uses %s to find basic information about each resource.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getResources")), supports: 3}),
+                        new WI.AuditTestCase("getResourceContent", WI.DefaultAudits.getResourceContent.toString(), {description: WI.UIString("This is an example test that uses %s to find the contents of the main resource.").format(WI.unlocalizedString("WebInspectorAudit.Accessibility.getResourceContent")), supports: 3}),
                     ], {description: WI.UIString("These are example tests that demonstrate how to use %s to get information about loaded resources.").format(WI.unlocalizedString("WebInspectorAudit.Resources")), supports: 2}),
                 ], {description: WI.UIString("These are example tests that demonstrate how to use %s to access information not normally available to _javascript_.").format(WI.unlocalizedString("WebInspectorAudit")), supports: 1}),
-                new WI.AuditTestCase("unsupported", removeWhitespace(unsupported), {description: WI.UIString("This is an example of a test that will not run because it is unsupported."), supports: Infinity}),
+                new WI.AuditTestCase("unsupported", WI.DefaultAudits.unsupported.toString(), {description: WI.UIString("This is an example of a test that will not run because it is unsupported."), supports: Infinity}),
             ], {description: WI.UIString("These are example tests that demonstrate the functionality and structure of audits.")}),
             new WI.AuditTestGroup(WI.UIString("Accessibility"), [
-                new WI.AuditTestCase("testMenuRoleForRequiredChildren", removeWhitespace(testMenuRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 and \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("menu"), WI.unlocalizedString("menubar")), supports: 1}),
-                new WI.AuditTestCase("testGridRoleForRequiredChildren", removeWhitespace(testGridRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("grid")), supports: 1}),
-                new WI.AuditTestCase("testForAriaLabelledBySpelling", removeWhitespace(testForAriaLabelledBySpelling), {description: WI.UIString("Ensure that \u0022%s\u0022 is spelled correctly.").format(WI.unlocalizedString("aria-labelledby")), supports: 1}),
-                new WI.AuditTestCase("testForMultipleBanners", removeWhitespace(testForMultipleBanners), {description: WI.UIString("Ensure that only one banner is used on the page."), supports: 1}),
-                new WI.AuditTestCase("testForLinkLabels", removeWhitespace(testForLinkLabels), {description: WI.UIString("Ensure that links have accessible labels for assistive technology."), supports: 1}),
-                new WI.AuditTestCase("testRowGroupRoleForRequiredChildren", removeWhitespace(testRowGroupRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("rowgroup")), supports: 1}),
-                new WI.AuditTestCase("testTableRoleForRequiredChildren", removeWhitespace(testTableRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("table")), supports: 1}),
-                new WI.AuditTestCase("testForMultipleLiveRegions", removeWhitespace(testForMultipleLiveRegions), {description: WI.UIString("Ensure that only one live region is used on the page."), supports: 1}),
-                new WI.AuditTestCase("testListBoxRoleForRequiredChildren", removeWhitespace(testListBoxRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("listbox")), supports: 1}),
-                new WI.AuditTestCase("testImageLabels", removeWhitespace(testImageLabels), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have accessible labels for assistive technology.").format(WI.unlocalizedString("img")), supports: 1}),
-                new WI.AuditTestCase("testForAriaHiddenFalse", removeWhitespace(testForAriaHiddenFalse), {description: WI.UIString("Ensure aria-hidden=\u0022%s\u0022 is not used.").format(WI.unlocalizedString("false")), supports: 1}),
-                new WI.AuditTestCase("testTreeRoleForRequiredChildren", removeWhitespace(testTreeRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("tree")), supports: 1}),
-                new WI.AuditTestCase("testRadioGroupRoleForRequiredChildren", removeWhitespace(testRadioGroupRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("radiogroup")), supports: 1}),
-                new WI.AuditTestCase("testFeedRoleForRequiredChildren", removeWhitespace(testFeedRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("feed")), supports: 1}),
-                new WI.AuditTestCase("testTabListRoleForRequiredChildren", removeWhitespace(testTabListRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("tablist")), supports: 1}),
-                new WI.AuditTestCase("testButtonLabels", removeWhitespace(testButtonLabels), {description: WI.UIString("Ensure that buttons have accessible labels for assistive technology."), supports: 1}),
-                new WI.AuditTestCase("testRowRoleForRequiredChildren", removeWhitespace(testRowRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("row")), supports: 1}),
-                new WI.AuditTestCase("testListRoleForRequiredChildren", removeWhitespace(testListRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("list")), supports: 1}),
-                new WI.AuditTestCase("testComboBoxRoleForRequiredChildren", removeWhitespace(testComboBoxRoleForRequiredChildren), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("combobox")), supports: 1}),
-                new WI.AuditTestCase("testForMultipleMainContentSections", removeWhitespace(testForMultipleMainContentSections), {description: WI.UIString("Ensure that only one main content section is used on the page."), supports: 1}),
-                new WI.AuditTestCase("testDialogsForLabels", removeWhitespace(testDialogsForLabels), {description: WI.UIString("Ensure that dialogs have accessible labels for assistive technology."), supports: 1}),
-                new WI.AuditTestCase("testForInvalidAriaHiddenValue", removeWhitespace(testForInvalidAriaHiddenValue), {description: WI.UIString("Ensure that values for \u0022%s\u0022 are valid.").format(WI.unlocalizedString("aria-hidden")), supports: 1})
+                new WI.AuditTestCase("testMenuRoleForRequiredChildren", WI.DefaultAudits.testMenuRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 and \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("menu"), WI.unlocalizedString("menubar")), supports: 1}),
+                new WI.AuditTestCase("testGridRoleForRequiredChildren", WI.DefaultAudits.testGridRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("grid")), supports: 1}),
+                new WI.AuditTestCase("testForAriaLabelledBySpelling", WI.DefaultAudits.testForAriaLabelledBySpelling.toString(), {description: WI.UIString("Ensure that \u0022%s\u0022 is spelled correctly.").format(WI.unlocalizedString("aria-labelledby")), supports: 1}),
+                new WI.AuditTestCase("testForMultipleBanners", WI.DefaultAudits.testForMultipleBanners.toString(), {description: WI.UIString("Ensure that only one banner is used on the page."), supports: 1}),
+                new WI.AuditTestCase("testForLinkLabels", WI.DefaultAudits.testForLinkLabels.toString(), {description: WI.UIString("Ensure that links have accessible labels for assistive technology."), supports: 1}),
+                new WI.AuditTestCase("testRowGroupRoleForRequiredChildren", WI.DefaultAudits.testRowGroupRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("rowgroup")), supports: 1}),
+                new WI.AuditTestCase("testTableRoleForRequiredChildren", WI.DefaultAudits.testTableRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("table")), supports: 1}),
+                new WI.AuditTestCase("testForMultipleLiveRegions", WI.DefaultAudits.testForMultipleLiveRegions.toString(), {description: WI.UIString("Ensure that only one live region is used on the page."), supports: 1}),
+                new WI.AuditTestCase("testListBoxRoleForRequiredChildren", WI.DefaultAudits.testListBoxRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("listbox")), supports: 1}),
+                new WI.AuditTestCase("testImageLabels", WI.DefaultAudits.testImageLabels.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have accessible labels for assistive technology.").format(WI.unlocalizedString("img")), supports: 1}),
+                new WI.AuditTestCase("testForAriaHiddenFalse", WI.DefaultAudits.testForAriaHiddenFalse.toString(), {description: WI.UIString("Ensure aria-hidden=\u0022%s\u0022 is not used.").format(WI.unlocalizedString("false")), supports: 1}),
+                new WI.AuditTestCase("testTreeRoleForRequiredChildren", WI.DefaultAudits.testTreeRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("tree")), supports: 1}),
+                new WI.AuditTestCase("testRadioGroupRoleForRequiredChildren", WI.DefaultAudits.testRadioGroupRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("radiogroup")), supports: 1}),
+                new WI.AuditTestCase("testFeedRoleForRequiredChildren", WI.DefaultAudits.testFeedRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("feed")), supports: 1}),
+                new WI.AuditTestCase("testTabListRoleForRequiredChildren", WI.DefaultAudits.testTabListRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("tablist")), supports: 1}),
+                new WI.AuditTestCase("testButtonLabels", WI.DefaultAudits.testButtonLabels.toString(), {description: WI.UIString("Ensure that buttons have accessible labels for assistive technology."), supports: 1}),
+                new WI.AuditTestCase("testRowRoleForRequiredChildren", WI.DefaultAudits.testRowRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("row")), supports: 1}),
+                new WI.AuditTestCase("testListRoleForRequiredChildren", WI.DefaultAudits.testListRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("list")), supports: 1}),
+                new WI.AuditTestCase("testComboBoxRoleForRequiredChildren", WI.DefaultAudits.testComboBoxRoleForRequiredChildren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA.").format(WI.unlocalizedString("combobox")), supports: 1}),
+                new WI.AuditTestCase("testForMultipleMainContentSections", WI.DefaultAudits.testForMultipleMainContentSections.toString(), {description: WI.UIString("Ensure that only one main content section is used on the page."), supports: 1}),
+                new WI.AuditTestCase("testDialogsForLabels", WI.DefaultAudits.testDialogsForLabels.toString(), {description: WI.UIString("Ensure that dialogs have accessible labels for assistive technology."), supports: 1}),
+                new WI.AuditTestCase("testForInvalidAriaHiddenValue", WI.DefaultAudits.testForInvalidAriaHiddenValue.toString(), {description: WI.UIString("Ensure that values for \u0022%s\u0022 are valid.").format(WI.unlocalizedString("aria-hidden")), supports: 1})
             ], {description: WI.UIString("Diagnoses common accessibility problems affecting screen readers and other assistive technology.")}),
         ];
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (276679 => 276680)


--- trunk/Source/WebInspectorUI/UserInterface/Main.html	2021-04-27 23:40:17 UTC (rev 276679)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html	2021-04-27 23:53:42 UTC (rev 276680)
@@ -941,6 +941,8 @@
     <script src=""
     <script src=""
 
+    <script src=""
+
     <script src=""
 
     <script>

Added: trunk/Source/WebInspectorUI/UserInterface/NonMinified/DefaultAudits.js (0 => 276680)


--- trunk/Source/WebInspectorUI/UserInterface/NonMinified/DefaultAudits.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/NonMinified/DefaultAudits.js	2021-04-27 23:53:42 UTC (rev 276680)
@@ -0,0 +1,681 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WI.DefaultAudits = {};
+
+WI.DefaultAudits.levelPass = function() {
+    return {level: "pass"};
+};
+
+WI.DefaultAudits.levelWarn = function() {
+    return {level: "warn"};
+};
+
+WI.DefaultAudits.levelFail = function() {
+    return {level: "fail"};
+};
+
+WI.DefaultAudits.levelError = function() {
+    return {level: "error"};
+};
+
+WI.DefaultAudits.levelUnsupported = function() {
+    return {level: "unsupported"};
+};
+
+WI.DefaultAudits.dataDOMNodes = function() {
+    return {level: "pass", domNodes: [document.body]};
+};
+
+WI.DefaultAudits.dataDOMAttributes = function() {
+    return {level: "pass", domNodes: Array.from(document.querySelectorAll("[id]")), domAttributes: ["id"]};
+};
+
+WI.DefaultAudits.dataErrors = function() {
+    throw Error("this error was thrown from inside the audit test code.");
+};
+
+WI.DefaultAudits.dataCustom = function() {
+    return {level: "pass", a: 1, b: [2], c: {key: 3}};
+};
+
+WI.DefaultAudits.getElementsByComputedRole = function() {
+    return {level: "pass", domNodes: WebInspectorAudit.Accessibility.getElementsByComputedRole("link"), domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.getActiveDescendant = function() {
+    let result = {level: "pass"};
+    let activeDescendant = WebInspectorAudit.Accessibility.getActiveDescendant(document.body);
+    if (activeDescendant)
+        result.domNodes = [activeDescendant];
+    return result;
+};
+
+WI.DefaultAudits.getChildNodes = function() {
+    let childNodes = WebInspectorAudit.Accessibility.getChildNodes(document.body);
+    return {level: "pass", domNodes: childNodes || []};
+};
+
+WI.DefaultAudits.getComputedProperties = function() {
+    let domAttributes = ["alt", "aria-atomic", "aria-busy", "aria-checked", "aria-current", "aria-disabled", "aria-expanded", "aria-haspopup", "aria-hidden", "aria-invalid", "aria-label", "aria-labelledby", "aria-level", "aria-live", "aria-pressed", "aria-readonly", "aria-relevant", "aria-required", "aria-selected", "role", "title"].filter((attribute) => document.body.hasAttribute(attribute));
+    let computedProperties = WebInspectorAudit.Accessibility.getComputedProperties(document.body);
+    return {level: "pass", domNodes: [document.body], domAttributes, ...(computedProperties || {})};
+};
+
+WI.DefaultAudits.getControlledNodes = function() {
+    let controlledNodes = WebInspectorAudit.Accessibility.getControlledNodes(document.body);
+    return {level: "pass", domNodes: controlledNodes || []};
+};
+
+WI.DefaultAudits.getFlowedNodes = function() {
+    let flowedNodes = WebInspectorAudit.Accessibility.getFlowedNodes(document.body);
+    return {level: "pass", domNodes: flowedNodes || []};
+};
+
+WI.DefaultAudits.getMouseEventNode = function() {
+    let result = {level: "pass"};
+    let mouseEventNode = WebInspectorAudit.Accessibility.getMouseEventNode(document.body);
+    if (mouseEventNode)
+        result.domNodes = [mouseEventNode];
+    return result;
+};
+
+WI.DefaultAudits.getOwnedNodes = function() {
+    let ownedNodes = WebInspectorAudit.Accessibility.getOwnedNodes(document.body);
+    return {level: "pass", domNodes: ownedNodes || []};
+};
+
+WI.DefaultAudits.getParentNode = function() {
+    let result = {level: "pass"};
+    let parentNode = WebInspectorAudit.Accessibility.getParentNode(document.body);
+    if (parentNode)
+        result.domNodes = [parentNode];
+    return result;
+};
+
+WI.DefaultAudits.getSelectedChildNodes = function() {
+    let selectedChildNodes = WebInspectorAudit.Accessibility.getSelectedChildNodes(document.body);
+    return {level: "pass", domNodes: selectedChildNodes || []};
+};
+
+WI.DefaultAudits.hasEventListeners = function() {
+    let domAttributes = Array.from(document.body.attributes).filter((attribute) => attribute.name.startsWith("on"));
+    return {level: "pass", domNodes: [document.body], domAttributes, hasEventListeners: WebInspectorAudit.DOM.hasEventListeners(document.body)};
+};
+
+WI.DefaultAudits.hasEventListenersClick = function() {
+    let domAttributes = ["onclick"].filter((attribute) => document.body.hasAttribute(attribute));
+    return {level: "pass", domNodes: [document.body], domAttributes, hasClickEventListener: WebInspectorAudit.DOM.hasEventListeners(document.body, "click")};
+};
+
+WI.DefaultAudits.getResources = function() {
+    return {level: "pass", resources: WebInspectorAudit.Resources.getResources()};
+};
+
+WI.DefaultAudits.getResourceContent = function() {
+    let resources = WebInspectorAudit.Resources.getResources();
+    let mainResource = resources.find((resource) => resource.url ="" window.location.href);
+    return {level: "pass", mainResource, resourceContent: WebInspectorAudit.Resources.getResourceContent(mainResource.id)};
+};
+
+WI.DefaultAudits.unsupported = function() {
+    throw Error("this test should not be supported.");
+};
+
+WI.DefaultAudits.testMenuRoleForRequiredChildren = function() {
+    const relationships = {
+        menu: ["menuitem", "menuitemcheckbox", "menuitemradio"],
+        menubar: ["menuitem", "menuitemcheckbox", "menuitemradio"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testGridRoleForRequiredChildren = function() {
+    const relationships = {
+        grid: ["row", "rowgroup"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testForAriaLabelledBySpelling = function() {
+    let domNodes = Array.from(document.querySelectorAll("[aria-labeledby]"));
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-labeledby"]};
+};
+
+WI.DefaultAudits.testForMultipleBanners = function() {
+    let domNodes = [];
+    let banners = WebInspectorAudit.Accessibility.getElementsByComputedRole("banner");
+    if (banners.length > 1)
+        domNodes = banners;
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testForLinkLabels = function() {
+    let links = WebInspectorAudit.Accessibility.getElementsByComputedRole("link");
+    let domNodes = links.filter((link) => !WebInspectorAudit.Accessibility.getComputedProperties(link).label);
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-label", "aria-labelledby", "title"]};
+};
+
+WI.DefaultAudits.testRowGroupRoleForRequiredChildren = function() {
+    const relationships = {
+        rowgroup: ["row"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testTableRoleForRequiredChildren = function() {
+    const relationships = {
+        table: ["row", "rowgroup"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testForMultipleLiveRegions = function() {
+    const liveRegionRoles = ["alert", "log", "status", "marquee", "timer"];
+    let domNodes = [];
+    let liveRegions = liveRegionRoles.reduce((a, b) => {
+        return a.concat(WebInspectorAudit.Accessibility.getElementsByComputedRole(b));
+    }, []);
+    liveRegions = liveRegions.concat(Array.from(document.querySelectorAll(`[aria-live="polite"], [aria-live="assertive"]`)));
+    if (liveRegions.length > 1)
+        domNodes = liveRegions;
+    return {level: domNodes.length ? "warn" : "pass", domNodes, domAttributes: ["aria-live"]};
+};
+
+WI.DefaultAudits.testListBoxRoleForRequiredChildren = function() {
+    const relationships = {
+        listbox: ["option"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testImageLabels = function() {
+    let images = WebInspectorAudit.Accessibility.getElementsByComputedRole("img");
+    let domNodes = images.filter((image) => !WebInspectorAudit.Accessibility.getComputedProperties(image).label);
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-label", "aria-labelledby", "title", "alt"]};
+};
+
+WI.DefaultAudits.testForAriaHiddenFalse = function() {
+    let domNodes = Array.from(document.querySelectorAll(`[aria-hidden="false"]`));
+    return {level: domNodes.length ? "warn" : "pass", domNodes, domAttributes: ["aria-hidden"]};
+};
+
+WI.DefaultAudits.testTreeRoleForRequiredChildren = function() {
+    const relationships = {
+        tree: ["treeitem", "group"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testRadioGroupRoleForRequiredChildren = function() {
+    const relationships = {
+        radiogroup: ["radio"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testFeedRoleForRequiredChildren = function() {
+    const relationships = {
+        feed: ["article"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testTabListRoleForRequiredChildren = function() {
+    const relationships = {
+        tablist: ["tab"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testButtonLabels = function() {
+    let buttons = WebInspectorAudit.Accessibility.getElementsByComputedRole("button");
+    let domNodes = buttons.filter((button) => !WebInspectorAudit.Accessibility.getComputedProperties(button).label);
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-label", "aria-labelledby", "title"]};
+};
+
+WI.DefaultAudits.testRowRoleForRequiredChildren = function() {
+    const relationships = {
+        row: ["cell", "gridcell", "columnheader", "rowheader"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testListRoleForRequiredChildren = function() {
+    const relationships = {
+        list: ["listitem", "group"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "warn" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testComboBoxRoleForRequiredChildren = function() {
+    const relationships = {
+        combobox: ["textbox", "listbox", "tree", "grid", "dialog"],
+    };
+    let domNodes = [];
+    let visitedParents = new Set;
+    function hasChildWithRole(node, expectedRoles) {
+        let childNode = node;
+        if (!childNode)
+            return false;
+
+        if (childNode.parentNode)
+            visitedParents.add(childNode.parentNode);
+
+        while (childNode) {
+            let properties = WebInspectorAudit.Accessibility.getComputedProperties(childNode);
+            if (childNode.nodeType === Node.ELEMENT_NODE && properties) {
+                if (expectedRoles.includes(properties.role))
+                    return true;
+
+                if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles))
+                    return true;
+            }
+            childNode = childNode.nextSibling;
+        }
+        return false;
+    }
+    for (let role in relationships) {
+        for (let parentNode of WebInspectorAudit.Accessibility.getElementsByComputedRole(role)) {
+            if (visitedParents.has(parentNode))
+                continue;
+
+            if (!hasChildWithRole(parentNode.firstChild, relationships[role]))
+                domNodes.push(parentNode);
+        }
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+
+WI.DefaultAudits.testForMultipleMainContentSections = function() {
+    let domNodes = [];
+    let mainContentElements = WebInspectorAudit.Accessibility.getElementsByComputedRole("main");
+    if (mainContentElements.length > 1) {
+        domNodes = mainContentElements;
+    }
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"]};
+};
+WI.DefaultAudits.testDialogsForLabels = function() {
+    let dialogs = WebInspectorAudit.Accessibility.getElementsByComputedRole("dialog");
+    let domNodes = dialogs.filter((dialog) => !WebInspectorAudit.Accessibility.getComputedProperties(dialog).label);
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-label", "aria-labelledby", "title"]};
+};
+
+WI.DefaultAudits.testForInvalidAriaHiddenValue = function() {
+    let domNodes = Array.from(document.querySelectorAll(`[aria-hidden]:not([aria-hidden="true"], [aria-hidden="false"])`));
+    return {level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-hidden"]};
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Test.html (276679 => 276680)


--- trunk/Source/WebInspectorUI/UserInterface/Test.html	2021-04-27 23:40:17 UTC (rev 276679)
+++ trunk/Source/WebInspectorUI/UserInterface/Test.html	2021-04-27 23:53:42 UTC (rev 276680)
@@ -286,6 +286,8 @@
     <script src=""
     <script src=""
 
+    <script src=""
+
     <script type="text/_javascript_">
         WI.sharedApp = new WI.TestAppController;
         WI.sharedApp.initialize();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to