Skip to content
52 changes: 44 additions & 8 deletions .github/workflows/test-runner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,23 @@ jobs:

runs-on: ubuntu-latest

# Define the matrix of different PHP, Laravel, and testbench versions
# Define the matrix of different PHP, Laravel, testbench versions, and shards
strategy:
# Fail the whole workflow if one of the jobs fails
fail-fast: true
matrix:
php: [ 8.2, 8.3, 8.4 ]
php: [ 8.3, 8.4 ]
laravel: [ 11.*, 12.* ]
dependency-version: [ prefer-stable ]
shard: [ 1, 2, 3, 4 ]
include:
# Laravel 12 uses Orchestra Testbench 10
- laravel: 12.*
testbench: 10.*
# Laravel 11 uses Orchestra Testbench 9
- laravel: 11.*
testbench: 9.*
name: PHP ${{ matrix.php }} / L${{ matrix.laravel }} / ${{ matrix.dependency-version }}
name: PHP ${{ matrix.php }} / L${{ matrix.laravel }} / ${{ matrix.dependency-version }} / Shard ${{ matrix.shard }}/4

steps:

Expand All @@ -46,6 +47,29 @@ jobs:
with:
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Cache Playwright browsers
id: playwright-cache
uses: actions/cache@v3
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-latest
restore-keys: |
playwright-${{ runner.os }}-latest
playwright-${{ runner.os }}-

- name: Install and update Playwright
run: |
if [ ! -d ~/.cache/ms-playwright ]; then
npm install playwright@latest
npx playwright install --with-deps
fi

- name: Validate composer.json and composer.lock
run: composer validate --strict

Expand All @@ -61,19 +85,31 @@ jobs:
with:
php-version: ${{ matrix.php }}
coverage: xdebug
# extensions: mbstring, gd, intl
extensions: mbstring, gd, intl, pcntl

- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
composer update --${{ matrix.dependency-version }} --prefer-dist --no-progress --no-interaction
composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update
composer require "orchestra/testbench:${{ matrix.testbench }}" --dev --no-interaction --no-update
composer update --${{ matrix.dependency-version }} --prefer-dist --no-progress --no-interaction --no-scripts

- name: Setup testbench environment
run: |
cp workbench/.env.example workbench/.env
sed -i 's/APP_KEY=/APP_KEY=base64:ZQvPGC7uVADkjOgtGIIuCI8u3\/Pzu+VaRObIbHsgjCc=/' workbench/.env
sed -i 's/APP_ENV=local/APP_ENV=testing/' workbench/.env
grep "APP_KEY=base64:" workbench/.env
npm install
php vendor/bin/testbench vendor:publish --tag='filament-shield-config'
php vendor/bin/testbench filament:assets
php vendor/bin/testbench package:sync-skeleton

- name: Run test suite
run: composer test -- --coverage-clover ./coverage.xml
run: vendor/bin/pest --shard=${{ matrix.shard }}/4 --parallel --coverage-clover ./coverage.xml

- name: Upload coverage reports to Codecov
# Make sure the Codecov action is only executed once
if: matrix.php == '8.2' && matrix.laravel == '12.*' && matrix.dependency-version == 'prefer-stable'
if: matrix.php == '8.3' && matrix.laravel == '12.*' && matrix.dependency-version == 'prefer-stable' && matrix.shard == 1
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down
13 changes: 10 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@
"require-dev": {
"laravel/pint": "^1.21",
"orchestra/testbench": "^9.9|^10.0",
"pestphp/pest": "^3.7",
"pestphp/pest-plugin-livewire": "^3.0"
"pestphp/pest": "^4.0",
"pestphp/pest-plugin-browser": "^4.0",
"pestphp/pest-plugin-laravel": "^4.0",
"pestphp/pest-plugin-livewire": "^4.0"
},
"scripts": {
"post-autoload-dump": [
Expand All @@ -64,7 +66,12 @@
"post-install-cmd": "@setup",
"post-update-cmd": "@setup",
"format": "vendor/bin/pint",
"test": "vendor/bin/testbench package:test",
"test": "vendor/bin/testbench package:test --parallel",
"test-shard": "vendor/bin/pest --shard=%SHARD%/%SHARDS%",
"test-shard-1": "vendor/bin/pest --shard=1/4",
"test-shard-2": "vendor/bin/pest --shard=2/4",
"test-shard-3": "vendor/bin/pest --shard=3/4",
"test-shard-4": "vendor/bin/pest --shard=4/4",
"clear": "@php vendor/bin/testbench package:purge-skeleton --ansi",
"prepare": "@php vendor/bin/testbench package:discover --ansi",
"build": "@php vendor/bin/testbench workbench:build --ansi",
Expand Down
47 changes: 47 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@
"@commitlint/cli": "^19.7.1",
"@commitlint/config-conventional": "^19.7.1",
"husky": "^9.1.7"
},
"dependencies": {
"playwright": "^1.56.1"
}
}
48 changes: 48 additions & 0 deletions tests/Browser/CountryResourceBrowserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

