diff --git a/core/modules/media/tests/src/FunctionalJavascript/MediaEmbedFilterConfigurationUiTest.php b/core/modules/media/tests/src/FunctionalJavascript/MediaEmbedFilterConfigurationUiTest.php index efae01fc10e47463741ef5de7a3405043a2afeca..13513802d783cb45bfce5e574a645c93eb624547 100644 --- a/core/modules/media/tests/src/FunctionalJavascript/MediaEmbedFilterConfigurationUiTest.php +++ b/core/modules/media/tests/src/FunctionalJavascript/MediaEmbedFilterConfigurationUiTest.php @@ -15,6 +15,13 @@ class MediaEmbedFilterConfigurationUiTest extends MediaJavascriptTestBase { */ protected $defaultTheme = 'stark'; + /** + * {@inheritdoc} + * + * @todo Remove this class property in https://www.drupal.org/node/3091878/. + */ + protected $failOnJavascriptConsoleErrors = FALSE; + /** * {@inheritdoc} */ diff --git a/core/modules/system/tests/modules/js_errors_test/js/js_errors_test.es6.js b/core/modules/system/tests/modules/js_errors_test/js/js_errors_test.es6.js new file mode 100644 index 0000000000000000000000000000000000000000..421d036ee8509c22621087d071be1bfc795cd48d --- /dev/null +++ b/core/modules/system/tests/modules/js_errors_test/js/js_errors_test.es6.js @@ -0,0 +1,11 @@ +/** + * @file + * Testing tools for JavaScript errors. + */ +(function ({ throwError, behaviors }) { + behaviors.testErrors = { + attach: () => { + throwError(new Error('A manually thrown error.')); + }, + }; +})(Drupal); diff --git a/core/modules/system/tests/modules/js_errors_test/js/js_errors_test.js b/core/modules/system/tests/modules/js_errors_test/js/js_errors_test.js new file mode 100644 index 0000000000000000000000000000000000000000..a3357d06f801eb847a768e6cea2fddc31a3ac4f8 --- /dev/null +++ b/core/modules/system/tests/modules/js_errors_test/js/js_errors_test.js @@ -0,0 +1,16 @@ +/** +* DO NOT EDIT THIS FILE. +* See the following change record for more information, +* https://www.drupal.org/node/2815083 +* @preserve +**/ + +(function (_ref) { + var throwError = _ref.throwError, + behaviors = _ref.behaviors; + behaviors.testErrors = { + attach: function attach() { + throwError(new Error('A manually thrown error.')); + } + }; +})(Drupal); \ No newline at end of file diff --git a/core/modules/system/tests/modules/js_errors_test/js_errors_test.info.yml b/core/modules/system/tests/modules/js_errors_test/js_errors_test.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..64c9225341eb1ae8c84f519d1e3fb01a3396b4e7 --- /dev/null +++ b/core/modules/system/tests/modules/js_errors_test/js_errors_test.info.yml @@ -0,0 +1,5 @@ +name: 'JS Errors test' +description: 'Provides a JavaScript error that can be used for tests' +type: module +package: Testing +version: VERSION diff --git a/core/modules/system/tests/modules/js_errors_test/js_errors_test.libraries.yml b/core/modules/system/tests/modules/js_errors_test/js_errors_test.libraries.yml new file mode 100644 index 0000000000000000000000000000000000000000..3454e7cb63448c516723758191bc78a3db104d44 --- /dev/null +++ b/core/modules/system/tests/modules/js_errors_test/js_errors_test.libraries.yml @@ -0,0 +1,6 @@ +errors_test: + version: VERSION + js: + js/js_errors_test.js: {} + dependencies: + - core/drupal diff --git a/core/modules/system/tests/modules/js_errors_test/js_errors_test.routing.yml b/core/modules/system/tests/modules/js_errors_test/js_errors_test.routing.yml new file mode 100644 index 0000000000000000000000000000000000000000..d096284e25296fec1ecd79b2699e9bbd9207529e --- /dev/null +++ b/core/modules/system/tests/modules/js_errors_test/js_errors_test.routing.yml @@ -0,0 +1,7 @@ +js_errors_test.errors: + path: '/js_errors_test' + defaults: + _controller: '\Drupal\js_errors_test\Controller\JsErrorsTestController::jsErrorsTest' + _title: 'JsErrorsTest' + requirements: + _access: 'TRUE' diff --git a/core/modules/system/tests/modules/js_errors_test/src/Controller/JsErrorsTestController.php b/core/modules/system/tests/modules/js_errors_test/src/Controller/JsErrorsTestController.php new file mode 100644 index 0000000000000000000000000000000000000000..99628a272c57d184feed6810b92db836c893a56f --- /dev/null +++ b/core/modules/system/tests/modules/js_errors_test/src/Controller/JsErrorsTestController.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\js_errors_test\Controller; + +/** + * Test Controller loading js_errors_test/errors_test library. + */ +class JsErrorsTestController { + + /** + * Renders page that has js_errors_test/errors_test library attached. + * + * @return string[][] + * Render array. + */ + public function jsErrorsTest(): array { + return [ + '#attached' => ['library' => ['js_errors_test/errors_test']], + ]; + } + +} diff --git a/core/modules/system/tests/modules/js_testing_log_test/js/js_testing_log.es6.js b/core/modules/system/tests/modules/js_testing_log_test/js/js_testing_log.es6.js new file mode 100644 index 0000000000000000000000000000000000000000..dd6fe578ed362223d02007d9ac7c425138239423 --- /dev/null +++ b/core/modules/system/tests/modules/js_testing_log_test/js/js_testing_log.es6.js @@ -0,0 +1,35 @@ +/** + * @file + * Support code for testing JavaScript error handling in functional tests. + */ +(function (Drupal) { + if (typeof console !== 'undefined' && console.warn) { + const originalWarnFunction = console.warn; + console.warn = (warning) => { + const warnings = JSON.parse( + sessionStorage.getItem('js_testing_log_test.warnings') || + JSON.stringify([]), + ); + warnings.push(warning); + sessionStorage.setItem( + 'js_testing_log_test.warnings', + JSON.stringify(warnings), + ); + originalWarnFunction(warning); + }; + + const originalThrowFunction = Drupal.throwError; + Drupal.throwError = (error) => { + const errors = JSON.parse( + sessionStorage.getItem('js_testing_log_test.errors') || + JSON.stringify([]), + ); + errors.push(error.stack); + sessionStorage.setItem( + 'js_testing_log_test.errors', + JSON.stringify(errors), + ); + originalThrowFunction(error); + }; + } +})(Drupal); diff --git a/core/modules/system/tests/modules/js_testing_log_test/js/js_testing_log.js b/core/modules/system/tests/modules/js_testing_log_test/js/js_testing_log.js new file mode 100644 index 0000000000000000000000000000000000000000..2a5348723b0dc8ee65442d539840f1aa3dd88ac2 --- /dev/null +++ b/core/modules/system/tests/modules/js_testing_log_test/js/js_testing_log.js @@ -0,0 +1,28 @@ +/** +* DO NOT EDIT THIS FILE. +* See the following change record for more information, +* https://www.drupal.org/node/2815083 +* @preserve +**/ + +(function (Drupal) { + if (typeof console !== 'undefined' && console.warn) { + var originalWarnFunction = console.warn; + + console.warn = function (warning) { + var warnings = JSON.parse(sessionStorage.getItem('js_testing_log_test.warnings') || JSON.stringify([])); + warnings.push(warning); + sessionStorage.setItem('js_testing_log_test.warnings', JSON.stringify(warnings)); + originalWarnFunction(warning); + }; + + var originalThrowFunction = Drupal.throwError; + + Drupal.throwError = function (error) { + var errors = JSON.parse(sessionStorage.getItem('js_testing_log_test.errors') || JSON.stringify([])); + errors.push(error.stack); + sessionStorage.setItem('js_testing_log_test.errors', JSON.stringify(errors)); + originalThrowFunction(error); + }; + } +})(Drupal); \ No newline at end of file diff --git a/core/modules/system/tests/modules/js_deprecation_log_test/js_deprecation_log_test.info.yml b/core/modules/system/tests/modules/js_testing_log_test/js_testing_log_test.info.yml similarity index 100% rename from core/modules/system/tests/modules/js_deprecation_log_test/js_deprecation_log_test.info.yml rename to core/modules/system/tests/modules/js_testing_log_test/js_testing_log_test.info.yml diff --git a/core/modules/system/tests/modules/js_deprecation_log_test/js_deprecation_log_test.libraries.yml b/core/modules/system/tests/modules/js_testing_log_test/js_testing_log_test.libraries.yml similarity index 61% rename from core/modules/system/tests/modules/js_deprecation_log_test/js_deprecation_log_test.libraries.yml rename to core/modules/system/tests/modules/js_testing_log_test/js_testing_log_test.libraries.yml index 1744815c98613b2925cfdb03d0958d01893b0e91..d02c19893cee2f62707f7278d5e5ec675ba4a182 100644 --- a/core/modules/system/tests/modules/js_deprecation_log_test/js_deprecation_log_test.libraries.yml +++ b/core/modules/system/tests/modules/js_testing_log_test/js_testing_log_test.libraries.yml @@ -1,6 +1,6 @@ deprecation_log: version: VERSION js: - js/js_deprecation_log.js: { weight: -100 } + js/js_testing_log.js: {} dependencies: - core/drupal diff --git a/core/modules/system/tests/modules/js_deprecation_log_test/js_deprecation_log_test.module b/core/modules/system/tests/modules/js_testing_log_test/js_testing_log_test.module similarity index 55% rename from core/modules/system/tests/modules/js_deprecation_log_test/js_deprecation_log_test.module rename to core/modules/system/tests/modules/js_testing_log_test/js_testing_log_test.module index a86a2f21fbd204bd9f23ae640c1a670ad01bbaee..d140ecfdaff7543ac963d87fe897cd070cb3102a 100644 --- a/core/modules/system/tests/modules/js_deprecation_log_test/js_deprecation_log_test.module +++ b/core/modules/system/tests/modules/js_testing_log_test/js_testing_log_test.module @@ -8,14 +8,14 @@ /** * Implements hook_page_attachments(). */ -function js_deprecation_log_test_page_attachments(array &$attachments) { +function js_testing_log_test_page_attachments(array &$attachments) { // Unconditionally attach an asset to the page. - $attachments['#attached']['library'][] = 'js_deprecation_log_test/deprecation_log'; + $attachments['#attached']['library'][] = 'js_testing_log_test/deprecation_log'; } /** * Implements hook_js_settings_alter(). */ -function js_deprecation_log_test_js_settings_alter(&$settings) { +function js_testing_log_test_js_settings_alter(&$settings) { $settings['suppressDeprecationErrors'] = FALSE; } diff --git a/core/modules/user/tests/src/FunctionalJavascript/PasswordWidgetThemeFunctionTest.php b/core/modules/user/tests/src/FunctionalJavascript/PasswordWidgetThemeFunctionTest.php index af11642b98143393c88a231bcaba3d36be345121..0794c9e42398799d14f584408e01d1a4b7980b4b 100644 --- a/core/modules/user/tests/src/FunctionalJavascript/PasswordWidgetThemeFunctionTest.php +++ b/core/modules/user/tests/src/FunctionalJavascript/PasswordWidgetThemeFunctionTest.php @@ -15,6 +15,13 @@ class PasswordWidgetThemeFunctionTest extends WebDriverTestBase { */ protected $defaultTheme = 'password_theme_function_test'; + /** + * {@inheritdoc} + * + * @todo Remove this class property in https://www.drupal.org/node/3217947. + */ + protected $failOnJavascriptConsoleErrors = FALSE; + /** * {@inheritdoc} */ diff --git a/core/profiles/nightwatch_testing/nightwatch_testing.info.yml b/core/profiles/nightwatch_testing/nightwatch_testing.info.yml index 04289408ed9338d09c2d28762b79d06f59d34c08..6e3f05ad741c1ae080df3a99375f692d3e95cb91 100644 --- a/core/profiles/nightwatch_testing/nightwatch_testing.info.yml +++ b/core/profiles/nightwatch_testing/nightwatch_testing.info.yml @@ -4,4 +4,4 @@ description: 'Minimal profile for running Nightwatch tests. Includes absolutely version: VERSION hidden: true install: - - js_deprecation_log_test + - js_testing_log_test diff --git a/core/tests/Drupal/FunctionalJavascriptTests/JavascriptErrorsSuppressionTest.php b/core/tests/Drupal/FunctionalJavascriptTests/JavascriptErrorsSuppressionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ad0bd48217593a6031982a6000d2ed0c9532b0bb --- /dev/null +++ b/core/tests/Drupal/FunctionalJavascriptTests/JavascriptErrorsSuppressionTest.php @@ -0,0 +1,38 @@ +<?php + +namespace Drupal\FunctionalJavascriptTests; + +/** + * Tests that Drupal.throwError can be suppressed to allow a test to pass. + * + * @group javascript + */ +class JavascriptErrorsSuppressionTest extends WebDriverTestBase { + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * {@inheritdoc} + */ + protected static $modules = ['js_errors_test']; + + /** + * {@inheritdoc} + */ + protected $failOnJavascriptConsoleErrors = FALSE; + + /** + * Tests that JavaScript console errors can be suppressed. + */ + public function testJavascriptErrors(): void { + // Visit page that will throw a JavaScript console error. + $this->drupalGet('js_errors_test'); + // Ensure that errors from previous page loads will be + // detected. + $this->drupalGet('user'); + } + +} diff --git a/core/tests/Drupal/FunctionalJavascriptTests/JavascriptErrorsTest.php b/core/tests/Drupal/FunctionalJavascriptTests/JavascriptErrorsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bb020b2918fc603463d0e205639ff33e0d9e44fb --- /dev/null +++ b/core/tests/Drupal/FunctionalJavascriptTests/JavascriptErrorsTest.php @@ -0,0 +1,35 @@ +<?php + +namespace Drupal\FunctionalJavascriptTests; + +/** + * Tests that Drupal.throwError will cause a deprecation warning. + * + * @group javascript + * @group legacy + */ +class JavascriptErrorsTest extends WebDriverTestBase { + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * {@inheritdoc} + */ + protected static $modules = ['js_errors_test']; + + /** + * Tests that JavaScript console errors will result in a deprecation warning. + */ + public function testJavascriptErrors(): void { + $this->expectDeprecation('Not failing JavaScript test for JavaScript errors is deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. This test had the following JavaScript errors: Error: A manually thrown error.'); + // Visit page that will throw a JavaScript console error. + $this->drupalGet('js_errors_test'); + // Ensure that errors from previous page loads will be + // detected. + $this->drupalGet('user'); + } + +} diff --git a/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php b/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php index 516062a80409fd96995f81214b018c9ad8ee6525..20f04782735134cb24e1edea95f309af6f159184 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php @@ -16,6 +16,13 @@ */ abstract class WebDriverTestBase extends BrowserTestBase { + /** + * Determines if a test should fail on JavaScript console errors. + * + * @var bool + */ + protected $failOnJavascriptConsoleErrors = TRUE; + /** * Disables CSS animations in tests for more reliable testing. * @@ -61,7 +68,7 @@ protected function initMink() { */ protected function installModulesFromClassProperty(ContainerInterface $container) { self::$modules = [ - 'js_deprecation_log_test', + 'js_testing_log_test', 'jquery_keyevent_polyfill_test', ]; if ($this->disableCssAnimations) { @@ -102,12 +109,20 @@ protected function tearDown() { throw new \RuntimeException('Unfinished AJAX requests while tearing down a test'); } - $warnings = $this->getSession()->evaluateScript("JSON.parse(sessionStorage.getItem('js_deprecation_log_test.warnings') || JSON.stringify([]))"); + $warnings = $this->getSession()->evaluateScript("JSON.parse(sessionStorage.getItem('js_testing_log_test.warnings') || JSON.stringify([]))"); foreach ($warnings as $warning) { if (strpos($warning, '[Deprecation]') === 0) { @trigger_error('Javascript Deprecation:' . substr($warning, 13), E_USER_DEPRECATED); } } + if ($this->failOnJavascriptConsoleErrors) { + $errors = $this->getSession()->evaluateScript("JSON.parse(sessionStorage.getItem('js_testing_log_test.errors') || JSON.stringify([]))"); + if (!empty($errors)) { + $all_errors = implode("\n", $errors); + @trigger_error("Not failing JavaScript test for JavaScript errors is deprecated in drupal:9.3.0 and is removed from drupal:10.0.0. This test had the following JavaScript errors: $all_errors. See https://www.drupal.org/node/3221100", E_USER_DEPRECATED); + } + } + } parent::tearDown(); } diff --git a/core/tests/Drupal/Nightwatch/Assertions/deprecationErrorExists.js b/core/tests/Drupal/Nightwatch/Assertions/deprecationErrorExists.js index 999b8083e79e2949bd27763ec6f425653ded5854..0b8b9f64f56c85b0ee50615a16eb97ae7e0e1374 100644 --- a/core/tests/Drupal/Nightwatch/Assertions/deprecationErrorExists.js +++ b/core/tests/Drupal/Nightwatch/Assertions/deprecationErrorExists.js @@ -18,6 +18,6 @@ module.exports.assertion = function (expected) { this.command = (callback) => // eslint-disable-next-line prefer-arrow-callback this.api.execute(function () { - return window.sessionStorage.getItem('js_deprecation_log_test.warnings'); + return window.sessionStorage.getItem('js_testing_log_test.warnings'); }, callback); }; diff --git a/core/tests/Drupal/Nightwatch/Assertions/noDeprecationErrors.js b/core/tests/Drupal/Nightwatch/Assertions/noDeprecationErrors.js index 2dec7bf464b9d16d6cc328da6649fe759e6c1d62..8d5ab79b9e8a9c8ad9ca48c45827203749503e05 100644 --- a/core/tests/Drupal/Nightwatch/Assertions/noDeprecationErrors.js +++ b/core/tests/Drupal/Nightwatch/Assertions/noDeprecationErrors.js @@ -18,6 +18,6 @@ module.exports.assertion = function () { this.command = (callback) => // eslint-disable-next-line prefer-arrow-callback this.api.execute(function () { - return window.sessionStorage.getItem('js_deprecation_log_test.warnings'); + return window.sessionStorage.getItem('js_testing_log_test.warnings'); }, callback); };