Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
103 lines
4.5 KiB
PHP
103 lines
4.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace LIT\MCP\Tests\Unit\Integrations\WordPress\Schema;
|
|
|
|
use Brain\Monkey\Functions;
|
|
use LIT\MCP\Integrations\WordPress\Schema\FieldDefinition;
|
|
use LIT\MCP\Integrations\WordPress\Schema\FieldValidator;
|
|
use LIT\MCP\Tests\Unit\TestCase;
|
|
|
|
final class FieldValidatorTest extends TestCase
|
|
{
|
|
/** @return array<string, FieldDefinition> */
|
|
private function definitions(): array
|
|
{
|
|
return [
|
|
'role' => new FieldDefinition('role', 'Funktion', 'string', 'pods', 'writable', true),
|
|
'level' => new FieldDefinition('level', 'Stufe', 'choice', 'pods', 'writable', false, false, [
|
|
['value' => 'junior', 'label' => 'Junior'],
|
|
['value' => 'senior', 'label' => 'Senior'],
|
|
]),
|
|
'mentor' => new FieldDefinition('mentor', 'Mentor', 'relation', 'pods', 'writable', false, false, null, [
|
|
'object_type' => 'post_type',
|
|
'name' => 'lit_person',
|
|
]),
|
|
'photos' => new FieldDefinition('photos', 'Fotos', 'file', 'pods', 'writable', false, true, null, [
|
|
'object_type' => 'media',
|
|
'name' => null,
|
|
]),
|
|
'start' => new FieldDefinition('start', 'Beginn', 'date', 'pods', 'writable'),
|
|
'secret' => new FieldDefinition('_secret', '_secret', 'string', 'meta', 'readonly'),
|
|
'city' => new FieldDefinition('city', 'city', 'unknown', 'sample', 'unknown'),
|
|
];
|
|
}
|
|
|
|
public function testValidValuesPassUnchanged(): void
|
|
{
|
|
Functions\when('get_post_type')->alias(static fn (int $id) => [12 => 'lit_person', 3 => 'attachment'][$id] ?? false);
|
|
$values = ['role' => 'Leitung', 'level' => 'senior', 'mentor' => 12, 'photos' => [3], 'start' => '2026-10-01'];
|
|
|
|
$result = (new FieldValidator())->validate($this->definitions(), $values, true);
|
|
|
|
self::assertSame([], $result['errors']);
|
|
self::assertSame($values, $result['values']);
|
|
}
|
|
|
|
public function testRequiredFieldMustBeSetOnCreateAndNotClearedOnUpdate(): void
|
|
{
|
|
$validator = new FieldValidator();
|
|
|
|
self::assertSame('Pflichtfeld fehlt.', $validator->validate($this->definitions(), [], true)['errors']['role']);
|
|
self::assertSame(
|
|
'Pflichtfeld darf nicht geleert werden.',
|
|
$validator->validate($this->definitions(), ['role' => ''], false)['errors']['role']
|
|
);
|
|
self::assertSame([], $validator->validate($this->definitions(), ['level' => 'junior'], false)['errors']);
|
|
}
|
|
|
|
public function testUnknownReadonlyAndInvalidValuesAreReported(): void
|
|
{
|
|
Functions\when('get_post_type')->alias(static fn (int $id) => [7 => 'page', 3 => 'attachment'][$id] ?? false);
|
|
|
|
$errors = (new FieldValidator())->validate($this->definitions(), [
|
|
'role' => 'x',
|
|
'nope' => 1,
|
|
'secret' => 'x',
|
|
'level' => 'expert',
|
|
'mentor' => 7,
|
|
'photos' => 3,
|
|
'start' => '01.10.2026',
|
|
], false)['errors'];
|
|
|
|
self::assertStringContainsString('lit-content-types', $errors['nope']);
|
|
self::assertSame('Feld ist schreibgeschützt.', $errors['secret']);
|
|
self::assertSame('Erlaubte Werte: junior, senior.', $errors['level']);
|
|
self::assertSame('Eintrag 7 ist vom Typ page, erwartet lit_person.', $errors['mentor']);
|
|
self::assertSame('Liste erwartet.', $errors['photos']);
|
|
self::assertSame('Datum im Format JJJJ-MM-TT erwartet.', $errors['start']);
|
|
self::assertArrayNotHasKey('role', $errors);
|
|
}
|
|
|
|
public function testMissingRelatedPostAndNonMediaAreRejected(): void
|
|
{
|
|
Functions\when('get_post_type')->alias(static fn (int $id) => [5 => 'page'][$id] ?? false);
|
|
|
|
$errors = (new FieldValidator())->validate($this->definitions(), ['mentor' => 99, 'photos' => [5]], false)['errors'];
|
|
|
|
self::assertSame('Eintrag 99 existiert nicht.', $errors['mentor']);
|
|
self::assertSame('5 ist kein Medium der Mediathek.', $errors['photos']);
|
|
}
|
|
|
|
public function testUnknownTypedFieldsAreAcceptedWithAWarningAndNullClears(): void
|
|
{
|
|
$result = (new FieldValidator())->validate($this->definitions(), ['city' => ['any' => 'thing'], 'level' => null], false);
|
|
|
|
self::assertSame([], $result['errors']);
|
|
self::assertSame(['city' => ['any' => 'thing'], 'level' => null], $result['values']);
|
|
self::assertCount(1, $result['warnings']);
|
|
self::assertStringContainsString('city', $result['warnings'][0]);
|
|
}
|
|
}
|