使用 Laravel Dusk 测试 HTML5 验证
Testing HTML5 Validation with Laravel Dusk
我正在 Laravel Dusk 中创建一个简单的测试,用户在将电子邮件字段留空时无法注册。测试代码如下:
/** @test */
public function a_user_cannot_register_without_filling_in_email_field()
{
$this->browse(function (Browser $browser) {
$browser->visit('/register')
->type('password', $this->user->password)
->type('password_confirmation', $this->user->password)
->press('Register')
->assertSee('The email field is required.');
});
}
当从表单输入中删除 required
属性时,此测试通过,但添加时测试失败。
还有其他方法可以测试吗?
我也一直在努力解决这个问题。我不认为 HTML5 验证错误在 DOM 中呈现,这意味着 dusk 无法检查它们是否实际呈现。 (这是因为 dusk 使用的网络驱动程序最终使用 javascript 来让您网站上的元素点击、获取值、类型等)
在您的情况下,HTML5 验证阻止您提交表单。这意味着您不会看到自己的错误消息,因为您的代码永远不会验证数据,因此您的错误消息不会呈现并且 dusk 看不到它。
在我的例子中,我刚刚禁用了 HTML5 表单验证,因为它只是一个额外的很好的 client-side 验证层,但最终并不重要。
我设法通过此测试的方法是执行以下操作:
在 app
目录中创建一个 helpers.php
。确保此文件包含在您的 autoloaders
和 composer.json
中
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"files": [
"app/helpers.php"
],
"psr-4": {
"App\": "app/"
}
},
在 helpers.php
中您可以创建以下自定义函数:
<?php
/**
* Helper to put novalidate on a form when testing
*/
function disableValidationIfTesting() {
$env = env('APP_ENV');
if ($env == 'local') {
echo 'novalidate';
} else {
return;
}
}
更改此名称以反映您的本地环境名称。有时它可以是 testing
但在我的例子中它只是 local
.
然后,在您要检查测试的表单中,将以下代码添加到您的 form
{{ disableValidationIfTesting() }}
- 这就是您在 blade 文件中呈现函数的方式。
在我的实例中,我是这样包含的:
<form class="form-horizontal" method="POST" action="{{ route('register') }}" {{ disableValidationIfTesting() }}>
这意味着当我在本地开发和测试时(因为您不应该在生产服务器上使用 dusk),表单会添加一个 novalidate
属性,允许浏览器跳过 HTML5 验证并继续标准 Laravel 验证。
这样做之后,我所有的测试都没有问题地通过了:D
感谢 的回答,我想出了以下使用脚本,这样只有测试用例会修改它,而我不必更改原始表单源代码。
所以使用$browser->script("document.querySelector('form').noValidate = true");
是关键。
<?php
/** @test */
public function a_user_cannot_register_without_filling_in_email_field()
{
$this->browse(function (Browser $browser) {
$browser->visit('/register')
->script("document.querySelector('#form_register').noValidate = true");
$browser->type('password', $this->user->password)
->type('password_confirmation', $this->user->password)
->press('Register')
->assertSee('The email field is required.');
});
}
我正在 Laravel Dusk 中创建一个简单的测试,用户在将电子邮件字段留空时无法注册。测试代码如下:
/** @test */
public function a_user_cannot_register_without_filling_in_email_field()
{
$this->browse(function (Browser $browser) {
$browser->visit('/register')
->type('password', $this->user->password)
->type('password_confirmation', $this->user->password)
->press('Register')
->assertSee('The email field is required.');
});
}
当从表单输入中删除 required
属性时,此测试通过,但添加时测试失败。
还有其他方法可以测试吗?
我也一直在努力解决这个问题。我不认为 HTML5 验证错误在 DOM 中呈现,这意味着 dusk 无法检查它们是否实际呈现。 (这是因为 dusk 使用的网络驱动程序最终使用 javascript 来让您网站上的元素点击、获取值、类型等)
在您的情况下,HTML5 验证阻止您提交表单。这意味着您不会看到自己的错误消息,因为您的代码永远不会验证数据,因此您的错误消息不会呈现并且 dusk 看不到它。
在我的例子中,我刚刚禁用了 HTML5 表单验证,因为它只是一个额外的很好的 client-side 验证层,但最终并不重要。
我设法通过此测试的方法是执行以下操作:
在 app
目录中创建一个 helpers.php
。确保此文件包含在您的 autoloaders
和 composer.json
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"files": [
"app/helpers.php"
],
"psr-4": {
"App\": "app/"
}
},
在 helpers.php
中您可以创建以下自定义函数:
<?php
/**
* Helper to put novalidate on a form when testing
*/
function disableValidationIfTesting() {
$env = env('APP_ENV');
if ($env == 'local') {
echo 'novalidate';
} else {
return;
}
}
更改此名称以反映您的本地环境名称。有时它可以是 testing
但在我的例子中它只是 local
.
然后,在您要检查测试的表单中,将以下代码添加到您的 form
{{ disableValidationIfTesting() }}
- 这就是您在 blade 文件中呈现函数的方式。
在我的实例中,我是这样包含的:
<form class="form-horizontal" method="POST" action="{{ route('register') }}" {{ disableValidationIfTesting() }}>
这意味着当我在本地开发和测试时(因为您不应该在生产服务器上使用 dusk),表单会添加一个 novalidate
属性,允许浏览器跳过 HTML5 验证并继续标准 Laravel 验证。
这样做之后,我所有的测试都没有问题地通过了:D
感谢
所以使用$browser->script("document.querySelector('form').noValidate = true");
是关键。
<?php
/** @test */
public function a_user_cannot_register_without_filling_in_email_field()
{
$this->browse(function (Browser $browser) {
$browser->visit('/register')
->script("document.querySelector('#form_register').noValidate = true");
$browser->type('password', $this->user->password)
->type('password_confirmation', $this->user->password)
->press('Register')
->assertSee('The email field is required.');
});
}