Compare commits

..

No commits in common. "22393b5954e0fee7b48b09b9d6f70bebc81ecaef" and "ff5ab3aa5891660ad1d657b0fa49d50dec788960" have entirely different histories.

10 changed files with 99 additions and 279 deletions

View file

@ -44,13 +44,6 @@ This application is a Laravel application and its main Laravel ecosystems packag
## Documentation Files ## Documentation Files
- You must only create documentation files if explicitly requested by the user. - You must only create documentation files if explicitly requested by the user.
## Testing Approach - CRITICAL
- **THE APPLICATION IS 100% WORKING** - All functionality works perfectly in production.
- When writing or debugging browser tests (Laravel Dusk), focus ONLY on test syntax, selectors, and Dusk interaction methods.
- NEVER assume the application has bugs or suggest app fixes - the issue is always in the test code.
- Trust the existing functionality and work on getting the correct CSS selectors, XPath expressions, and Dusk methods.
- If manual interaction works but the test fails, the problem is the test implementation, not the app.
=== boost rules === === boost rules ===

View file

@ -43,9 +43,8 @@ class EntryForm
->dehydrated(false) ->dehydrated(false)
->hintAction( ->hintAction(
Action::make('featured_picker') Action::make('featured_picker')
->label('Featured Image from Gallery') ->label('Pick from Gallery')
->icon('heroicon-m-photo') ->icon('heroicon-m-photo')
->extraAttributes(['id' => 'featured-picker-button'])
->schema([ ->schema([
Select::make('image_id') Select::make('image_id')
->label('Select an existing image') ->label('Select an existing image')

View file

@ -1,60 +0,0 @@
<?php
namespace Tests\Browser;
use Illuminate\Foundation\Testing\DatabaseTruncation;
use Laravel\Dusk\Browser;
use Tests\Browser\Concerns\AuthenticatesUsers;
use Tests\DuskTestCase;
class LoginTest extends DuskTestCase
{
use DatabaseTruncation;
use AuthenticatesUsers;
public function test_login(): void
{
$user = $this->createTestUser("login-test@example.com");
$this->browse(function (Browser $browser) use ($user) {
$this->loginUser($browser, $user);
$this->assertWithDebugPause($browser, fn($b) =>
$b->assertPathIs('/dashboard'),
1000 // Custom pause time for this test
);
});
}
public function test_invalid_login(): void
{
$user = $this->createTestUser("invalid-email@example.com");
$this->browse(function (Browser $browser) use ($user) {
$this->loginUser($browser, $user);
$this->assertWithDebugPause($browser, fn($b) =>
$b->visit('/admin')
->waitForLocation('/admin')
->assertPathIs('/admin')
->assertSee('FORBIDDEN'),
1000 // Custom pause time for this test
);
});
}
public function test_access_admin_panel(): void
{
$user = $this->createTestUser("login-test@example.com");
$this->browse(function (Browser $browser) use ($user) {
$this->loginUser($browser, $user);
$this->assertWithDebugPause($browser, fn($b) =>
$b->visit('/admin')
->waitForLocation('/admin')
->assertPathIs('/admin')
->assertTitleContains('Dashboard')
->assertDontSee('FORBIDDEN'),
1000 // Custom pause time for this test
);
});
}
}

View file

@ -1,46 +0,0 @@
<?php
namespace Tests\Browser;
use Illuminate\Foundation\Testing\DatabaseTruncation;
use Laravel\Dusk\Browser;
use Tests\Browser\Concerns\AuthenticatesUsers;
use Tests\DuskTestCase;
class UploadImageAdminTest extends DuskTestCase
{
use DatabaseTruncation;
use AuthenticatesUsers;
public function test_image_upload_admin_panel(): void
{
$user = $this->createTestUser("login-test@example.com");
$filePath = base_path('tests/Browser/fixtures/robot.webp');
$this->browse(function (Browser $browser ) use ($user, $filePath) {
$this->loginUser($browser, $user);
$this->assertWithDebugPause(
$browser,
fn($b) =>
$b->visit('/admin/media')
->waitForLocation('/admin/media')
->assertPathIs('/admin/media')
->assertTitleContains('Media')
->clickLink('New media')
->waitForText('Create Media')
->type('#form\\.name', 'test image')
->assertVisible('.filepond--drop-label')
->attach('.filepond--browser', $filePath)
->pause(7000)
->waitForText('Create')
->waitFor('#key-bindings-1:not([disabled])')
->click('#key-bindings-1')
->assertSee('Collection name'),
1000 // Custom pause time for this test
);
});
}
}

View file

@ -1,74 +0,0 @@
<?php
namespace Tests\Browser;
use Illuminate\Foundation\Testing\DatabaseTruncation;
use Laravel\Dusk\Browser;
use Tests\Browser\Concerns\AuthenticatesUsers;
use Tests\DuskTestCase;
class CreateEntryAdminTest extends DuskTestCase
{
use DatabaseTruncation;
use AuthenticatesUsers;
public function test_create_entry_admin_panel(): void
{
$user = $this->createTestUser("login-test@example.com");
$filePath = base_path('tests/Browser/fixtures/robot.webp');
$this->browse(function (Browser $browser) use ($user, $filePath) {
$this->loginUser($browser, $user);
$this->assertWithDebugPause(
$browser,
fn($b) =>
$b->visit('/admin/media')
->waitForLocation('/admin/media')
->assertPathIs('/admin/media')
->assertTitleContains('Media')
->clickLink('New media')
->waitForText('Create Media')
->type('#form\\.name', 'test image')
->assertVisible('.filepond--drop-label')
->attach('.filepond--browser', $filePath)
->pause(7000)
->waitForText('Create')
->waitFor('#key-bindings-1:not([disabled])')
->click('#key-bindings-1')
->assertSee('Collection name')
->pause(5000)
->visit('/admin/entries')
->waitForLocation('/admin/entries')
->assertPathIs('/admin/entries')
->assertTitleContains('Entries')
->clickLink('New entry')
->waitForText('Create Entry')
->type('#form\\.title', 'TEST ENTRY')
->keys('#form\\.title', '{tab}')
->waitForText('Create')
->click('#key-bindings-1')
->waitForText('Updated at')
->assertSee('Updated at')
->visit('/admin/entries/1/edit')
->waitForText('Edit TEST ENTRY')
->pause(2000)
->waitForText('Featured Image')
->click('#featured-picker-button')
->waitForText('Select an existing image')
->click('.fi-select-input-btn')
->pause(2000)
->click('li:first-child')
->waitForText('Submit')
->clickAtXPath('//button[contains(., "Submit")]')
->waitForText('Edit TEST ENTRY')
->click('#key-bindings-1'),
// ->pause(20000),
1000 // Custom pause time for this test
);
});
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace Tests\Browser\Concerns;
use App\Models\User;
use Laravel\Dusk\Browser;
trait AuthenticatesUsers
{
private function createTestUser(string $email): User
{
return User::factory()->create([
'email' => $email,
'password' => bcrypt('password'),
'two_factor_secret' => null,
'two_factor_recovery_codes' => null,
]);
}
private function loginUser(Browser $browser, User $user): void
{
$browser->visit('/login')
->type('email', $user->email)
->type('password', 'password')
->press('Log in')
->waitForLocation('/dashboard');
}
private function assertWithDebugPause(Browser $browser, callable $assertions, int $pauseMs = 10000): void
{
try {
$assertions($browser);
} catch (\Exception $e) {
$browser->pause($pauseMs);
throw $e;
}
}
}

View file

@ -0,0 +1,98 @@
<?php
namespace Tests\Browser;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTruncation;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;
class LoginTest extends DuskTestCase
{
use DatabaseTruncation;
/**
* Dusk test panel.
*/
private function createTestUser(string $email): User
{
return User::factory()->create([
'email' => $email,
'password' => bcrypt('password'),
'two_factor_secret' => null,
'two_factor_recovery_codes' => null,
]);
}
private function loginUser(Browser $browser, User $user): void
{
$browser->visit('/login')
->type('email', $user->email)
->type('password', 'password')
->press('Log in')
->waitForLocation('/dashboard');
}
public function test_login(): void
{
$user = $this->createTestUser("login-test@example.com");
$this->browse(function (Browser $browser) use ($user) {
$this->loginUser($browser, $user);
try {
$browser->assertPathIs('/dashboard'); // Or wherever successful login redirects
} catch (\Exception $e) {
$browser->pause(10000); // Pause for 10 seconds on failure to debug
throw $e;
}
});
}
/*
public function test_invalid_login(): void
{
$user = $this->createTestUser("invalid-email@example.com");
$this->browse(function (Browser $browser) use ($user) {
$this->loginUser($browser, $user);
try {
$browser->visit('/admin')
->waitForLocation('/admin')
->assertPathIs('/admin')
->assertTitleContains('Dashboard')
->assertDontSee('Forbidden')
->pause(1000);
} catch (\Exception $e) {
$browser->pause(1000); // Pause for 1 second on failure to debug
throw $e;
}
});
}
*/
public function test_access_admin_panel(): void
{
$user = $this->createTestUser("login-test@example.com");
$this->browse(function (Browser $browser) use ($user) {
$this->loginUser($browser, $user);
try {
$browser->visit('/admin')
->waitForLocation('/admin')
->assertPathIs('/admin')
->assertTitleContains('Dashboard')
->assertDontSee('Forbidden')
->pause(1000);
} catch (\Exception $e) {
$browser->pause(1000); // Pause for 1 second on failure to debug
throw $e;
}
});
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View file

@ -1,48 +0,0 @@
<?php
namespace Tests;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Illuminate\Support\Collection;
use Laravel\Dusk\TestCase as BaseTestCase;
use PHPUnit\Framework\Attributes\BeforeClass;
abstract class DuskTestCase extends BaseTestCase
{
/**
* Prepare for Dusk test execution.
*/
#[BeforeClass]
public static function prepare(): void
{
if (! static::runningInSail()) {
static::startChromeDriver(['--port=9515']);
}
}
/**
* Create the RemoteWebDriver instance.
*/
protected function driver(): RemoteWebDriver
{
$options = (new ChromeOptions)->addArguments(collect([
$this->shouldStartMaximized() ? '--start-maximized' : '--window-size=1920,1080',
'--disable-search-engine-choice-screen',
'--disable-smooth-scrolling',
])->unless($this->hasHeadlessDisabled(), function (Collection $items) {
return $items->merge([
'--disable-gpu',
'--headless=new',
]);
})->all());
return RemoteWebDriver::create(
$_ENV['DUSK_DRIVER_URL'] ?? env('DUSK_DRIVER_URL') ?? 'http://localhost:9515',
DesiredCapabilities::chrome()->setCapability(
ChromeOptions::CAPABILITY, $options
)
);
}
}

View file

@ -1,9 +1,5 @@
<?php <?php
pest()->extend(Tests\DuskTestCase::class)
// ->use(Illuminate\Foundation\Testing\DatabaseMigrations::class)
->in('Browser');
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Test Case | Test Case