laravel/dusk

Failed to load assets in Sail

damms005 opened this issue · 4 comments

Dusk Version

8.0.0

Laravel Version

10.48.2

PHP Version

8.2.8

PHPUnit Version

10.5.12

Database Driver & Version

mysql Ver 8.0.32 for Linux on x86_64 (MySQL Community Server - GPL)

Description

Assets are not loaded when running Dusk tests.

test('homepage', function () {
    $student = addStudent();

    $this->browse(function (Browser $browser) use ($student) {
        $browser->visit(route('homepage'))
            ->loginAs($student->userModel->id)
            ->storeConsoleLog('error-log') // --> debug purposes
            ->assertSee('Something');
    });
});

Console log output

[
    {
        "level": "SEVERE",
        "message": "http:\/\/tims.local\/build\/assets\/app-931911db.css - Failed to load resource: net::ERR_CONNECTION_REFUSED",
        "source": "network",
        "timestamp": 1710742000259
    },
    {
        "level": "SEVERE",
        "message": "http:\/\/tims.local\/new-frontend\/assets\/js\/jquery.min.js - Failed to load resource: net::ERR_CONNECTION_REFUSED",
        "source": "network",
        "timestamp": 1710742000259
    },
    {
        "level": "SEVERE",
        "message": "http:\/\/tims.local\/build\/assets\/main-f5d540ec.js - Failed to load resource: net::ERR_CONNECTION_REFUSED",
        "source": "network",
        "timestamp": 1710742000259
    },
    {
        "level": "SEVERE",
        "message": "http:\/\/tims.local\/build\/assets\/main-97df0a5b.js - Failed to load resource: net::ERR_CONNECTION_REFUSED",
        "source": "network",
        "timestamp": 1710742000259
    },
    {
        "level": "SEVERE",
        "message": "http:\/\/tims.local\/favicon-32x32.png - Failed to load resource: net::ERR_CONNECTION_REFUSED",
        "source": "network",
        "timestamp": 1710742000774
    },
    {
        "level": "SEVERE",
        "message": "http:\/\/tims.local\/favicon-16x16.png - Failed to load resource: net::ERR_CONNECTION_REFUSED",
        "source": "network",
        "timestamp": 1710742000774
    }
]

docker-compose.yml

# For more information: https://laravel.com/docs/sail
version: '3'
services:
    laravel.test:
        build:
            context: ./docker/8.2
            dockerfile: Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        image: tims-laravel-sail-php8.2/app
        extra_hosts:
            - 'host.docker.internal:host-gateway'
        ports:
            - '${APP_PORT:-80}:80'
        environment:
            WWWUSER: '${WWWUSER}'
            LARAVEL_SAIL: 1
            XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
            XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
            PHP_CLI_SERVER_WORKERS: 10
        volumes:
            - '.:/var/www/html'
        networks:
            - sail
        depends_on:
            - mysql
            - selenium
    mysql:
        image: 'mysql/mysql-server:8.0'
        ports:
            - '${FORWARD_DB_PORT:-3306}:3306'
        environment:
            MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ROOT_HOST: "%"
            MYSQL_DATABASE: '${DB_DATABASE}'
            MYSQL_USER: '${DB_USERNAME}'
            MYSQL_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ALLOW_EMPTY_PASSWORD: 1
        volumes:
            - 'sail-mysql:/var/lib/mysql'
            - './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh'
        networks:
            - sail
        healthcheck:
            test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"]
            retries: 3
            timeout: 5s
    selenium:
      image: 'selenium/standalone-chrome'
      extra_hosts:
        - 'host.docker.internal:host-gateway'
      volumes:
          - '/dev/shm:/dev/shm'
      networks:
          - sail
networks:
    sail:
        driver: bridge
volumes:
    sail-mysql:
        driver: local

