WpLinkTargets answers the library, internal "_" types and every type without a Divi post_link_url option like a missing ID; replace-text strips library IDs only from global subtrees. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
89 lines
4.4 KiB
PHP
89 lines
4.4 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Pages;
|
||
|
||
use Brain\Monkey\Functions;
|
||
use LIT\MCP\Integrations\Divi\Pages\WpLinkTargets;
|
||
use LIT\MCP\Integrations\Divi\Pages\WpValueSanitizer;
|
||
use LIT\MCP\Tests\Unit\TestCase;
|
||
use WP_Post;
|
||
|
||
final class WpValueSanitizerTest extends TestCase
|
||
{
|
||
protected function setUp(): void
|
||
{
|
||
parent::setUp();
|
||
Functions\when('wp_kses_post')->alias(static fn (string $value): string => 'kses(' . $value . ')');
|
||
Functions\when('esc_url_raw')->alias(static fn (string $value): string => 'url(' . $value . ')');
|
||
}
|
||
|
||
public function testEditorsGetKsesForRichTextAndCode(): void
|
||
{
|
||
Functions\when('current_user_can')->alias(static fn (string $cap): bool => $cap !== 'unfiltered_html');
|
||
$sanitizer = new WpValueSanitizer();
|
||
|
||
self::assertSame('kses(<iframe></iframe>)', $sanitizer->html('<iframe></iframe>'));
|
||
self::assertSame('kses(<script>x</script>)', $sanitizer->code('<script>x</script>'));
|
||
self::assertFalse($sanitizer->allowsUnfilteredHtml());
|
||
}
|
||
|
||
public function testAdministratorsKeepRichTextAndCodeUnfiltered(): void
|
||
{
|
||
// Ruling S4: html() depends on unfiltered_html like code() – admin embeds survive updates.
|
||
Functions\when('current_user_can')->alias(static fn (string $cap): bool => $cap === 'unfiltered_html');
|
||
$sanitizer = new WpValueSanitizer();
|
||
|
||
self::assertSame('<iframe src="https://x.test"></iframe>', $sanitizer->html('<iframe src="https://x.test"></iframe>'));
|
||
self::assertSame('<script>x</script>', $sanitizer->code('<script>x</script>'));
|
||
self::assertTrue($sanitizer->allowsUnfilteredHtml());
|
||
}
|
||
|
||
public function testTextAndUrlDoNotDependOnTheRole(): void
|
||
{
|
||
Functions\when('current_user_can')->justReturn(true);
|
||
$sanitizer = new WpValueSanitizer();
|
||
|
||
self::assertSame('Hallo', $sanitizer->text('<b>Hallo</b>'));
|
||
self::assertSame('url(https://x.test/a b)', $sanitizer->url(' https://x.test/a b '));
|
||
}
|
||
|
||
public function testCanReadPostAsksWordPress(): void
|
||
{
|
||
Functions\when('current_user_can')->alias(static fn (string $cap, int $id = 0): bool => $cap === 'read_post' && $id === 12);
|
||
$sanitizer = new WpValueSanitizer();
|
||
|
||
self::assertTrue($sanitizer->canReadPost(12));
|
||
self::assertFalse($sanitizer->canReadPost(13));
|
||
}
|
||
|
||
/** Ruling P10: the full form uses the {{link:}} targets – attachments, trash and unreadable entries are none. */
|
||
public function testLinkTargetTypeFollowsTheLinkTargets(): void
|
||
{
|
||
Functions\when('get_post')->alias(static fn (int $id): ?WP_Post => match ($id) {
|
||
12 => new WP_Post(['ID' => 12, 'post_type' => 'page', 'post_status' => 'draft']),
|
||
13 => new WP_Post(['ID' => 13, 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_parent' => 12]),
|
||
14 => new WP_Post(['ID' => 14, 'post_type' => 'page', 'post_status' => 'trash']),
|
||
16 => new WP_Post(['ID' => 16, 'post_type' => 'page', 'post_status' => 'private']),
|
||
17 => new WP_Post(['ID' => 17, 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_parent' => 0]),
|
||
18 => new WP_Post(['ID' => 18, 'post_type' => 'attachment', 'post_status' => 'trash', 'post_parent' => 0]),
|
||
19 => new WP_Post(['ID' => 19, 'post_type' => 'attachment', 'post_status' => 'private', 'post_parent' => 0]),
|
||
20 => new WP_Post(['ID' => 20, 'post_type' => 'post', 'post_status' => 'publish']),
|
||
default => null,
|
||
});
|
||
Functions\when('current_user_can')->alias(static fn (string $cap, int $id): bool => $id !== 16);
|
||
$sanitizer = new WpValueSanitizer(new WpLinkTargets(static fn (string $type): bool => $type !== 'wp_block'));
|
||
|
||
self::assertSame('page', $sanitizer->linkTargetType(12));
|
||
self::assertSame('post', $sanitizer->linkTargetType(20));
|
||
self::assertNull($sanitizer->linkTargetType(13), 'attached attachment');
|
||
self::assertNull($sanitizer->linkTargetType(14), 'trashed');
|
||
self::assertNull($sanitizer->linkTargetType(15), 'missing');
|
||
self::assertNull($sanitizer->linkTargetType(16), 'unreadable');
|
||
self::assertNull($sanitizer->linkTargetType(17), 'unattached attachment');
|
||
self::assertNull($sanitizer->linkTargetType(18), 'trashed attachment');
|
||
self::assertNull($sanitizer->linkTargetType(19), 'attachment with an own status');
|
||
}
|
||
}
|