use Eclipse\World\Filament\Clusters\World\Resources\CountryResource;
use Eclipse\World\Models\Country;
use Eclipse\World\Models\Region;

beforeEach(function () {
$this->setUpSuperAdmin();
});

test('can browse country resource page', function () {
$region = Region::factory()->create(['name' => 'Test Region']);
$country = Country::factory()->create([
'name' => 'Test Country',
'id' => 'TC',
'region_id' => $region->id,
]);

$this->visit(CountryResource::getUrl())
->assertSee('Countries')
->assertSee('Test Country')
->assertSee('TC')
->assertSee('Test Region');
});

test('can interact with country resource table', function () {
$region = Region::factory()->create(['name' => 'Browser Test Region']);
$country = Country::factory()->create([
'name' => 'Browser Test Country',
'id' => 'BTC',
'region_id' => $region->id,
]);

$this->visit(CountryResource::getUrl())
->assertSee('Browser Test Country')
->assertSee('BTC')
->assertSee('Browser Test Region')
->assertSee('Countries');
});

test('country resource page loads without JavaScript errors', function () {
$this->visit(CountryResource::getUrl())
->assertSee('Countries')
->assertDontSee('Uncaught')
->assertDontSee('ReferenceError')
->assertDontSee('TypeError')
->assertDontSee('SyntaxError');
});
93 changes: 93 additions & 0 deletions tests/Browser/VisualRegressionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

use Eclipse\World\Filament\Clusters\World\Resources\CountryResource;
use Eclipse\World\Filament\Clusters\World\Resources\CurrencyResource;
use Eclipse\World\Filament\Clusters\World\Resources\PostResource;
use Eclipse\World\Filament\Clusters\World\Resources\RegionResource;
use Eclipse\World\Models\Country;
use Eclipse\World\Models\Region;

beforeEach(function () {
$this->setUpSuperAdmin();
});

describe('Visual Regression Tests', function () {
test('country resource page visual regression', function () {
$region = Region::factory()->create(['name' => 'Visual Test Region']);
$country = Country::factory()->create([
'name' => 'Visual Test Country',
'id' => 'VT',
'a3_id' => 'VTC',
'num_code' => '999',
'flag' => '🏳️',
'region_id' => $region->id,
]);

$this->visit(CountryResource::getUrl())
->assertSee('Countries')
->assertSee('Visual Test Country')
->wait(1)
->assertScreenshotMatches();
});

test('currency resource page visual regression', function () {
$this->visit(CurrencyResource::getUrl())
->assertSee('Currencies')
->wait(1)
->assertScreenshotMatches();
});

test('post resource page visual regression', function () {
$this->visit(PostResource::getUrl())
->assertSee('Posts')
->wait(1)
->assertScreenshotMatches();
});

test('region resource page visual regression', function () {
$this->visit(RegionResource::getUrl())
->assertSee('Regions')
->wait(1)
->assertScreenshotMatches();
});

test('country resource page with data visual regression', function () {
$region1 = Region::factory()->create(['name' => 'Europe']);
$region2 = Region::factory()->create(['name' => 'Asia']);

Country::factory()->create([
'name' => 'Germany',
'id' => 'DE',
'a3_id' => 'DEU',
'num_code' => '276',
'flag' => '🇩🇪',
'region_id' => $region1->id,
]);

Country::factory()->create([
'name' => 'Japan',
'id' => 'JP',
'a3_id' => 'JPN',
'num_code' => '392',
'flag' => '🇯🇵',
'region_id' => $region2->id,
]);

Country::factory()->create([
'name' => 'United States',
'id' => 'US',
'a3_id' => 'USA',
'num_code' => '840',
'flag' => '🇺🇸',
'region_id' => $region1->id,
]);

$this->visit(CountryResource::getUrl())
->assertSee('Countries')
->assertSee('Germany')
->assertSee('Japan')
->assertSee('United States')
->wait(1)
->assertScreenshotMatches();
});
});
Loading