You've already forked wp-prometheus
feat: Add comprehensive PHPUnit test suite and CI/CD test gating (v0.5.0)
189 tests across 8 test classes covering all core plugin classes: CustomMetricBuilder, StorageFactory, Authentication, DashboardProvider, RuntimeCollector, Installer, Collector, and MetricsEndpoint. Added test job to Gitea release workflow that gates build-release. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
376
tests/Unit/Admin/DashboardProviderTest.php
Normal file
376
tests/Unit/Admin/DashboardProviderTest.php
Normal file
@@ -0,0 +1,376 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Magdev\WpPrometheus\Tests\Unit\Admin;
|
||||
|
||||
use Magdev\WpPrometheus\Admin\DashboardProvider;
|
||||
use Magdev\WpPrometheus\Tests\Helpers\GlobalFunctionState;
|
||||
use Magdev\WpPrometheus\Tests\Unit\TestCase;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
|
||||
#[CoversClass(DashboardProvider::class)]
|
||||
class DashboardProviderTest extends TestCase
|
||||
{
|
||||
private DashboardProvider $provider;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->provider = new DashboardProvider();
|
||||
}
|
||||
|
||||
// ── register_dashboard() - Validation ────────────────────────────
|
||||
|
||||
#[Test]
|
||||
public function register_with_inline_json_succeeds(): void
|
||||
{
|
||||
$result = $this->provider->register_dashboard('my-dashboard', [
|
||||
'title' => 'My Dashboard',
|
||||
'json' => '{"panels":[]}',
|
||||
]);
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_rejects_empty_slug(): void
|
||||
{
|
||||
$result = $this->provider->register_dashboard('', [
|
||||
'title' => 'Test',
|
||||
'json' => '{}',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_rejects_invalid_slug_characters(): void
|
||||
{
|
||||
// sanitize_key removes all non [a-z0-9_-] characters
|
||||
// A slug like '!@#' becomes '' after sanitize_key
|
||||
$result = $this->provider->register_dashboard('!@#', [
|
||||
'title' => 'Test',
|
||||
'json' => '{}',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_rejects_duplicate_builtin_slug(): void
|
||||
{
|
||||
$result = $this->provider->register_dashboard('wordpress-overview', [
|
||||
'title' => 'Override Built-in',
|
||||
'json' => '{}',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_rejects_duplicate_registered_slug(): void
|
||||
{
|
||||
$this->provider->register_dashboard('my-dashboard', [
|
||||
'title' => 'First',
|
||||
'json' => '{}',
|
||||
]);
|
||||
|
||||
$result = $this->provider->register_dashboard('my-dashboard', [
|
||||
'title' => 'Second',
|
||||
'json' => '{}',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_requires_title(): void
|
||||
{
|
||||
$result = $this->provider->register_dashboard('no-title', [
|
||||
'json' => '{}',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_requires_file_or_json(): void
|
||||
{
|
||||
$result = $this->provider->register_dashboard('no-content', [
|
||||
'title' => 'No Content',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_rejects_both_file_and_json(): void
|
||||
{
|
||||
$fileExists = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'file_exists');
|
||||
$fileExists->expects($this->any())->willReturn(true);
|
||||
|
||||
$isReadable = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'is_readable');
|
||||
$isReadable->expects($this->any())->willReturn(true);
|
||||
|
||||
$realpath = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'realpath');
|
||||
$realpath->expects($this->any())->willReturnArgument(0);
|
||||
|
||||
$result = $this->provider->register_dashboard('both', [
|
||||
'title' => 'Both',
|
||||
'file' => '/tmp/wordpress/wp-content/plugins/test/dashboard.json',
|
||||
'json' => '{}',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_file_requires_absolute_path(): void
|
||||
{
|
||||
$result = $this->provider->register_dashboard('relative', [
|
||||
'title' => 'Relative Path',
|
||||
'file' => 'relative/path/dashboard.json',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_file_must_exist(): void
|
||||
{
|
||||
$fileExists = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'file_exists');
|
||||
$fileExists->expects($this->any())->willReturn(false);
|
||||
|
||||
$result = $this->provider->register_dashboard('missing-file', [
|
||||
'title' => 'Missing File',
|
||||
'file' => '/tmp/wordpress/wp-content/plugins/test/nonexistent.json',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_file_rejects_path_traversal(): void
|
||||
{
|
||||
$fileExists = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'file_exists');
|
||||
$fileExists->expects($this->any())->willReturn(true);
|
||||
|
||||
$isReadable = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'is_readable');
|
||||
$isReadable->expects($this->any())->willReturn(true);
|
||||
|
||||
$realpath = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'realpath');
|
||||
$realpath->expects($this->any())->willReturnArgument(0);
|
||||
|
||||
$result = $this->provider->register_dashboard('evil', [
|
||||
'title' => 'Evil Dashboard',
|
||||
'file' => '/etc/passwd',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_file_accepts_path_under_wp_content(): void
|
||||
{
|
||||
$fileExists = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'file_exists');
|
||||
$fileExists->expects($this->any())->willReturn(true);
|
||||
|
||||
$isReadable = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'is_readable');
|
||||
$isReadable->expects($this->any())->willReturn(true);
|
||||
|
||||
$realpath = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'realpath');
|
||||
$realpath->expects($this->any())->willReturnArgument(0);
|
||||
|
||||
$result = $this->provider->register_dashboard('valid-file', [
|
||||
'title' => 'Valid File Dashboard',
|
||||
'file' => '/tmp/wordpress/wp-content/plugins/my-plugin/dashboard.json',
|
||||
]);
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_rejects_invalid_inline_json(): void
|
||||
{
|
||||
$result = $this->provider->register_dashboard('bad-json', [
|
||||
'title' => 'Bad JSON',
|
||||
'json' => '{invalid json',
|
||||
]);
|
||||
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function register_sets_source_to_third_party(): void
|
||||
{
|
||||
$this->provider->register_dashboard('ext-dashboard', [
|
||||
'title' => 'Extension',
|
||||
'json' => '{}',
|
||||
'plugin' => 'My Plugin',
|
||||
]);
|
||||
|
||||
$this->assertTrue($this->provider->is_third_party('ext-dashboard'));
|
||||
}
|
||||
|
||||
// ── get_available() ──────────────────────────────────────────────
|
||||
|
||||
#[Test]
|
||||
public function get_available_includes_builtin_dashboards(): void
|
||||
{
|
||||
$fileExists = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'file_exists');
|
||||
$fileExists->expects($this->any())->willReturn(true);
|
||||
|
||||
$available = $this->provider->get_available();
|
||||
|
||||
$this->assertArrayHasKey('wordpress-overview', $available);
|
||||
$this->assertArrayHasKey('wordpress-runtime', $available);
|
||||
$this->assertArrayHasKey('wordpress-woocommerce', $available);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function get_available_includes_registered_dashboards(): void
|
||||
{
|
||||
$fileExists = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'file_exists');
|
||||
$fileExists->expects($this->any())->willReturn(true);
|
||||
|
||||
$this->provider->register_dashboard('custom-dash', [
|
||||
'title' => 'Custom',
|
||||
'json' => '{"panels":[]}',
|
||||
]);
|
||||
|
||||
$available = $this->provider->get_available();
|
||||
$this->assertArrayHasKey('custom-dash', $available);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function get_available_excludes_builtin_with_missing_file(): void
|
||||
{
|
||||
$fileExists = $this->getFunctionMock('Magdev\\WpPrometheus\\Admin', 'file_exists');
|
||||
$fileExists->expects($this->any())->willReturn(false);
|
||||
|
||||
$available = $this->provider->get_available();
|
||||
|
||||
// Built-in dashboards should be excluded (files don't exist).
|
||||
$this->assertArrayNotHasKey('wordpress-overview', $available);
|
||||
}
|
||||
|
||||
// ── is_third_party() ─────────────────────────────────────────────
|
||||
|
||||
#[Test]
|
||||
public function builtin_dashboard_is_not_third_party(): void
|
||||
{
|
||||
$this->assertFalse($this->provider->is_third_party('wordpress-overview'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function registered_dashboard_is_third_party(): void
|
||||
{
|
||||
$this->provider->register_dashboard('ext-dash', [
|
||||
'title' => 'Extension Dashboard',
|
||||
'json' => '{}',
|
||||
]);
|
||||
|
||||
$this->assertTrue($this->provider->is_third_party('ext-dash'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function unknown_slug_is_not_third_party(): void
|
||||
{
|
||||
$this->assertFalse($this->provider->is_third_party('nonexistent'));
|
||||
}
|
||||
|
||||
// ── get_plugin_name() ────────────────────────────────────────────
|
||||
|
||||
#[Test]
|
||||
public function get_plugin_name_returns_name_for_registered(): void
|
||||
{
|
||||
$this->provider->register_dashboard('ext-dash', [
|
||||
'title' => 'Extension',
|
||||
'json' => '{}',
|
||||
'plugin' => 'My Awesome Plugin',
|
||||
]);
|
||||
|
||||
$this->assertSame('My Awesome Plugin', $this->provider->get_plugin_name('ext-dash'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function get_plugin_name_returns_null_for_builtin(): void
|
||||
{
|
||||
$this->assertNull($this->provider->get_plugin_name('wordpress-overview'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function get_plugin_name_returns_null_when_empty(): void
|
||||
{
|
||||
$this->provider->register_dashboard('no-plugin', [
|
||||
'title' => 'No Plugin',
|
||||
'json' => '{}',
|
||||
]);
|
||||
|
||||
$this->assertNull($this->provider->get_plugin_name('no-plugin'));
|
||||
}
|
||||
|
||||
// ── get_filename() ───────────────────────────────────────────────
|
||||
|
||||
#[Test]
|
||||
public function get_filename_returns_file_for_builtin(): void
|
||||
{
|
||||
$filename = $this->provider->get_filename('wordpress-overview');
|
||||
$this->assertSame('wordpress-overview.json', $filename);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function get_filename_returns_slug_json_for_inline(): void
|
||||
{
|
||||
$this->provider->register_dashboard('my-dash', [
|
||||
'title' => 'My Dashboard',
|
||||
'json' => '{}',
|
||||
]);
|
||||
|
||||
$this->assertSame('my-dash.json', $this->provider->get_filename('my-dash'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function get_filename_returns_null_for_unknown(): void
|
||||
{
|
||||
$this->assertNull($this->provider->get_filename('nonexistent'));
|
||||
}
|
||||
|
||||
// ── get_metadata() ───────────────────────────────────────────────
|
||||
|
||||
#[Test]
|
||||
public function get_metadata_returns_builtin_data(): void
|
||||
{
|
||||
$metadata = $this->provider->get_metadata('wordpress-overview');
|
||||
|
||||
$this->assertIsArray($metadata);
|
||||
$this->assertSame('WordPress Overview', $metadata['title']);
|
||||
$this->assertSame('builtin', $metadata['source']);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function get_metadata_returns_registered_data(): void
|
||||
{
|
||||
$this->provider->register_dashboard('ext-dash', [
|
||||
'title' => 'Extension',
|
||||
'description' => 'A test dashboard',
|
||||
'json' => '{}',
|
||||
'plugin' => 'TestPlugin',
|
||||
]);
|
||||
|
||||
$metadata = $this->provider->get_metadata('ext-dash');
|
||||
|
||||
$this->assertIsArray($metadata);
|
||||
$this->assertSame('Extension', $metadata['title']);
|
||||
$this->assertSame('third-party', $metadata['source']);
|
||||
$this->assertSame('TestPlugin', $metadata['plugin']);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function get_metadata_returns_null_for_unknown(): void
|
||||
{
|
||||
$this->assertNull($this->provider->get_metadata('nonexistent'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user