Coding

Laravel Dusk tests failing - no such window target window already closed

Posted on Fri, Jul 11, 2025

Laravel Dusk tests failing -  no such window target window already closed

Last week, I encountered an issue while using Laravel Dusk to test a web application I was developing.

I use Laravel Dusk as part of my testing process to ensure that the frontend behaves as expected—clicking buttons, filling out forms, and so on. This complements the unit and feature tests, allowing me to run php artisan dusk or php artisan dusk --browse to test the entire frontend in one go.

The issue I ran into was the following error:

FAILED  Tests\Browser\FrontendTest > check customers can forward test NoSuchWindowException
  no such window: target window already closed
from unknown error: web view not found
  (Session info: chrome=138.0.7204.93)

This was odd because the test would occasionally pass. I spent more time than I’d like to admit trying to figure out why it was failing. Eventually, while running php artisan dusk --browse, I noticed a security message popping up in Chrome. It was warning me that the password I was using to log in had been compromised.

No surprise there—the password was 12345. Since I’m testing on my local development machine, I don't use secure credentials. It’s purely for development purposes.

How I Fixed the Issue

When you set up Dusk, you get a DuskTestCase.php file that configures the Chrome environment. I added the --incognito flag there. This (I believe) helps suppress some of Chrome’s security checks during startup.

But I didn’t stop there—I added several other flags to disable features that might interfere with automated testing. Here's the final version of my DuskTestCase.php driver configuration:

protected function driver()
{
    $options = new ChromeOptions();

    $arguments = collect([
        $this->shouldStartMaximized() ? '--start-maximized' : '--window-size=1920,1080',
        '--disable-search-engine-choice-screen',
        '--no-default-browser-check',
        '--incognito',
        '--no-first-run',
        '--disable-default-apps',
        '--disable-extensions',
        '--disable-plugins',
        '--disable-popup-blocking',
        '--disable-notifications',
        '--disable-translate',
        '--disable-background-networking',
        '--disable-component-update',
        '--safebrowsing-disable-download-protection',
        '--disable-client-side-phishing-detection',
        '--disable-features=PasswordChangeDetection,PasswordCheck,SafeBrowsingEnhancedProtection',
        '--ignore-certificate-errors',
        '--ignore-ssl-errors',
        '--disable-automation',
        '--disable-blink-features=AutomationControlled',
    ])->unless($this->hasHeadlessDisabled(), function ($items) {
        return $items->merge([
            '--disable-gpu',
            '--headless=new',
        ]);
    })->all();

    $options->addArguments($arguments);

    $options->setExperimentalOption('prefs', [
        'credentials_enable_service' => false,
        'profile.password_manager_enabled' => false,
        'profile.default_content_setting_values.notifications' => 2,
    ]);

    $capabilities = DesiredCapabilities::chrome();
    $capabilities->setCapability(ChromeOptions::CAPABILITY, $options);

    return RemoteWebDriver::create(
        'http://localhost:9515', // Default address for Chromedriver
        $capabilities
    );
}

Hopefully, this helps someone else in the future. It definitely had me scratching my head for a while.