feat: admin settings page UI/UX pass with WordPress-native patterns
- Header: h1 + logo in a wrapping flex row, hr.wp-header-end before the tabs, aria-current on the active tab; own CSS/JS enqueued only on this screen. - Verbindung: ordered "So verbindest du Claude" steps, copy button (core clipboard.js + wp.a11y.speak), Site-Health-style status list, German details. - Zugriff: roles as form-table fieldset, connections with site date format, empty-state row, confirm on revoke; ConnectionUsage records last use via WP_Application_Passwords::record_application_password_usage (once a day). - Tools: plain-language legend, counter as inline notice, groups as core postboxes (postbox.js toggles, per-user closed state, summary when closed), fixed column widths with new "Art" column, submit above and below. - Protokoll: site-timezone times with UTC tooltip, result icons, filters with labels in the list table nav, retention link to Limits. - Limits: short labels with units and descriptions; snapshot count hidden but preserved. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Admin;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Admin\ConnectionUsage;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
|
||||
final class ConnectionUsageTest extends TestCase
|
||||
{
|
||||
/** @var list<array{int, string}> */
|
||||
private array $recorded = [];
|
||||
|
||||
private function usage(?array $claims): ConnectionUsage
|
||||
{
|
||||
return new ConnectionUsage(
|
||||
static fn (string $token): ?array => $token === 'valid-token' ? $claims : null,
|
||||
function (int $userId, string $uuid): void {
|
||||
$this->recorded[] = [$userId, $uuid];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private function request(string $route = '/mcp/mcp-oauth-server', string $auth = 'Bearer valid-token'): WP_REST_Request
|
||||
{
|
||||
return new WP_REST_Request($route, ['authorization' => $auth]);
|
||||
}
|
||||
|
||||
public function testRegistersAfterTheRouteCallback(): void
|
||||
{
|
||||
$usage = $this->usage([]);
|
||||
Functions\expect('add_filter')->once()->with('rest_request_after_callbacks', [$usage, 'record'], 10, 3);
|
||||
|
||||
$usage->register();
|
||||
}
|
||||
|
||||
public function testRecordsUsageOfTheTokensApplicationPasswordForTheAuthenticatedUser(): void
|
||||
{
|
||||
Functions\when('get_current_user_id')->justReturn(7);
|
||||
$response = ['jsonrpc' => '2.0'];
|
||||
|
||||
$result = $this->usage(['sub' => 7, 'app_pass_id' => 'uuid-1'])->record($response, [], $this->request());
|
||||
|
||||
self::assertSame($response, $result);
|
||||
self::assertSame([[7, 'uuid-1']], $this->recorded);
|
||||
}
|
||||
|
||||
public function testIgnoresOtherRoutesFailedRequestsAndForeignOrInvalidTokens(): void
|
||||
{
|
||||
Functions\when('get_current_user_id')->justReturn(7);
|
||||
$claims = ['sub' => 7, 'app_pass_id' => 'uuid-1'];
|
||||
|
||||
$this->usage($claims)->record([], [], $this->request('/wp/v2/posts'));
|
||||
$this->usage($claims)->record(new WP_Error('unauthorized', 'x'), [], $this->request());
|
||||
$this->usage($claims)->record([], [], $this->request('/mcp/mcp-oauth-server', 'Basic abc'));
|
||||
$this->usage($claims)->record([], [], $this->request('/mcp/mcp-oauth-server', 'Bearer forged'));
|
||||
$this->usage(['sub' => 8, 'app_pass_id' => 'uuid-1'])->record([], [], $this->request());
|
||||
$this->usage(['sub' => 7])->record([], [], $this->request());
|
||||
|
||||
self::assertSame([], $this->recorded);
|
||||
}
|
||||
|
||||
public function testNeverBreaksTheResponseWhenDecodingOrRecordingFails(): void
|
||||
{
|
||||
Functions\when('get_current_user_id')->justReturn(7);
|
||||
$usage = new ConnectionUsage(
|
||||
static fn (): ?array => throw new \RuntimeException('bad secret'),
|
||||
static function (): void {
|
||||
}
|
||||
);
|
||||
|
||||
self::assertSame(['ok'], $usage->record(['ok'], [], $this->request()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user