id()); self::assertFalse($integration->isAvailable(), 'no Divi classes in unit tests'); self::assertSame( self::EXPECTED, array_map(static fn (Ability $ability): string => $ability->name(), $integration->abilities()) ); foreach ($integration->abilities() as $ability) { self::assertSame('object', $ability->inputSchema()['type'], $ability->name()); self::assertFalse($ability->inputSchema()['additionalProperties'], $ability->name()); self::assertNotNull($ability->outputSchema(), $ability->name()); } } public function testProvidesTheLibraryGroup(): void { Functions\when('__')->returnArg(); $library = (new DiviIntegration(Mockery::mock(ContentSchema::class), FakeChangeLog::forbidden()))->library(); self::assertSame('divi-library', $library->id()); self::assertSame('Divi-Bibliothek', $library->label()); self::assertFalse($library->isAvailable(), 'no Divi classes in unit tests'); self::assertSame( ['lit/library-list', 'lit/library-save', 'lit/library-insert'], array_map(static fn (Ability $ability): string => $ability->name(), $library->abilities()) ); foreach ($library->abilities() as $ability) { self::assertFalse($ability->inputSchema()['additionalProperties'], $ability->name()); self::assertNotNull($ability->outputSchema(), $ability->name()); } } /** Ruling P9 (E9): lit/divi-node-copy follows lit/divi-insert's Tools-tab state. */ public function testNodeCopyFollowsLitDiviInsert(): void { $integration = new DiviIntegration( Mockery::mock(ContentSchema::class), FakeChangeLog::forbidden(), diviWritable: static fn (): bool => false ); $copy = null; foreach ($integration->abilities() as $ability) { if ($ability->name() === 'lit/divi-node-copy') { $copy = $ability; } } self::assertNotNull($copy); self::assertToolError($copy->permission(['post_id' => 7, 'source_post_id' => 8]), 'unsupported'); } public function testGivesContentCreateTheDiviShortForm(): void { $integration = new DiviIntegration(Mockery::mock(ContentSchema::class), FakeChangeLog::forbidden()); $composer = $integration->contentComposer(); self::assertInstanceOf(DiviContentComposer::class, $composer); self::assertFalse($composer->available(), 'no Divi classes in unit tests'); } /** E1/E3: the Divi read tools reach library entries; ruling P9: a hidden library leaves them not found. */ public function testTheReadToolsReachTheLibraryUnlessItIsHidden(): void { LibraryFixtures::given([LibraryFixtures::item(1055)]); $schema = Mockery::mock(ContentSchema::class); $schema->allows('isManaged')->andReturn(false); $outline = static fn (DiviIntegration $divi): mixed => $divi->abilities()[0]->permission(['post_id' => 1055]); // No Divi in unit tests: DiviRoles allows nothing, so the entry is not found either way (ruling P12); // the wiring shows in which gate the integration asks. $asked = 0; $visible = new DiviIntegration($schema, FakeChangeLog::forbidden(), null, static function () use (&$asked): bool { ++$asked; return true; }); self::assertToolError($outline($visible), 'not_found'); self::assertSame(1, $asked); self::assertToolError($outline(new DiviIntegration($schema, FakeChangeLog::forbidden())), 'not_found'); $hidden = new DiviIntegration($schema, FakeChangeLog::forbidden(), libraryVisible: static fn (): bool => false); $refusal = $outline($hidden); self::assertInstanceOf(WP_Error::class, $refusal); self::assertToolError($refusal, 'not_found'); } }