The Issue We’re Resolving
When running a Laravel test suite with Livewire components, the default workflow file provided by GitHub for Laravel likely won’t pass. When using their default config, I was presented with errors such as this:
FAILED Tests\Feature\Livewire\ContactFormTest > it displays on contact p…
Expected: <!DOCTYPE html>\n
<html lang="en" class="auto">\n
<!--\n
... (349 more lines)
To contain: "name":"contactform"
at vendor/livewire/livewire/src/Features/SupportTesting/SupportTesting.php:54
50▕ $component = app(ComponentRegistry::class)->getName($component);
51▕ }
52▕ $escapedComponentName = trim(htmlspecialchars(json_encode(['name' => $component])), '{}');
53▕
➜ 54▕ \PHPUnit\Framework\Assert::assertStringContainsString(
55▕ $escapedComponentName,
56▕ $this->getContent(),
57▕ 'Cannot find Livewire component ['.$component.'] rendered on page.'
58▕ );
+4 vendor frames
5 tests/Feature/Livewire/ContactFormTest.php:19
The test in question was simply checking if the component was rendered when a certain page was visited. In this example, as I’m testing my contact form, I’m checking that the contact form is displayed on the contact
route:
public function test_it_displays_on_contact_page(): void
{
$this->get(route('contact'))
->assertSeeVolt('contactform');
}
Why Livewire Tests Fail in GitHub Actions
It turns out that the issue in this case was that Livewire comes in two parts: PHP and Javascript. Without the Javascript, it simply won’t work. With that in mind, this is the default workflow GitHub provides for running Laravel tests (As of 19th August 2024):
name: Laravel
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
laravel-tests:
runs-on: ubuntu-latest
steps:
- uses: shivammathur/setup-php@15c43e89cdef867065b0213be354c2841860869e
with:
php-version: '8.0'
- uses: actions/checkout@v4
- name: Copy .env
run: php -r "file_exists('.env') || copy('.env.example', '.env');"
- name: Install Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: Generate key
run: php artisan key:generate
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
- name: Create Database
run: |
mkdir -p database
touch database/database.sqlite
- name: Execute tests (Unit and Feature tests) via PHPUnit/Pest
env:
DB_CONNECTION: sqlite
DB_DATABASE: database/database.sqlite
run: php artisan test
You’ll notice that this only accommodates the PHP side of Livewire. Everything is set up appropriately for a default Laravel installation, but Livewire introduces some extra complexity which this isn’t set up to handle appropriately.
How to Fix Livewire Tests in GitHub Actions
Here is my /.github/workflows/laravel.yml
file for HermitClock, my most recent Laravel/Livewire project:
name: Laravel
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
laravel-tests:
runs-on: ubuntu-latest
steps:
- uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 21
- name: Copy .env
run: php -r "file_exists('.env') || copy('.env.example', '.env');"
- name: Install PHP Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: Install Node Dependencies
run: |
npm ci
npm run build
- name: Generate key
run: php artisan key:generate
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
- name: Create Database
run: |
mkdir -p database
touch database/database.sqlite
- name: Execute tests via PHPUnit
env:
APP_ENV: testing
DB_CONNECTION: sqlite
DB_DATABASE: database/database.sqlite
run: php artisan test
As you can see, I’ve made some tweaks to the default configuration, as well as added some extra logic for Node.js to run:
php-version: '8.2
is now set to match my production environment.- uses: actions/setup-node@v4
utilises the community template for introducing Node into your pipeline.node-version: 21
specifies the version of Node you require. I’ve set this to21
as this is the version my production environment uses.npm run build
Thebuild
command which is being run refers to my production build script inpackage.json
.APP_ENV: testing
is used to ensure that Laravel is aware that it’s a testing environment, as this can affect how tests run.
Aside from these changes, the rest should be fairly self-explanatory. You will likely need to tweak the PHP and Node versions which I’ve set for my project. If you use any extra environment variables, you’ll likely need to set those too in an appropriate, secure manner.
Leave a Reply