Steps To Reproduce

  • Setup a new Sail app
  • Setup Dusk
  • Write a test that accesses any page that requires assets to be loaded
  • Log console errors using ->storeConsoleLog('...')
  • Run the Dusk test using sail dusk
  • See connection refused errors as shown in the issue description above

Heya, thanks for reporting.

We'll need more info and/or code to debug this further. Can you please create a repository with the command below, commit the code that reproduces the issue as one separate commit on the main/master branch and share the repository here? Please make sure that you have the latest version of the Laravel installer in order to run this command. Please also make sure you have both Git & the GitHub CLI tool properly set up.

laravel new bug-report --github="--public"

Please do not amend and create a separate commit with your custom changes. After you've posted the repository, we'll try to reproduce the issue.

Thanks!

Thank you. I am on it.

However, I should mention that when I ran laravel new bug-report --github="--public"

I got the following warning in the command output

WARN  Make sure the "gh" CLI tool is installed and that you're authenticated to GitHub. Skipping...

However, running gh --version outputs gh version 2.45.0 (2024-03-04), confirming that I have gh installed, as shown in the screenshot below.

image

@damms005 can't help you with that I'm afraid.. please just create the repo manually in this case and commit any custom things separately.

Thanks @driesvints

Having tried to unsuccessfully reproduce it in Laravel v11 and latest v10, I am now convinced that this is a problem with my local Docker setup. I think I've got my Docker environment messed up somehow, and it somehow only affects this project.

I am no Docker expert, so I'll pass on this. However, I managed to get a workaround, and sharing here should an alien from space hit this issue, too:

Workaround

Lary of Laracast gave me a hint that helped me with a temporary fix:

  1. Check Network Access: Verify that the Selenium service can access the laravel.test service. Since they are both in the same network (sail), they should be able to communicate without any issues.

With this nudge, I swapped APP_URL manually because no other solution I could think of worked. I tried:

  • setting APP_URL in a service provider if running test
  • setting APP_URL in phpunit.dusk.xml
  • manually creating content of .env.dusk.local from .env is not an option for me

So the below hot-swap monkey-patch is my workaround: tests/DuskTestCase.php:

protected static function ensureLaravelServiceIsAppUrl()
{
    $appEnvFilePath = __DIR__  . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '.env';
    $duskEnvFilePath = __DIR__  . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '.env.dusk.local';

    $laravelServiceName = 'laravel.test'; // -> service name in docker-compose.yml
    $appUrlForDusk = "http://{$laravelServiceName}";

    $contentOfEnv = file_get_contents($appEnvFilePath);
    $contentOfDuskEnv = file_exists($duskEnvFilePath)
        ? file_get_contents($duskEnvFilePath)
        : '';

    $appUrlInContentOfDuskEnv = preg_match('/APP_URL=(.*)/', $contentOfDuskEnv, $duskEnvMatches);

    if (!$appUrlInContentOfDuskEnv) {
        return self::copyEnvAndWriteLaravelServiceNameToDuskEnv($duskEnvFilePath,  $appUrlForDusk,  $contentOfEnv);
    }

    if ($duskEnvMatches[1] !== $appUrlForDusk) {
        return self::copyEnvAndWriteLaravelServiceNameToDuskEnv($duskEnvFilePath,  $appUrlForDusk,  $contentOfEnv);
    }
}

protected static function copyEnvAndWriteLaravelServiceNameToDuskEnv(string $duskEnvFilePath, string $appUrlForDusk, string $contentOfEnv)
{
    $updatedContentOfEnv = preg_replace('/APP_URL=(.*)/', "APP_URL={$appUrlForDusk}", $contentOfEnv);
    file_put_contents($duskEnvFilePath, $updatedContentOfEnv);
}

The finally, call it if running sail:

/**
 * Prepare for Dusk test execution.
 */
#[BeforeClass]
public static function prepare(): void
{
    if (!static::runningInSail()) {
        static::startChromeDriver();
    }

    if (static::runningInSail()) {
        self::ensureLaravelServiceIsAppUrl();
    }
}