File: /home/xedaptot/ai.naniguide.com/tests/Unit/PluginLifecycleTest.php
<?php
/**
* Plugin lifecycle integration test.
*
* NOTE: All assertions are in a single test intentionally.
*
* `plugin:init` loads the plugin's ServiceProvider into PHP's class registry.
* PHP never unloads classes within a process, and each Pest test creates a fresh
* Application container. Re-calling `App::register()` for the same provider in a
* later test would re-run `register()` — which calls `define()` on already-defined
* constants, throwing an ErrorException. Keeping everything in one test sidesteps
* that by ensuring the ServiceProvider is registered only once.
*/
use App\Model\Plugin;
use Illuminate\Support\Facades\Schema;
uses(\Tests\TestCase::class);
const TEST_PLUGIN = 'testvendor/testplugin';
const TEST_TABLE = 'testvendor_testplugin_settings';
function cleanupTestPlugin(): void
{
Schema::dropIfExists(TEST_TABLE);
$pluginDir = storage_path('app/plugins/' . TEST_PLUGIN);
if (file_exists($pluginDir)) {
\Illuminate\Support\Facades\File::deleteDirectory($pluginDir);
}
Plugin::where('name', TEST_PLUGIN)->delete();
}
beforeEach(fn () => cleanupTestPlugin());
afterEach(fn () => cleanupTestPlugin());
// ---------------------------------------------------------------------------
test('plugin lifecycle: scaffold → activate → delete', function () {
// ── 1. Scaffold ──────────────────────────────────────────────────────────
\Artisan::call('plugin:init', ['name' => TEST_PLUGIN]);
$plugin = Plugin::where('name', TEST_PLUGIN)->first();
expect($plugin)->not->toBeNull('plugin must be registered in DB after init');
expect($plugin->status)->toBe(Plugin::STATUS_INACTIVE);
// composer.json rendered with correct name
$composerPath = storage_path('app/plugins/' . TEST_PLUGIN . '/composer.json');
expect(file_exists($composerPath))->toBeTrue();
$composer = json_decode(file_get_contents($composerPath), true);
expect($composer['name'])->toBe(TEST_PLUGIN);
// migration file renamed from the template placeholder
$migrationFile = storage_path(
'app/plugins/' . TEST_PLUGIN .
'/database/migrations/2000_01_01_000000_create_testvendor_testplugin_settings_table.php'
);
expect(file_exists($migrationFile))->toBeTrue('migration file must be renamed from placeholder');
// table must NOT exist yet (activation hasn't run)
expect(Schema::hasTable(TEST_TABLE))->toBeFalse('settings table must not exist before activation');
// ── 2. Activate ───────────────────────────────────────────────────────────
$plugin->activate();
expect(Schema::hasTable(TEST_TABLE))->toBeTrue('settings table must exist after activation');
expect($plugin->fresh()->status)->toBe(Plugin::STATUS_ACTIVE);
// ── 3. Delete ─────────────────────────────────────────────────────────────
$plugin->deleteAndCleanup();
expect(Schema::hasTable(TEST_TABLE))->toBeFalse('settings table must be gone after deletion');
expect(Plugin::where('name', TEST_PLUGIN)->exists())->toBeFalse('DB record must be removed');
expect(file_exists(storage_path('app/plugins/' . TEST_PLUGIN)))->toBeFalse('plugin directory must be removed');
});