Skip to content
Snippets Groups Projects

Issue #3498889: Add component source plugin

1 file
+ 36
20
Compare changes
  • Side-by-side
  • Inline
  • `::testComponentEntityCreation()` was testing impossible things: things that can only occur if XB config entities are not being validated, which must never occur. In fact, the `JavaScriptComponent` config entity MUST guarantee that whatever is created by the person using the code component editor UI, *is* fully usable when placing an instance of such a component.
@@ -10,6 +10,7 @@ use Drupal\experience_builder\Entity\ComponentInterface;
use Drupal\experience_builder\Entity\JavaScriptComponent;
use Drupal\experience_builder\Plugin\ExperienceBuilder\ComponentSource\JsComponent;
use Drupal\KernelTests\KernelTestBase;
use Drupal\Tests\experience_builder\Traits\ConstraintViolationsTestTrait;
use Drupal\Tests\experience_builder\Traits\ContribStrictConfigSchemaTestTrait;
use Drupal\Tests\user\Traits\UserCreationTrait;
@@ -24,6 +25,7 @@ final class JavascriptComponentStorageTest extends KernelTestBase {
use UserCreationTrait;
use ContribStrictConfigSchemaTestTrait;
use ConstraintViolationsTestTrait;
/**
* {@inheritdoc}
@@ -72,6 +74,14 @@ final class JavascriptComponentStorageTest extends KernelTestBase {
'compiled_js' => 'console.log("hey");',
'compiled_css' => '.test { display: none; }',
]);
$this->assertSame([
'props.title' => "'examples' is a required key.",
], self::violationsToArray($js_component->getTypedData()->validate()));
// Make it pass validation by adding the missing `examples`, and save it.
$props['title']['examples'] = ['Title'];
$js_component->setProps($props);
$this->assertEmpty(self::violationsToArray($js_component->getTypedData()->validate()));
$js_component->save();
// No Component config entity is ever created for JavaScript Components not
@@ -80,30 +90,36 @@ final class JavascriptComponentStorageTest extends KernelTestBase {
self::assertEmpty($reason_repository->getReasons()[JsComponent::SOURCE_PLUGIN_ID] ?? []);
self::assertNull($component);
// Now flag it and observe the consequences.
$js_component->enable()->save();
self::assertEquals([
$component_id => 'Prop "title" is required, but does not have example value',
], $reason_repository->getReasons()[JsComponent::SOURCE_PLUGIN_ID] ?? []);
$component = Component::load($component_id);
self::assertNull($component);
// Use a non-storable prop shape.
// Use a non-storable prop shape. The JavaScript Component config entity's
// config schema SHOULD prevent the component author from choosing props
// that the Experience Builder cannot generate an input UX for.
// @see \Drupal\experience_builder\Plugin\ExperienceBuilder\ComponentSource\GeneratedFieldExplicitInputUxComponentSourceBase
// @see the `Choice` constraints on `type: experience_builder.js_component.*`'s for prop `format`.
$props['title']['format'] = 'hostname';
$props['title']['examples'] = ['Title'];
$js_component->setProps($props);
$js_component->save();
self::assertEquals([
$component_id => 'Experience Builder does not know of a field type/widget to allow populating the <code>title</code> prop, with the shape <code>{"type":"string","format":"hostname"}</code>.',
], $reason_repository->getReasons()[JsComponent::SOURCE_PLUGIN_ID] ?? []);
$component = Component::load($component_id);
self::assertNull($component);
$this->assertSame([
'props.title.format' => 'The value you selected is not a valid choice.',
], self::violationsToArray($js_component->getTypedData()->validate()));
// @see the `Choice` constraints on `type: experience_builder.js_component.*`'s for prop `type`.
unset($props['title']['format']);
$props['title']['type'] = 'object';
$js_component->setProps($props);
$js_component->save();
$this->assertSame([
'props.title.type' => 'The value you selected is not a valid choice.',
], self::violationsToArray($js_component->getTypedData()->validate()));
// In other words: if the JavaScript Component config entity is sufficiently
// tightly validated, the following should always be true.
self::assertSame([], $reason_repository->getReasons()[JsComponent::SOURCE_PLUGIN_ID] ?? []);
// Now remove the attempts to bypass the JavaScriptComponent config entity's
// validation, enable it and verify that a corresponding Component config
// entity is created.
$props['title']['type'] = 'string';
$js_component
->setProps($props)
->enable()
->save();
$component = Component::load($component_id);
self::assertInstanceOf(ComponentInterface::class, $component);
Loading