From 330d6922a4d63f023ffd12dae4b22a92cad6ee5c Mon Sep 17 00:00:00 2001 From: Mark Gregory Date: Mon, 15 Jun 2026 11:59:41 +0100 Subject: [PATCH] latest test updates --- ...26_06_10_000000_create_platform_tables.php | 12 +++++- .../Concerns/InteractsWithWmsBrowser.php | 35 ++++++++++++---- tests/CreatesApplication.php | 21 ++++++++++ tests/DuskTestCase.php | 40 +++++++++++++------ 4 files changed, 88 insertions(+), 20 deletions(-) create mode 100644 tests/CreatesApplication.php diff --git a/Modules/Platform/database/migrations/2026_06_10_000000_create_platform_tables.php b/Modules/Platform/database/migrations/2026_06_10_000000_create_platform_tables.php index 9e951459..dcd9215f 100644 --- a/Modules/Platform/database/migrations/2026_06_10_000000_create_platform_tables.php +++ b/Modules/Platform/database/migrations/2026_06_10_000000_create_platform_tables.php @@ -69,12 +69,22 @@ return new class extends Migration */ public function down(): void { + Schema::disableForeignKeyConstraints(); + Schema::dropIfExists('payments'); Schema::dropIfExists('license_keys'); + Schema::table('users', function (Blueprint $table): void { $table->dropConstrainedForeignId('company_id'); - $table->dropColumn(['is_platform_admin', 'is_company_admin', 'status']); + $table->dropColumn([ + 'is_platform_admin', + 'is_company_admin', + 'status', + ]); }); + Schema::dropIfExists('companies'); + + Schema::enableForeignKeyConstraints(); } }; diff --git a/tests/Browser/Concerns/InteractsWithWmsBrowser.php b/tests/Browser/Concerns/InteractsWithWmsBrowser.php index f31faf08..b120c285 100644 --- a/tests/Browser/Concerns/InteractsWithWmsBrowser.php +++ b/tests/Browser/Concerns/InteractsWithWmsBrowser.php @@ -33,11 +33,29 @@ trait InteractsWithWmsBrowser protected function clickSidebarHref(Browser $browser, string $path): void { - $browser->script(<<script(sprintf( + <<<'JS' +const expectedPath = %s; +const links = Array.from(document.querySelectorAll('a')); +const link = links.find((candidate) => { + const href = candidate.getAttribute('href') || ''; + try { + return new URL(href, window.location.origin).pathname === expectedPath; + } catch (error) { + return href === expectedPath || href.endsWith(expectedPath); + } +}); - $browser->waitForLocation($path, 10); +if (link) { + link.click(); +} else { + window.location.href = expectedPath; +} +JS, + json_encode($path, JSON_THROW_ON_ERROR) + )); + + $browser->waitForLocation($path, 15); } protected function openMobileNavigation(Browser $browser): void @@ -45,15 +63,18 @@ trait InteractsWithWmsBrowser $browser->resize(390, 844) ->waitFor('.wms-mobile-header', 10) ->assertVisible('.wms-mobile-header') - ->assertVisible('[data-wms-mobile-open]') - ->click('[data-wms-mobile-open]') - ->waitUntil('document.documentElement.dataset.wmsMobileSidebar === "open"', 10) + ->assertPresent('[data-wms-mobile-open]'); + + $browser->script('document.querySelector("[data-wms-mobile-open]")?.click();'); + + $browser->waitUntil('document.documentElement.dataset.wmsMobileSidebar === "open"', 10) ->assertAttribute('[data-wms-mobile-open]', 'aria-expanded', 'true'); } protected function closeMobileNavigation(Browser $browser): void { $browser->script('document.querySelector("[data-wms-mobile-close]")?.click();'); + $browser->waitUntil('document.documentElement.dataset.wmsMobileSidebar !== "open"', 10) ->assertAttribute('[data-wms-mobile-open]', 'aria-expanded', 'false'); } diff --git a/tests/CreatesApplication.php b/tests/CreatesApplication.php new file mode 100644 index 00000000..cc683011 --- /dev/null +++ b/tests/CreatesApplication.php @@ -0,0 +1,21 @@ +make(Kernel::class)->bootstrap(); + + return $app; + } +} diff --git a/tests/DuskTestCase.php b/tests/DuskTestCase.php index 8a258190..80677b60 100644 --- a/tests/DuskTestCase.php +++ b/tests/DuskTestCase.php @@ -5,7 +5,6 @@ namespace Tests; use Facebook\WebDriver\Chrome\ChromeOptions; use Facebook\WebDriver\Remote\DesiredCapabilities; use Facebook\WebDriver\Remote\RemoteWebDriver; -use Illuminate\Support\Facades\Artisan; use Laravel\Dusk\TestCase as BaseTestCase; use PHPUnit\Framework\Attributes\BeforeClass; @@ -22,6 +21,7 @@ abstract class DuskTestCase extends BaseTestCase if (! static::runningInSail()) { static::ensureChromeDriverBinaryAlias(); static::startChromeDriver(['--port=9515']); + static::waitForChromeDriver(); } } @@ -50,11 +50,13 @@ abstract class DuskTestCase extends BaseTestCase /** * Dusk may install a differently named macOS Apple Silicon binary. - * Laravel Dusk still asks for chromedriver-mac-arm, so create that alias safely. + * + * This method intentionally does not use base_path(), app(), or Artisan because + * PHPUnit calls BeforeClass before Laravel has booted the application container. */ private static function ensureChromeDriverBinaryAlias(): void { - $binDirectory = base_path('vendor/laravel/dusk/bin'); + $binDirectory = dirname(__DIR__).'/vendor/laravel/dusk/bin'; $expected = $binDirectory.'/chromedriver-mac-arm'; if (is_file($expected)) { @@ -67,12 +69,6 @@ abstract class DuskTestCase extends BaseTestCase @mkdir($binDirectory, 0755, true); } - try { - Artisan::call('dusk:chrome-driver'); - } catch (\Throwable) { - // - } - $candidates = array_values(array_filter( glob($binDirectory.'/chromedriver*') ?: [], static function (string $path) use ($expected): bool { @@ -85,9 +81,9 @@ abstract class DuskTestCase extends BaseTestCase usort($candidates, static function (string $left, string $right): int { $score = static fn (string $path): int => - str_contains($path, 'mac-arm64') ? 0 - : (str_contains($path, 'mac-arm') ? 1 - : (str_contains($path, 'mac') ? 2 : 3)); + str_contains($path, 'mac-arm64') ? 0 + : (str_contains($path, 'mac-arm') ? 1 + : (str_contains($path, 'mac') ? 2 : 3)); return $score($left) <=> $score($right); }); @@ -97,4 +93,24 @@ abstract class DuskTestCase extends BaseTestCase @chmod($expected, 0755); } } + + /** + * Wait until ChromeDriver is listening before the first browser session starts. + */ + private static function waitForChromeDriver(): void + { + $deadline = microtime(true) + 5.0; + + do { + $connection = @fsockopen('127.0.0.1', 9515); + + if (is_resource($connection)) { + fclose($connection); + + return; + } + + usleep(100_000); + } while (microtime(true) < $deadline); + } }