fix: lit-content-create mit divi auf einer Website ohne Divi verlangt keine Fähigkeiten – execute() antwortet mit unsupported (Divi 5 ist nicht aktiv) statt divi_incompatible samt refused-Eintrag

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-18 22:48:23 +02:00
co-authored by Claude Opus 5.5
parent 39143c01d0
commit 56947e54cf
4 changed files with 36 additions and 2 deletions
@@ -112,11 +112,17 @@ final class ContentCreateAbility implements Ability, DeclaresRequirements
/**
* Without divi the call stays in WordPress and needs nothing; with divi it needs what the ContentComposer says it
* needs (the Divi integration names its capabilities), so the guard refuses before a draft is inserted.
* needs (the Divi integration names its capabilities), so the guard refuses before a draft is inserted. Without an
* available composer (Divi 5 not active) nothing is required either: execute() then answers with the precise
* unsupported error instead of the guard reporting locked capabilities.
*/
public function requirements(array $input): array
{
return array_key_exists('divi', $input) && $this->divi !== null ? $this->divi->requirements() : [];
if (! array_key_exists('divi', $input) || $this->divi === null || ! $this->divi->available()) {
return [];
}
return $this->divi->requirements();
}
public function execute(array $input): mixed
@@ -208,6 +208,7 @@ final class DiviFeatureGateTest extends TestCase
private function composerNeeding(string ...$ids): ContentComposer
{
$composer = Mockery::mock(ContentComposer::class);
$composer->allows('available')->andReturn(true);
$composer->allows('requirements')->andReturn(array_values($ids));
return $composer;
@@ -237,6 +238,20 @@ final class DiviFeatureGateTest extends TestCase
self::assertSame('lit/content-create', $log->records[0]['ability']);
}
public function testContentCreateWithDiviOnASiteWithoutDiviIsLeftToTheToolItself(): void
{
DiviFeatureFixtures::lock(DiviFeature::PageWrite, ReleaseState::Incompatible);
$composer = Mockery::mock(ContentComposer::class);
$composer->allows('available')->andReturn(false);
$composer->shouldNotReceive('requirements');
$tool = $this->contentCreate($composer);
self::assertNull(
$this->gate(FakeChangeLog::forbidden())->refusal($tool, ['post_type' => 'page', 'divi' => [[]]]),
'no divi_incompatible and no refused entry: execute() answers "Divi 5 ist nicht aktiv"'
);
}
public function testContentCreateWithDiviRunsWhenOnlyOtherFeaturesAreLocked(): void
{
DiviFeatureFixtures::useStates([
@@ -216,6 +216,7 @@ final class DiviToolFeaturesTest extends TestCase
{
$divi = new DiviIntegration(Mockery::mock(ContentSchema::class), FakeChangeLog::forbidden());
$composer = Mockery::mock(ContentComposer::class);
$composer->allows('available')->andReturn(true);
$composer->allows('requirements')->andReturn(self::COMPOSE);
$wordPress = new WordPressIntegration(
Mockery::mock(ContentSchema::class),
@@ -103,6 +103,18 @@ final class ContentCreateDiviTest extends TestCase
self::assertSame([], $this->ability(null)->requirements(self::INPUT), 'no composer: the call is refused anyway');
}
public function testRequirementsAreEmptyWhenTheComposerIsUnavailable(): void
{
$composer = $this->composer(available: false);
$composer->shouldNotReceive('requirements');
self::assertSame(
[],
$this->ability($composer)->requirements(self::INPUT),
'Divi inactive: execute() answers unsupported ("Divi 5 ist nicht aktiv"), the gate must not refuse first'
);
}
public function testRequirementsWithDiviAreThoseOfTheComposer(): void
{
$composer = $this->composer();