使用 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。确保此文件包含在您的 autoloaderscomposer.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.');
    });
}