feat: jedes Divi-Tool und lit/content-create erklärt seine Divi-Fähigkeiten (RequiresDiviFeatures, DeclaresRequirements, FeatureSets); Tabelle Tool → Fähigkeiten als Test
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
e387d8d29e
commit
fdbda8012c
@@ -9,6 +9,7 @@ use LIT\MCP\Integrations\Divi\Compose\VariableRef;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviContentComposer;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviSaver;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Tests\Support\DiviFixtures;
|
||||
use LIT\MCP\Tests\Support\DiviWriterFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
@@ -68,6 +69,17 @@ final class DiviContentComposerTest extends TestCase
|
||||
];
|
||||
}
|
||||
|
||||
public function testRequirementsNameTheCapabilitiesANewEntryNeeds(): void
|
||||
{
|
||||
$requirements = $this->composer()->requirements();
|
||||
sort($requirements);
|
||||
|
||||
self::assertSame(['catalog', 'design-read', 'dynamic-sources', 'page-read', 'page-write'], $requirements);
|
||||
foreach ($requirements as $id) {
|
||||
self::assertNotNull(DiviFeature::tryFrom($id), $id);
|
||||
}
|
||||
}
|
||||
|
||||
public function testChecksBeforeTheEntryExistsWithDivisMapForNoEntry(): void
|
||||
{
|
||||
self::assertNull($this->composer()->check('page', self::sections()));
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\Ability;
|
||||
use LIT\MCP\Abilities\DeclaresRequirements;
|
||||
use LIT\MCP\Integrations\Divi\DiviIntegration;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\FeatureSets;
|
||||
use LIT\MCP\Integrations\Divi\Release\RequiresDiviFeatures;
|
||||
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Integrations\WordPress\WordPressIntegration;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
|
||||
/**
|
||||
* The table of the Divi capabilities every tool of the groups divi, divi-library and divi-theme-builder and
|
||||
* lit/content-create declare (plan "Divi-Freigabe je Fähigkeit", Task 8). The table is the contract: a tool that
|
||||
* needs more or less than listed here changes it here, on purpose.
|
||||
*/
|
||||
final class DiviToolFeaturesTest extends TestCase
|
||||
{
|
||||
private const PAGE = 5;
|
||||
private const LIBRARY_ENTRY = 7;
|
||||
private const LAYOUT = 9;
|
||||
|
||||
/** Post ID => post type for get_post_type(); every other ID names no entry. */
|
||||
private const TYPES = [
|
||||
self::PAGE => 'page',
|
||||
self::LIBRARY_ENTRY => 'et_pb_layout',
|
||||
self::LAYOUT => 'et_body_layout',
|
||||
];
|
||||
|
||||
/** What a tool needs whatever its input names: tool => capabilities (DiviFeature values). */
|
||||
private const EXPECTED = [
|
||||
// Pages (divi)
|
||||
'lit/divi-outline' => ['page-read', 'design-read'],
|
||||
'lit/divi-node-get' => ['page-read', 'design-read'],
|
||||
'lit/divi-catalog' => ['catalog'],
|
||||
'lit/divi-design-system' => ['design-read'],
|
||||
'lit/divi-insert' => ['page-read', 'page-write', 'catalog', 'design-read', 'dynamic-sources'],
|
||||
'lit/divi-update' => ['page-read', 'page-write', 'catalog', 'design-read', 'dynamic-sources'],
|
||||
'lit/divi-move' => ['page-read', 'page-write', 'catalog', 'design-read'],
|
||||
'lit/divi-delete' => ['page-read', 'page-write', 'catalog', 'design-read'],
|
||||
'lit/divi-duplicate-node' => ['page-read', 'page-write', 'catalog', 'design-read'],
|
||||
'lit/divi-replace-text' => ['page-read', 'catalog', 'design-read', 'dynamic-sources'],
|
||||
'lit/divi-node-copy' => ['page-read', 'page-write', 'catalog', 'design-read', 'dynamic-sources'],
|
||||
'lit/divi-dynamic-sources' => ['dynamic-sources', 'roles'],
|
||||
// Design system (divi)
|
||||
'lit/divi-preset-get' => ['design-read', 'catalog'],
|
||||
'lit/divi-presets-set' => ['design-read', 'preset-write', 'catalog'],
|
||||
'lit/divi-presets-delete' => ['design-read', 'preset-write'],
|
||||
'lit/divi-design-snapshots' => [],
|
||||
'lit/divi-design-restore' => ['design-read', 'preset-write'],
|
||||
'lit/divi-presets-assign' => [
|
||||
'page-read', 'page-write', 'catalog', 'design-read', 'preset-write', 'library-read', 'library-write',
|
||||
'tb-write', 'roles',
|
||||
],
|
||||
'lit/divi-design-detach' => [
|
||||
'page-read', 'page-write', 'catalog', 'design-read', 'preset-write', 'library-read', 'library-write',
|
||||
'tb-write', 'roles',
|
||||
],
|
||||
// Library (divi-library)
|
||||
'lit/library-list' => ['library-read', 'roles'],
|
||||
'lit/library-find-similar' => ['page-read', 'catalog', 'roles'],
|
||||
'lit/library-insert' => [
|
||||
'page-read', 'page-write', 'catalog', 'design-read', 'dynamic-sources', 'library-read', 'roles',
|
||||
],
|
||||
'lit/library-make-global' => [
|
||||
'page-read', 'page-write', 'catalog', 'design-read', 'dynamic-sources', 'library-read', 'library-write',
|
||||
'roles',
|
||||
],
|
||||
'lit/library-save' => [
|
||||
'page-read', 'page-write', 'catalog', 'design-read', 'dynamic-sources', 'library-write', 'roles',
|
||||
],
|
||||
// Theme Builder (divi-theme-builder)
|
||||
'lit/tb-list' => ['tb-read', 'roles'],
|
||||
'lit/tb-create-template' => ['tb-read', 'tb-write', 'roles'],
|
||||
'lit/tb-assign' => ['tb-read', 'tb-write', 'roles'],
|
||||
'lit/tb-activate' => ['tb-read', 'tb-write', 'roles'],
|
||||
// WordPress: without the divi key it stays in the core
|
||||
'lit/content-create' => [],
|
||||
];
|
||||
|
||||
/** The compose set of a new or changed page. */
|
||||
private const COMPOSE = ['page-read', 'page-write', 'catalog', 'design-read', 'dynamic-sources'];
|
||||
|
||||
/**
|
||||
* Input-dependent additions: label => [tool, input, capabilities for that input].
|
||||
*
|
||||
* @return array<string, array{0: string, 1: array<string, mixed>, 2: list<string>}>
|
||||
*/
|
||||
public static function inputCases(): array
|
||||
{
|
||||
$page = self::PAGE;
|
||||
$library = self::LIBRARY_ENTRY;
|
||||
$layout = self::LAYOUT;
|
||||
$libraryWrite = ['roles', 'library-read', 'library-write'];
|
||||
$layoutWrite = ['roles', 'tb-read', 'tb-write'];
|
||||
|
||||
return [
|
||||
'outline of a page' => ['lit/divi-outline', ['post_id' => $page], ['page-read', 'design-read']],
|
||||
'outline of a library entry' => [
|
||||
'lit/divi-outline', ['post_id' => $library], ['page-read', 'design-read', 'roles'],
|
||||
],
|
||||
'outline of a layout' => [
|
||||
'lit/divi-outline', ['post_id' => $layout], ['page-read', 'design-read', 'roles'],
|
||||
],
|
||||
'node-get of a library entry' => [
|
||||
'lit/divi-node-get', ['post_id' => $library, 'id' => 's0'], ['page-read', 'design-read', 'roles'],
|
||||
],
|
||||
'outline of an unknown entry' => [
|
||||
'lit/divi-outline', ['post_id' => 999], ['page-read', 'design-read'],
|
||||
],
|
||||
'outline without post_id' => ['lit/divi-outline', [], ['page-read', 'design-read']],
|
||||
'insert into a page' => ['lit/divi-insert', ['post_id' => $page], self::COMPOSE],
|
||||
'insert into a library entry' => [
|
||||
'lit/divi-insert', ['post_id' => $library], array_merge(self::COMPOSE, $libraryWrite),
|
||||
],
|
||||
'update of a layout' => [
|
||||
'lit/divi-update', ['post_id' => $layout], array_merge(self::COMPOSE, $layoutWrite),
|
||||
],
|
||||
'move in a layout' => [
|
||||
'lit/divi-move', ['post_id' => $layout],
|
||||
array_merge(['page-read', 'page-write', 'catalog', 'design-read'], $layoutWrite),
|
||||
],
|
||||
'delete with a numeric string ID' => [
|
||||
'lit/divi-delete', ['post_id' => (string) $library],
|
||||
array_merge(['page-read', 'page-write', 'catalog', 'design-read'], $libraryWrite),
|
||||
],
|
||||
'node-copy of a page into a page' => [
|
||||
'lit/divi-node-copy', ['post_id' => $page, 'source_post_id' => $page], self::COMPOSE,
|
||||
],
|
||||
'node-copy out of a library entry' => [
|
||||
'lit/divi-node-copy', ['post_id' => $page, 'source_post_id' => $library],
|
||||
array_merge(self::COMPOSE, ['roles']),
|
||||
],
|
||||
'node-copy into a library entry' => [
|
||||
'lit/divi-node-copy', ['post_id' => $library, 'source_post_id' => $page],
|
||||
array_merge(self::COMPOSE, $libraryWrite),
|
||||
],
|
||||
'replace-text dry run by default' => [
|
||||
'lit/divi-replace-text', ['search' => 'a', 'replace' => 'b'],
|
||||
['page-read', 'catalog', 'design-read', 'dynamic-sources'],
|
||||
],
|
||||
'replace-text dry run explicit' => [
|
||||
'lit/divi-replace-text', ['dry_run' => true, 'targets' => [['post_id' => $library]]],
|
||||
['page-read', 'catalog', 'design-read', 'dynamic-sources'],
|
||||
],
|
||||
'replace-text on pages' => [
|
||||
'lit/divi-replace-text', ['dry_run' => false, 'targets' => [['post_id' => $page, 'tree_rev' => 'x']]],
|
||||
array_merge(['page-read', 'catalog', 'design-read', 'dynamic-sources'], ['page-write']),
|
||||
],
|
||||
'replace-text on a library entry' => [
|
||||
'lit/divi-replace-text',
|
||||
['dry_run' => false, 'targets' => [['post_id' => $page], ['post_id' => $library], 'bad']],
|
||||
array_merge(['page-read', 'catalog', 'design-read', 'dynamic-sources', 'page-write'], $libraryWrite),
|
||||
],
|
||||
'presets-set without from_node' => [
|
||||
'lit/divi-presets-set', ['items' => [['module' => 'button', 'name' => 'x']]],
|
||||
['design-read', 'preset-write', 'catalog'],
|
||||
],
|
||||
'presets-set from a page node' => [
|
||||
'lit/divi-presets-set', ['items' => [['from_node' => ['post_id' => $page, 'id' => 's0']]]],
|
||||
['design-read', 'preset-write', 'catalog', 'page-read'],
|
||||
],
|
||||
'presets-set from a library node' => [
|
||||
'lit/divi-presets-set', ['items' => [1, ['from_node' => ['post_id' => $library, 'id' => 's0']]]],
|
||||
['design-read', 'preset-write', 'catalog', 'page-read', 'roles'],
|
||||
],
|
||||
'library-list' => ['lit/library-list', [], ['library-read', 'roles']],
|
||||
'library-list of one entry' => [
|
||||
'lit/library-list', ['id' => $library], ['library-read', 'roles', 'page-read', 'design-read'],
|
||||
],
|
||||
'library-insert into a layout' => [
|
||||
'lit/library-insert', ['post_id' => $layout, 'library_id' => $library],
|
||||
array_merge(
|
||||
['page-read', 'page-write', 'catalog', 'design-read', 'dynamic-sources', 'library-read'],
|
||||
$layoutWrite
|
||||
),
|
||||
],
|
||||
'tb-create-template without nodes' => [
|
||||
'lit/tb-create-template', ['title' => 'T', 'header' => ['source' => 'new']],
|
||||
['tb-read', 'tb-write', 'roles'],
|
||||
],
|
||||
'tb-create-template with nodes' => [
|
||||
'lit/tb-create-template', ['title' => 'T', 'body' => ['source' => 'new', 'nodes' => [[]]]],
|
||||
array_merge(['tb-read', 'tb-write', 'roles'], self::COMPOSE),
|
||||
],
|
||||
'tb-create-template with empty nodes' => [
|
||||
'lit/tb-create-template', ['title' => 'T', 'footer' => ['source' => 'new', 'nodes' => []]],
|
||||
['tb-read', 'tb-write', 'roles'],
|
||||
],
|
||||
'content-create without divi' => ['lit/content-create', ['post_type' => 'page'], []],
|
||||
'content-create with divi' => [
|
||||
'lit/content-create', ['post_type' => 'page', 'divi' => [[]]], self::COMPOSE,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
Functions\when('__')->returnArg();
|
||||
Functions\when('get_post_type')->alias(static fn (int $id): string|false => self::TYPES[$id] ?? false);
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
}
|
||||
|
||||
/** @return array<string, Ability> name => ability of the three Divi groups and lit/content-create */
|
||||
private function abilities(): array
|
||||
{
|
||||
$divi = new DiviIntegration(Mockery::mock(ContentSchema::class), FakeChangeLog::forbidden());
|
||||
$composer = Mockery::mock(ContentComposer::class);
|
||||
$composer->allows('requirements')->andReturn(self::COMPOSE);
|
||||
$wordPress = new WordPressIntegration(
|
||||
Mockery::mock(ContentSchema::class),
|
||||
FakeChangeLog::forbidden(),
|
||||
$composer
|
||||
);
|
||||
|
||||
$found = [];
|
||||
foreach ([
|
||||
...$divi->abilities(),
|
||||
...$divi->library()->abilities(),
|
||||
...$divi->themeBuilder()->abilities(),
|
||||
] as $ability) {
|
||||
$found[$ability->name()] = $ability;
|
||||
}
|
||||
foreach ($wordPress->abilities() as $ability) {
|
||||
if ($ability->name() === 'lit/content-create') {
|
||||
$found[$ability->name()] = $ability;
|
||||
}
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<DiviFeature> $features
|
||||
* @return list<string> The values, sorted.
|
||||
*/
|
||||
private static function values(array $features): array
|
||||
{
|
||||
$values = array_map(static fn (DiviFeature $feature): string => $feature->value, $features);
|
||||
sort($values);
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/** @param list<string> $values */
|
||||
private static function sorted(array $values): array
|
||||
{
|
||||
sort($values);
|
||||
|
||||
return array_values(array_unique($values));
|
||||
}
|
||||
|
||||
public function testEveryToolOfTheDiviGroupsDeclaresItsFeatures(): void
|
||||
{
|
||||
$abilities = $this->abilities();
|
||||
|
||||
foreach ($abilities as $name => $ability) {
|
||||
if ($name === 'lit/content-create') {
|
||||
self::assertInstanceOf(DeclaresRequirements::class, $ability, $name);
|
||||
self::assertNotInstanceOf(RequiresDiviFeatures::class, $ability, 'the core imports no Divi class');
|
||||
continue;
|
||||
}
|
||||
self::assertInstanceOf(RequiresDiviFeatures::class, $ability, $name);
|
||||
}
|
||||
}
|
||||
|
||||
public function testEveryRowOfTheTableHasAnAbilityAndTheOtherWayRound(): void
|
||||
{
|
||||
$abilities = array_keys($this->abilities());
|
||||
|
||||
self::assertSame([], array_values(array_diff(array_keys(self::EXPECTED), $abilities)), 'row without ability');
|
||||
self::assertSame([], array_values(array_diff($abilities, array_keys(self::EXPECTED))), 'ability without row');
|
||||
}
|
||||
|
||||
public function testEveryToolDeclaresExactlyTheTableForAnInputThatNamesNothing(): void
|
||||
{
|
||||
foreach ($this->abilities() as $name => $ability) {
|
||||
self::assertSame(
|
||||
self::sorted(self::EXPECTED[$name] ?? ['<no row>']),
|
||||
self::values(FeatureSets::declaredBy($ability, [])),
|
||||
$name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $input
|
||||
* @param list<string> $expected
|
||||
* @dataProvider inputCases
|
||||
*/
|
||||
public function testInputDependentFeatures(string $tool, array $input, array $expected): void
|
||||
{
|
||||
$ability = $this->abilities()[$tool];
|
||||
|
||||
self::assertSame(self::sorted($expected), self::values(FeatureSets::declaredBy($ability, $input)));
|
||||
}
|
||||
|
||||
public function testNoToolDeclaresAFeatureTwiceAndEveryIdIsAFeature(): void
|
||||
{
|
||||
foreach ($this->abilities() as $name => $ability) {
|
||||
$declared = $ability instanceof RequiresDiviFeatures
|
||||
? array_map(static fn (DiviFeature $f): string => $f->value, $ability->diviFeatures([]))
|
||||
: [];
|
||||
self::assertSame($declared, array_values(array_unique($declared)), $name);
|
||||
}
|
||||
foreach (self::EXPECTED as $name => $ids) {
|
||||
foreach ($ids as $id) {
|
||||
self::assertNotNull(DiviFeature::tryFrom($id), $name . ': ' . $id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testEveryWritingToolNeedsTheWriteFeatureOfEverythingItSaves(): void
|
||||
{
|
||||
$writes = [
|
||||
'lit/divi-insert' => 'page-write', 'lit/divi-update' => 'page-write', 'lit/divi-move' => 'page-write',
|
||||
'lit/divi-delete' => 'page-write', 'lit/divi-duplicate-node' => 'page-write',
|
||||
'lit/divi-node-copy' => 'page-write', 'lit/library-insert' => 'page-write',
|
||||
'lit/library-make-global' => 'library-write', 'lit/library-save' => 'library-write',
|
||||
'lit/divi-presets-set' => 'preset-write', 'lit/divi-presets-delete' => 'preset-write',
|
||||
'lit/divi-design-restore' => 'preset-write', 'lit/divi-design-detach' => 'preset-write',
|
||||
'lit/divi-presets-assign' => 'page-write', 'lit/tb-assign' => 'tb-write', 'lit/tb-activate' => 'tb-write',
|
||||
'lit/tb-create-template' => 'tb-write',
|
||||
];
|
||||
foreach ($writes as $name => $feature) {
|
||||
self::assertContains($feature, self::EXPECTED[$name], $name);
|
||||
}
|
||||
// Read-only tools never need a write capability.
|
||||
foreach (['lit/divi-outline', 'lit/divi-node-get', 'lit/divi-catalog', 'lit/divi-design-system',
|
||||
'lit/divi-dynamic-sources', 'lit/divi-preset-get', 'lit/library-list', 'lit/library-find-similar',
|
||||
'lit/tb-list', 'lit/divi-design-snapshots'] as $name) {
|
||||
foreach (self::EXPECTED[$name] as $id) {
|
||||
self::assertFalse(DiviFeature::from($id)->isWrite(), $name . ': ' . $id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Release;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\Ability;
|
||||
use LIT\MCP\Abilities\DeclaresRequirements;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use LIT\MCP\Integrations\Divi\Release\FeatureSets;
|
||||
use LIT\MCP\Integrations\Divi\Release\RequiresDiviFeatures;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
|
||||
final class FeatureSetsTest extends TestCase
|
||||
{
|
||||
/** @var array<int, string> */
|
||||
private array $types = [];
|
||||
|
||||
private bool $mayEdit = true;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
Functions\when('get_post_type')->alias(fn (int $id): string|false => $this->types[$id] ?? false);
|
||||
Functions\when('current_user_can')->alias(fn (string $capability): bool => $this->mayEdit);
|
||||
}
|
||||
|
||||
public function testMergeKeepsEveryFeatureOnceInTheOrderOfItsFirstAppearance(): void
|
||||
{
|
||||
$merged = FeatureSets::merge(
|
||||
[DiviFeature::Catalog, DiviFeature::Roles],
|
||||
[],
|
||||
[DiviFeature::Roles, DiviFeature::PageRead, DiviFeature::Catalog]
|
||||
);
|
||||
|
||||
self::assertSame([DiviFeature::Catalog, DiviFeature::Roles, DiviFeature::PageRead], $merged);
|
||||
self::assertSame([], FeatureSets::merge());
|
||||
}
|
||||
|
||||
public function testAPageOrPostAddsNothing(): void
|
||||
{
|
||||
$this->types = [5 => 'page', 6 => 'post', 7 => 'project'];
|
||||
|
||||
foreach ([5, 6, 7, '5'] as $id) {
|
||||
self::assertSame([], FeatureSets::ofEntry($id, true), (string) $id);
|
||||
self::assertSame([], FeatureSets::ofEntry($id, false), (string) $id);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAnIdThatNamesNoEntryAddsNothing(): void
|
||||
{
|
||||
foreach ([null, 0, -3, 'abc', '1.5', [], 404] as $id) {
|
||||
self::assertSame([], FeatureSets::ofEntry($id, true), var_export($id, true));
|
||||
}
|
||||
}
|
||||
|
||||
public function testALibraryEntryNeedsTheRolesAndWritingAlsoTheLibrary(): void
|
||||
{
|
||||
$this->types = [7 => 'et_pb_layout'];
|
||||
|
||||
self::assertSame([DiviFeature::Roles], FeatureSets::ofEntry(7, false));
|
||||
self::assertSame(
|
||||
[DiviFeature::Roles, DiviFeature::LibraryRead, DiviFeature::LibraryWrite],
|
||||
FeatureSets::ofEntry('7', true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testEveryThemeBuilderLayoutNeedsTheRolesAndWritingAlsoTheThemeBuilder(): void
|
||||
{
|
||||
$this->types = [1 => 'et_header_layout', 2 => 'et_body_layout', 3 => 'et_footer_layout'];
|
||||
|
||||
foreach ([1, 2, 3] as $id) {
|
||||
self::assertSame([DiviFeature::Roles], FeatureSets::ofEntry($id, false), (string) $id);
|
||||
self::assertSame(
|
||||
[DiviFeature::Roles, DiviFeature::ThemeBuilderRead, DiviFeature::ThemeBuilderWrite],
|
||||
FeatureSets::ofEntry($id, true),
|
||||
(string) $id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAnEntryTheCallerMayNotEditAddsNothingSoALockNeverNamesItsKind(): void
|
||||
{
|
||||
$this->types = [7 => 'et_pb_layout', 9 => 'et_body_layout'];
|
||||
$this->mayEdit = false;
|
||||
|
||||
foreach ([7, 9] as $id) {
|
||||
self::assertSame([], FeatureSets::ofEntry($id, true), (string) $id);
|
||||
self::assertSame([], FeatureSets::ofEntry($id, false), (string) $id);
|
||||
}
|
||||
}
|
||||
|
||||
public function testTemplatesAndThemeBuilderPostsAreNoLayouts(): void
|
||||
{
|
||||
$this->types = [1 => 'et_template', 2 => 'et_theme_builder'];
|
||||
|
||||
self::assertSame([], FeatureSets::ofEntry(1, true));
|
||||
self::assertSame([], FeatureSets::ofEntry(2, true));
|
||||
}
|
||||
|
||||
public function testDeclaredByReadsTheDiviToolsOwnList(): void
|
||||
{
|
||||
$tool = Mockery::mock(Ability::class, RequiresDiviFeatures::class);
|
||||
$tool->expects('diviFeatures')->with(['a' => 1])->andReturn([DiviFeature::Roles, DiviFeature::Roles]);
|
||||
|
||||
self::assertSame([DiviFeature::Roles], FeatureSets::declaredBy($tool, ['a' => 1]));
|
||||
}
|
||||
|
||||
public function testDeclaredByTranslatesTheIdsOfACoreToolAndIgnoresUnknownOnes(): void
|
||||
{
|
||||
$tool = Mockery::mock(Ability::class, DeclaresRequirements::class);
|
||||
$tool->expects('requirements')->with(['divi' => []])->andReturn(['page-write', 'other-integration', 'catalog']);
|
||||
|
||||
self::assertSame(
|
||||
[DiviFeature::PageWrite, DiviFeature::Catalog],
|
||||
FeatureSets::declaredBy($tool, ['divi' => []])
|
||||
);
|
||||
}
|
||||
|
||||
public function testDeclaredByIsEmptyForAnyOtherTool(): void
|
||||
{
|
||||
self::assertSame([], FeatureSets::declaredBy(Mockery::mock(Ability::class), ['x' => 1]));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user