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')); } }