Laravel 测试 url 到 public 目录中的资源

Laravel testing url to resource in public directory

我正在使用 Laravel Dusk 来测试页面上的所有链接,这些链接是使用 [=32= 从 resources/docs 复制到 public/docs 的 PDF 文件] 混合
问题是尝试使用 get(uri) 方法访问文档的 URL 会得到 404,这是我的 Dusk 的简化版本:

protected function refreshApplicationWithLocale($locale)
{
    self::tearDown();
    putenv(LaravelLocalization::ENV_ROUTE_KEY . '=' . $locale);
    self::setUp();
}

protected function setUp(): void
{
    parent::setUp();
    if(!File::copyDirectory( resource_path('docs'), public_path() . '/docs'))
        throw new \Exception("couldn't copy the folder :(");
    // Storage::assertExists(public_path() . '/docs/clothing/existing_file.pdf'); // this assertion fails, what's weird is the path in the exception message does actually exist
    $this->artisan('storage:link');
}

protected function tearDown(): void
{
    parent::tearDown();
    foreach (static::$browsers as $browser) {
        $browser->driver->manage()->deleteAllCookies();
    }
}

public function testClothing()
{
    $this->refreshApplicationWithLocale('fr');
    $this->get('/test')->assertStatus(200); // passes
    $this->get('/fr/vetements')->assertStatus(200); // passes
    //usually I'd get the page urls dynamically with Dusk, but for simplicity sake I'm just testing with this link that I know it exists and can curl it from withing Homestead
    $this->get('/docs/clothing/Hoodies.pdf')->assertStatus(200); //failes (404)
}

我错过了什么?
谢谢。
P.S.: 我正在使用 laravel 8 和 Homestead

编辑:
在@steven7mwesigwa 回答后,这是我的最终代码:

protected function refreshApplicationWithLocale($locale)
{
    self::tearDown();
    putenv(LaravelLocalization::ENV_ROUTE_KEY . '=' . $locale);
    self::setUp();
}

protected function setUp(): void
{
    parent::setUp();
    if(!File::copyDirectory( resource_path('docs'), public_path() . '/docs'))
        throw new \Exception("couldn't copy the documents folder :(");
}

protected function tearDown(): void
{
    parent::tearDown();
    foreach (static::$browsers as $browser) {
        $browser->driver->manage()->deleteAllCookies();
    }
}

public function testClothing()
{
    $this->refreshApplicationWithLocale('fr');
    $elements = [];
    $this->browse(function (Browser $browser) use(&$elements){
        $elements = $browser->visit('myroute')
            ->elements('.tmp_products_list a', 'href');
    });
    $this->assertGreaterThan(1, count($elements));
    foreach($elements as $element) {
        $response = Http::get($element->getAttribute('href'));
        self::assertEquals($response->status(), 200);
    }
}

问题 1:

// Storage::assertExists(public_path() . '/docs/clothing/existing_file.pdf');

// this assertion fails, what's weird is the path in the exception message does actually exist

The Storage facade uses the storage that is active in your config files (config/filesystems.php). Note that this defaults to local. The root path is set for each storage option. In the case of local, it's pointing to storage/app out of my head. - @bobbybouwmann

另外,通过storage路径搜索的正确方法,是指定filesystem "disk"。即,对于驻留在 storage/app/public/demo.js:

中的文件

Storage::disk("public")->assertExists("demo.js");

除此之外,由于您所需的测试文件位于 pubic 文件夹中,因此可以使用以下方法进行测试:

$this->assertFileExists(public_path() . '/docs/clothing/existing_file.pdf');

问题 2:

//usually I'd get the page urls dynamically with Dusk, but for simplicity sake I'm just testing with this link that I know it exists and can curl it from withing Homestead

$this->get('/docs/clothing/Hoodies.pdf')->assertStatus(200); //failes (404)

上面的代码片段不起作用,因为 $this->get(...) 本质上是在与此路径对应的应用程序路由文件中搜索 明确定义的路由 没有找到。

您必须使用浏览器测试框架(即 Laravel Dusk)来测试 Web 服务器上的静态文件。

可在此处找到更多内容:

尽管如此,由于您已经在使用 Laravel Dusk,这可以通过以下方式实现:

        $this->browse(function (Browser $browser) {
            $browser->visit('/docs/clothing/Hoodies.pdf')
                ->assertDontSee("404")
                ->assertDontSee("NOT FOUND");
        });

如果 URL 有效且 PDF 文件存在并加载,则不会加载 HTML 视图。因此测试应该通过。

如果 URL 无效,将加载 Laravel 的默认 404.blade.php 视图。该视图包括以下文本字符串:“404”和“NOT FOUND”。因此在这种情况下测试会失败。

如果您已经有 custom 404,请随意更改 assertDontSee(....) 方法参数中传递的文本字符串错误页面。