feat: write results warn about sections built like a library section (spec §5.5)
SimilarSections compares inserted sections (not global instances) with at most 200 editable library section entries by structure fingerprint, read lazily once per request, only while library IDs may be named (P13). lit/library-insert is not asked. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Library;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Block;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\LibraryContent;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
||||
use LIT\MCP\Integrations\Divi\Library\SimilarSections;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviChange;
|
||||
use LIT\MCP\Tests\Support\DiviFixtures;
|
||||
use LIT\MCP\Tests\Support\LibraryFixtures;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
|
||||
final class SimilarSectionsTest extends TestCase
|
||||
{
|
||||
private static function sectionLike1055(): Block
|
||||
{
|
||||
$root = LibraryContent::roots(LibraryContent::load(
|
||||
new Parser(),
|
||||
DiviFixtures::markup('stage3/library--library-abschnitt.html')
|
||||
))[0]->copy();
|
||||
$blurb = $root->children()[0]->children()[0]->children()[0];
|
||||
$attrs = $blurb->attrs();
|
||||
$attrs['title']['innerContent']['desktop']['value'] = 'Neuer Titel';
|
||||
$blurb->setAttrs($attrs);
|
||||
|
||||
return $root;
|
||||
}
|
||||
|
||||
/** @param list<string> $deniedRoles */
|
||||
private static function similar(array $deniedRoles = []): SimilarSections
|
||||
{
|
||||
LibraryFixtures::given([LibraryFixtures::item(1055), LibraryFixtures::item(1058)]);
|
||||
$store = LibraryFixtures::store();
|
||||
$store->allows('find')->andReturn([LibraryFixtures::item(1055), LibraryFixtures::item(1058)]);
|
||||
|
||||
return new SimilarSections(LibraryFixtures::access($deniedRoles, true, $store));
|
||||
}
|
||||
|
||||
public function testWarnsForAnInsertedSectionBuiltLikeALibrarySection(): void
|
||||
{
|
||||
$change = (new DiviChange('1 Divi-Knoten eingefügt'))->record(self::sectionLike1055(), 'inserted');
|
||||
|
||||
$warnings = self::similar()->warnings($change);
|
||||
|
||||
self::assertCount(1, $warnings);
|
||||
self::assertStringContainsString('„[Fixture] 1055“ (1055)', $warnings[0]);
|
||||
self::assertStringContainsString('lit-library-insert', $warnings[0]);
|
||||
self::assertStringContainsString('lit/library-find-similar', $warnings[0]);
|
||||
}
|
||||
|
||||
public function testOnlyInsertedSectionsAndOnlyWithLibraryAccess(): void
|
||||
{
|
||||
$moved = (new DiviChange('verschoben'))->record(self::sectionLike1055(), 'moved');
|
||||
$inserted = (new DiviChange('eingefügt'))->record(self::sectionLike1055(), 'inserted');
|
||||
|
||||
self::assertSame([], self::similar()->warnings($moved));
|
||||
self::assertSame([], self::similar(['divi_library'])->warnings($inserted));
|
||||
}
|
||||
|
||||
/** The library is read once per request, at most MAX_ITEMS section entries, only those the user may edit. */
|
||||
public function testReadsTheLibraryOnceBoundedAndOnlyEditableEntries(): void
|
||||
{
|
||||
LibraryFixtures::given([LibraryFixtures::item(1055)]);
|
||||
\Brain\Monkey\Functions\when('current_user_can')->alias(
|
||||
static fn (string $cap, mixed ...$args): bool => ! ($cap === 'edit_post' && ($args[0] ?? 0) === 1055)
|
||||
);
|
||||
$store = LibraryFixtures::store();
|
||||
$store->expects('find')->once()->with(['layout_type' => 'section'], SimilarSections::MAX_ITEMS - 1, 0)
|
||||
->andReturn([LibraryFixtures::item(1055)]);
|
||||
$similar = new SimilarSections(LibraryFixtures::access([], true, $store));
|
||||
$change = (new DiviChange('eingefügt'))->record(self::sectionLike1055(), 'inserted');
|
||||
|
||||
self::assertSame([], $similar->warnings($change), 'entry 1055 is not editable');
|
||||
self::assertSame([], $similar->warnings($change));
|
||||
}
|
||||
|
||||
/** No section inserted: the library is not read at all (cheap on every write). */
|
||||
public function testWithoutAnInsertedSectionTheLibraryIsNotRead(): void
|
||||
{
|
||||
LibraryFixtures::given([]);
|
||||
$store = LibraryFixtures::store();
|
||||
$store->expects('find')->never();
|
||||
$similar = new SimilarSections(LibraryFixtures::access([], true, $store));
|
||||
$row = self::sectionLike1055()->children()[0];
|
||||
|
||||
self::assertSame([], $similar->warnings((new DiviChange('eingefügt'))->record($row, 'inserted')));
|
||||
self::assertSame([], $similar->warnings((new DiviChange('geändert'))->record(self::sectionLike1055(), 'updated')));
|
||||
}
|
||||
|
||||
/** A global instance is already linked to the library – no warning, even for a global section entry. */
|
||||
public function testGlobalInstancesDoNotWarn(): void
|
||||
{
|
||||
$instance = \LIT\MCP\Integrations\Divi\BlockTree\GlobalInstance::of(self::sectionLike1055(), 1055);
|
||||
$change = (new DiviChange('eingefügt'))->record($instance, 'inserted');
|
||||
|
||||
self::assertSame([], self::similar()->warnings($change));
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,10 @@ use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||
use LIT\MCP\Integrations\Divi\Library\SimilarSections;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviChange;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviComposition;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviInsertAbility;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviPage;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviPageLoader;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviSaver;
|
||||
@@ -245,4 +247,48 @@ final class DiviWriterTest extends TestCase
|
||||
$log->assertRecorded();
|
||||
$log->assertPartials();
|
||||
}
|
||||
|
||||
/** Spec §5.5: the writer adds the similar-section warnings to every write result. */
|
||||
public function testWriteResultsCarryTheSimilarSectionWarning(): void
|
||||
{
|
||||
$content = DiviFixtures::markup('synthetic-basic.html');
|
||||
DiviFixtures::givenPost($content);
|
||||
Functions\when('get_preview_post_link')->justReturn('https://kunde.test/?page_id=7&preview=true');
|
||||
$similar = Mockery::mock(SimilarSections::class);
|
||||
$similar->allows('warnings')->andReturn(['Ein gleich aufgebauter Abschnitt liegt in der Divi-Bibliothek.']);
|
||||
$saved = [];
|
||||
$failures = [];
|
||||
$writer = DiviWriterFixture::writer($saved, $failures, false, null, null, null, $similar);
|
||||
|
||||
$result = (new DiviInsertAbility($writer))->execute([
|
||||
'post_id' => 7,
|
||||
'tree_rev' => \LIT\MCP\Abilities\Rev::of($content),
|
||||
'nodes' => [['type' => 'section', 'modules' => [['type' => 'text', 'content' => 'Neu']]]],
|
||||
]);
|
||||
|
||||
self::assertContains('Ein gleich aufgebauter Abschnitt liegt in der Divi-Bibliothek.', $result['warnings']);
|
||||
}
|
||||
|
||||
/** What lit/library-insert inserts comes from the library – no advice to use the library. */
|
||||
public function testLibraryInsertIsNotAskedForTheSimilarSectionWarning(): void
|
||||
{
|
||||
$content = DiviFixtures::markup('synthetic-basic.html');
|
||||
DiviFixtures::givenPost($content);
|
||||
Functions\when('get_preview_post_link')->justReturn('https://kunde.test/?page_id=7&preview=true');
|
||||
Functions\when('do_action')->justReturn(null);
|
||||
$similar = Mockery::mock(SimilarSections::class);
|
||||
$similar->expects('warnings')->never();
|
||||
$saved = [];
|
||||
$failures = [];
|
||||
$writer = DiviWriterFixture::writer($saved, $failures, false, null, null, null, $similar);
|
||||
$input = ['post_id' => 7, 'tree_rev' => Rev::of($content)];
|
||||
$page = $writer->page($input);
|
||||
$section = $page->index->find('s1')->copy();
|
||||
$page->document->children()[0]->removeChild($page->index->find('s1'));
|
||||
$change = (new DiviChange('eingefügt'))->record($section, 'inserted');
|
||||
|
||||
$result = $writer->save('lit/library-insert', $page, $change, $input);
|
||||
|
||||
self::assertSame(811, $result['revision_id']);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user