Issue #3091870 by tedbow, phenaproxima, alexpott, bnjmnm, tim.plunkett, lauriii, mradcliffe: Fail Functional Javascript tests that throw Javascript errors

merge-requests/880/head
effulgentsia 2021-06-30 14:26:18 -07:00
parent e595a4534e
commit e4284d2d91
19 changed files with 241 additions and 9 deletions

View File

@ -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}
*/

View File

@ -0,0 +1,11 @@
/**
* @file
* Testing tools for JavaScript errors.
*/
(function ({ throwError, behaviors }) {
behaviors.testErrors = {
attach: () => {
throwError(new Error('A manually thrown error.'));
},
};
})(Drupal);

View File

@ -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);

View File

@ -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

View File

@ -0,0 +1,6 @@
errors_test:
version: VERSION
js:
js/js_errors_test.js: {}
dependencies:
- core/drupal

View File

@ -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'

View File

@ -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']],
];
}
}

View File

@ -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);

View File

@ -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);

View File

@ -1,6 +1,6 @@
deprecation_log:
version: VERSION
js:
js/js_deprecation_log.js: { weight: -100 }
js/js_testing_log.js: {}
dependencies:
- core/drupal

View File

@ -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;
}

View File

@ -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}
*/

View File

@ -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

View File

@ -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');
}
}

View File

@ -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');
}
}

View File

@ -16,6 +16,13 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*/
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 @@ abstract class WebDriverTestBase extends BrowserTestBase {
*/
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 @@ abstract class WebDriverTestBase extends BrowserTestBase {
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();
}

View File

@ -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);
};

View File

@ -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);
};