diff --git a/src/Plugin/UiPatterns/PropType/BooleanPropType.php b/src/Plugin/UiPatterns/PropType/BooleanPropType.php index 25e74d25a614852101d73cdc5c81c4bddc960ecd..2b9d2bbafc8e0a8c60a8273655a217fb4fc167a6 100644 --- a/src/Plugin/UiPatterns/PropType/BooleanPropType.php +++ b/src/Plugin/UiPatterns/PropType/BooleanPropType.php @@ -6,6 +6,7 @@ namespace Drupal\ui_patterns\Plugin\UiPatterns\PropType; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\ui_patterns\Attribute\PropType; +use Drupal\ui_patterns\PropTypeConversionTrait; use Drupal\ui_patterns\PropTypePluginBase; /** @@ -22,10 +23,20 @@ use Drupal\ui_patterns\PropTypePluginBase; )] class BooleanPropType extends PropTypePluginBase { + use PropTypeConversionTrait; + /** * {@inheritdoc} */ public static function normalize(mixed $value, ?array $definition = NULL): bool { + if (is_bool($value)) { + return $value; + } + static::convertToScalar($value); + if (is_numeric($value) && is_string($value)) { + $value = (int) $value; + return (bool) $value; + } return (bool) $value; } diff --git a/src/Plugin/UiPatterns/PropType/IdentifierPropType.php b/src/Plugin/UiPatterns/PropType/IdentifierPropType.php index 17c88e0fb5d4038968cbb2db050a0d389ccd7d6e..c2f152da2def79efe9c7db12d6627c1d51539ba5 100644 --- a/src/Plugin/UiPatterns/PropType/IdentifierPropType.php +++ b/src/Plugin/UiPatterns/PropType/IdentifierPropType.php @@ -30,7 +30,7 @@ class IdentifierPropType extends PropTypePluginBase { * {@inheritdoc} */ public static function normalize(mixed $value, ?array $definition = NULL): mixed { - return static::convertToString($value); + return strip_tags(static::convertToString($value)); } } diff --git a/src/PropTypeConversionTrait.php b/src/PropTypeConversionTrait.php index c062430bdf56ea75737f5bac9173abe119a29499..137bf628c806d4d44d5e489af4c1674119378110 100644 --- a/src/PropTypeConversionTrait.php +++ b/src/PropTypeConversionTrait.php @@ -52,7 +52,9 @@ trait PropTypeConversionTrait { return NULL; } if (!empty(Element::properties($array))) { - $value = (string) \Drupal::service('renderer')->render($array); + /** @var \Drupal\Core\Render\Renderer $renderer */ + $renderer = \Drupal::service('renderer'); + $value = (string) $renderer->renderInIsolation($array); if ($strip_tags_from_render_arrays) { $value = strip_tags($value); } diff --git a/tests/modules/ui_patterns_test/components/prop_types_tests/prop_types_tests.component.yml b/tests/modules/ui_patterns_test/components/prop_types_tests/prop_types_tests.component.yml index 5883dcde9b541706f5319e6a58146516f3b343cb..cebe4ed827b8cc0039d10e3d77f23784f0adf6ca 100644 --- a/tests/modules/ui_patterns_test/components/prop_types_tests/prop_types_tests.component.yml +++ b/tests/modules/ui_patterns_test/components/prop_types_tests/prop_types_tests.component.yml @@ -5,8 +5,6 @@ props: required: - string properties: - nothing: - title: "Unknown (nothing)" object: title: "Unknown (empty object)" type: "object" diff --git a/tests/modules/ui_patterns_test/components/test-component/test-component.twig b/tests/modules/ui_patterns_test/components/test-component/test-component.twig index 1288e69f2f2fd86eee8cf7149af3dc675fcba144..7abf561dbefebc421a3a7fdd8a0f315141ec296e 100644 --- a/tests/modules/ui_patterns_test/components/test-component/test-component.twig +++ b/tests/modules/ui_patterns_test/components/test-component/test-component.twig @@ -1,5 +1,9 @@ {% set variant = variant|default('') %} -<div{{ attributes.addClass(['ui-patterns-test-component', 'ui-patterns-test-component-variant-' ~ variant]) }}> +{% set my_attributes = create_attribute(attributes.storage()) %} +<div{{ my_attributes.addClass(['ui-patterns-test-component', 'ui-patterns-test-component-variant-' ~ variant]) }}> + <div class="ui-patterns-props-attributes"> + <div{{ attributes }}></div> + </div> <div class="ui-patterns-props-string"> {{ string }} </div> diff --git a/tests/src/Unit/PropTypeNormalization/AttributesPropTypeNormalizationTest.php b/tests/src/Kernel/PropTypeNormalization/AttributesPropTypeTest.php similarity index 52% rename from tests/src/Unit/PropTypeNormalization/AttributesPropTypeNormalizationTest.php rename to tests/src/Kernel/PropTypeNormalization/AttributesPropTypeTest.php index 496d2d996d929a908c114d4c2ff363a8ad72dc2c..2b218e719975b9a900f77337dd25ab784e6b9e64 100644 --- a/tests/src/Unit/PropTypeNormalization/AttributesPropTypeNormalizationTest.php +++ b/tests/src/Kernel/PropTypeNormalization/AttributesPropTypeTest.php @@ -2,48 +2,81 @@ declare(strict_types=1); -namespace Drupal\Tests\ui_patterns\Unit; +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; -use Drupal\Tests\UnitTestCase; +use Drupal\Core\Template\Attribute; +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; use Drupal\ui_patterns\Plugin\UiPatterns\PropType\AttributesPropType; /** - * @coversDefaultClass Drupal\ui_patterns\Plugin\UiPatterns\PropType\LinksPropType + * Test AttributesPropType normalization. * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\AttributesPropType * @group ui_patterns */ -final class AttributesPropTypeNormalizationTest extends UnitTestCase { +class AttributesPropTypeTest extends PropTypeNormalizationTestBase { /** - * Test the method ::normalize(). + * Test normalize static method. * - * @dataProvider provideNormalizationData + * @dataProvider normalizationTests */ - public function testNormalize(array $value, array $expected): void { - $normalized = AttributesPropType::normalize($value); - self::assertEquals($normalized, $expected); + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = AttributesPropType::normalize($value, $this->testComponentProps['attributes']); + $this->assertEquals($normalized, $expected); } /** - * Provide data for testNormalize. + * Test rendered component with prop. + * + * @dataProvider renderingTests */ - public static function provideNormalizationData(): \Generator { - $data = [ - "Empty value" => [ - "value" => [], - "expected" => [], - ], + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('attributes', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "Empty value" => [[], []], "Standardized primitives, so already OK" => self::standardizedPrimitives(), "Type transformations" => self::typeTransformation(), "List array" => self::listArray(), + ]; + } + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "Empty Value" => [ + [], + '<div data-component-id="ui_patterns_test:test-component"></div>', + ], + "attribute_object" => [ + new Attribute(["data-foo" => "bar"]), + ' data-foo="bar"', + ], + "integer" => [ + ["data-foo" => 1], + ' data-foo="1"', + ], + "array" => [ + ["key" => ["1", "2"]], + ' key="1 2"', + ], + "escaping" => [ + ["key" => '"'], + ' key="""', + ], + "rendered value" => [ + ["key" => ["#markup" => "value"]], + ' key="value"', + ], ]; - foreach ($data as $label => $test) { - yield $label => [ - $test['value'], - $test['expected'], - ]; - }; } /** @@ -61,11 +94,7 @@ final class AttributesPropTypeNormalizationTest extends UnitTestCase { "integer" => 4, "float" => 1.4, ]; - $expected = $value; - return [ - "value" => $value, - "expected" => $expected, - ]; + return [$value, $value]; } /** @@ -112,10 +141,7 @@ final class AttributesPropTypeNormalizationTest extends UnitTestCase { '{"deep":{"very deep":["foo","bar"]}}', ], ]; - return [ - "value" => $value, - "expected" => $expected, - ]; + return [$value, $expected]; } /** @@ -134,10 +160,7 @@ final class AttributesPropTypeNormalizationTest extends UnitTestCase { "1" => "Two", "2" => 3, ]; - return [ - "value" => $value, - "expected" => $expected, - ]; + return [$value, $expected]; } } diff --git a/tests/src/Kernel/PropTypeNormalization/BooleanPropTypeTest.php b/tests/src/Kernel/PropTypeNormalization/BooleanPropTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..63417c9a44124f03bddfa90891a5f44612bf58c7 --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/BooleanPropTypeTest.php @@ -0,0 +1,84 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; +use Drupal\ui_patterns\Plugin\UiPatterns\PropType\BooleanPropType; + +/** + * Test BooleanPropType normalization. + * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\BooleanPropType + * @group ui_patterns + */ +class BooleanPropTypeTest extends PropTypeNormalizationTestBase { + + /** + * Test normalize static method. + * + * @dataProvider normalizationTests + */ + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = BooleanPropType::normalize($value, $this->testComponentProps['boolean']); + $this->assertEquals($normalized, $expected); + } + + /** + * Test rendered component with prop. + * + * @dataProvider renderingTests + */ + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('boolean', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, NULL], + "false value" => [FALSE, FALSE], + "true value" => [TRUE, TRUE], + "integer 0" => [0, FALSE], + "integer pos" => [22, TRUE], + "string empty" => ["", FALSE], + "string zero" => ["0", FALSE], + "string not zero" => ["22", TRUE], + "html" => ["<p>0</p>", TRUE], + "markup 0" => [["#markup" => "0"], FALSE], + "markup 1" => [["#markup" => "1"], TRUE], + ]; + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + '<div class="ui-patterns-props-boolean"></div>', + ], + "false value" => [ + FALSE, + '<div class="ui-patterns-props-boolean"></div>', + ], + "true value" => [ + TRUE, + '<div class="ui-patterns-props-boolean">1</div>', + ], + "zero string value" => [ + "0", + '<div class="ui-patterns-props-boolean"></div>', + ], + "not zero string value" => [ + "22", + '<div class="ui-patterns-props-boolean">1</div>', + ], + ]; + } + +} diff --git a/tests/src/Kernel/PropTypeNormalization/ComplexTest.php b/tests/src/Kernel/PropTypeNormalization/ComplexTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c5490f09269de320128e91a95acee03bf96710cf --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/ComplexTest.php @@ -0,0 +1,58 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; + +/** + * Test some complex cases. + * + * @group ui_patterns + */ +class ComplexTest extends PropTypeNormalizationTestBase { + + /** + * Test slot normalization. + */ + public function testNestedComponentWithForm() : void { + // Test nested component with form. + $render_array_tests = [ + [ + "#type" => "inline_template", + "#template" => " + {% set comp_form = include('ui_patterns_test:test-form-component', {}) %} + {{ include('ui_patterns_test:test-component', {slot: comp_form}) }}", + "#context" => [], + ], + [ + "#type" => "component", + '#component' => 'ui_patterns_test:test-component', + "#slots" => [ + "slot" => [ + "#type" => "component", + '#component' => 'ui_patterns_test:test-form-component', + ], + ], + ], + ]; + foreach ($render_array_tests as $render_array_test) { + $this->assertExpectedOutput( + [ + "rendered_value" => "<input ", + "assert" => "assertStringContainsString", + ], + $render_array_test + ); + $this->assertExpectedOutput( + [ + "rendered_value" => "<form ", + "assert" => "assertStringContainsString", + ], + $render_array_test + ); + } + } + +} diff --git a/tests/src/Kernel/PropTypeNormalization/EnumListPropTypeTest.php b/tests/src/Kernel/PropTypeNormalization/EnumListPropTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e986a262793dd0e5294e0f0793fc148770c63054 --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/EnumListPropTypeTest.php @@ -0,0 +1,67 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Core\Template\Attribute; +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; +use Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumListPropType; + +/** + * Test EnumListPropType normalization. + * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumListPropType + * @group ui_patterns + */ +class EnumListPropTypeTest extends PropTypeNormalizationTestBase { + + /** + * Test normalize static method. + * + * @dataProvider normalizationTests + */ + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = EnumListPropType::normalize($value, $this->testComponentProps['enum_list_multiple']); + $this->assertEquals($normalized, $expected); + } + + /** + * Test rendered component with prop. + * + * @dataProvider renderingTests + */ + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('enum_list_multiple', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, []], + "single item" => [[2], [2]], + "single item string" => [["2"], [2]], + "single string" => ["2", [2]], + "multiple items" => [[2, 2, 2], [2, 2, 2]], + ]; + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + '<div class="ui-patterns-props-enum_list_multiple"></div>', + ], + "multiple items with bad values" => [ + [2, "BAD", "2", 2, 444, "BAD", new Attribute(), [2]], + '<div class="ui-patterns-props-enum_list_multiple"><span>2</span><span>2</span><span>2</span></div>', + ], + ]; + } + +} diff --git a/tests/src/Kernel/PropTypeNormalization/EnumPropTypeTest.php b/tests/src/Kernel/PropTypeNormalization/EnumPropTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2fb87a7bd064f63a1ca3b75572ef7e765b5dd5d3 --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/EnumPropTypeTest.php @@ -0,0 +1,66 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; +use Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType; + +/** + * Test EnumPropType normalization. + * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType + * @group ui_patterns + */ +class EnumPropTypeTest extends PropTypeNormalizationTestBase { + + /** + * Test normalize static method. + * + * @dataProvider normalizationTests + */ + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = EnumPropType::normalize($value, $this->testComponentProps['enum_integer']); + $this->assertEquals($normalized, $expected); + } + + /** + * Test rendered component with prop. + * + * @dataProvider renderingTests + */ + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('enum_integer', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, NULL], + "integer" => [2, 2], + "string" => ["2", 2], + "string bad" => ["BAD VALUE", NULL], + "object" => [new \stdClass(), NULL], + "array" => [[2], 2], + "array assoc" => [["aa" => 2], 2], + "array assoc bad" => [["1" => NULL, "aa" => 2], 2], + "array markup" => [['#markup' => "2"], 2], + ]; + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + '<div class="ui-patterns-props-enum_integer"></div>', + ], + ]; + } + +} diff --git a/tests/src/Kernel/PropTypeNormalization/EnumSetPropTypeTest.php b/tests/src/Kernel/PropTypeNormalization/EnumSetPropTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7a914b4e4b9bbf61297070e82a559d1526c466fc --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/EnumSetPropTypeTest.php @@ -0,0 +1,71 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Core\Template\Attribute; +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; +use Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumSetPropType; + +/** + * Test EnumSetPropType normalization. + * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumSetPropType + * @group ui_patterns + */ +class EnumSetPropTypeTest extends PropTypeNormalizationTestBase { + + /** + * Test normalize static method. + * + * @dataProvider normalizationTests + */ + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = EnumSetPropType::normalize($value, $this->testComponentProps['enum_set']); + $this->assertEquals($normalized, $expected); + } + + /** + * Test rendered component with prop. + * + * @dataProvider renderingTests + */ + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('enum_set', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, []], + "single item" => [[2], [2]], + "single item string" => [["2"], [2]], + "single string" => ["2", [2]], + "multiple items" => [[2, 2, 2], [2]], + "multiple items with bad values" => [ + [2, "BAD", 2, 2, 444, "BAD", new Attribute(), [2]], + [2], + ], + ]; + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + '<div class="ui-patterns-props-enum_set"></div>', + ], + "multiple items with bad values" => [ + [2, "BAD", "2", 2, 444, "BAD", new Attribute(), [2]], + '<div class="ui-patterns-props-enum_set"><span>2</span></div>', + ], + ]; + } + +} diff --git a/tests/src/Kernel/PropTypeNormalization/IdentifierPropTypeTest.php b/tests/src/Kernel/PropTypeNormalization/IdentifierPropTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..28c99bd341975c30934e457d329d6bd2fa3b824a --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/IdentifierPropTypeTest.php @@ -0,0 +1,79 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; +use Drupal\ui_patterns\Plugin\UiPatterns\PropType\IdentifierPropType; +use Twig\Error\RuntimeError; + +/** + * Test IdentifierPropType normalization. + * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\IdentifierPropType + * @group ui_patterns + */ +class IdentifierPropTypeTest extends PropTypeNormalizationTestBase { + + /** + * Test normalize static method. + * + * @dataProvider normalizationTests + */ + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = IdentifierPropType::normalize($value, $this->testComponentProps['identifier']); + $this->assertEquals($normalized, $expected); + } + + /** + * Test rendered component with prop. + * + * @dataProvider renderingTests + */ + public function testRendering(mixed $value, mixed $rendered_value, ?string $exception_class = NULL) : void { + $this->runRenderPropTest('identifier', + ["value" => $value, "rendered_value" => $rendered_value, "exception_class" => $exception_class]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, NULL], + "markup" => [['#markup' => "abc"], "abc"], + "string" => ["abc", "abc"], + "string with markup" => ["<b>abc</b>", "abc"], + "string with square brackets" => ["a[v][eee]", "a[v][eee]"], + ]; + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + '<div class="ui-patterns-props-identifier"></div>', + RuntimeError::class, + ], + "empty value" => [ + "", + '<div class="ui-patterns-props-identifier"></div>', + RuntimeError::class, + ], + "invalid value" => [ + "2", + '<div class="ui-patterns-props-identifier"></div>', + RuntimeError::class, + ], + "correct value" => [ + "correct-value🔥", + '<div class="ui-patterns-props-identifier">correct-value🔥</div>', + ], + ]; + } + +} diff --git a/tests/src/Unit/PropTypeNormalization/LinksPropTypeNormalizationTest.php b/tests/src/Kernel/PropTypeNormalization/LinksPropTypeTest.php similarity index 63% rename from tests/src/Unit/PropTypeNormalization/LinksPropTypeNormalizationTest.php rename to tests/src/Kernel/PropTypeNormalization/LinksPropTypeTest.php index b4028366a131fa6d311cba3c1e5002d23e7d8c1b..237e22497d83f4e2a4bbfe2a9e66b24e5aeb1dac 100644 --- a/tests/src/Unit/PropTypeNormalization/LinksPropTypeNormalizationTest.php +++ b/tests/src/Kernel/PropTypeNormalization/LinksPropTypeTest.php @@ -2,38 +2,110 @@ declare(strict_types=1); -namespace Drupal\Tests\ui_patterns\Unit; +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; +use Drupal\Core\Render\Markup; use Drupal\Core\Template\Attribute; use Drupal\Core\Url; -use Drupal\Tests\UnitTestCase; +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; use Drupal\ui_patterns\Plugin\UiPatterns\PropType\LinksPropType; /** - * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\LinksPropType + * Test LinksPropType normalization. * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\LinksPropType * @group ui_patterns */ -final class LinksPropTypeNormalizationTest extends UnitTestCase { +class LinksPropTypeTest extends PropTypeNormalizationTestBase { /** - * Test the method ::normalize(). + * Test normalize static method. * - * @dataProvider provideNormalizationData + * @dataProvider normalizationTests */ - public function testNormalize(array $value, array $expected): void { - $normalized = LinksPropType::normalize($value); - self::assertEquals($normalized, $expected); + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = LinksPropType::normalize($value, $this->testComponentProps['links']); + $this->assertEquals($normalized, $expected); } /** - * Provide data for testNormalize. + * Test rendered component with prop. + * + * @dataProvider renderingTests */ - public static function provideNormalizationData(): \Generator { - $data = [ - "Empty value" => [ - "value" => [], - "expected" => [], + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('links', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, []], + "single item" => [ + [[ + "url" => "https://drupal.org", + "title" => "Drupal", + ], + ], + [[ + "url" => "https://drupal.org", + "title" => "Drupal", + ], + ], + ], + "single item with integer title" => [ + [[ + "url" => "https://drupal.org", + "title" => 2, + ], + ], + [[ + "url" => "https://drupal.org", + "title" => 2, + ], + ], + ], + "single item with markup title" => [ + [[ + "url" => Url::fromUri("https://drupal.org"), + "title" => Markup::create("Drupal"), + ], + ], + [[ + "url" => "https://drupal.org", + "title" => "Drupal", + ], + ], + ], + "single item with nolink url" => [ + [[ + "url" => "<nolink>", + "title" => "Drupal", + ], + ], + [[ + "url" => "<nolink>", + "title" => "Drupal", + ], + ], + ], + "single item with front url and svg" => [ + [[ + "url" => "<front>", + "title" => "<svg xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"> + <path d=\"m8 3.293 4.712 4.712A4.5 4.5 0 0 0 8.758 15H3.5A1.5 1.5 0 0 1 2 13.5V9.293z\"></path> + </svg>", + ], + ], + [[ + "url" => "<front>", + "title" => "<svg xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"> + <path d=\"m8 3.293 4.712 4.712A4.5 4.5 0 0 0 8.758 15H3.5A1.5 1.5 0 0 1 2 13.5V9.293z\"></path> + </svg>", + ], + ], ], "Standardized structure, flat, only primitives" => self::standardizedFlatPrimitives(), // "Standardized structure, flat, with objects" => @@ -45,12 +117,60 @@ final class LinksPropTypeNormalizationTest extends UnitTestCase { // "Menu, as generated by the Menu module" => self::menu(), "Where link_attributes is already manually set" => self::linkAttributes(), ]; - foreach ($data as $label => $test) { - yield $label => [ - $test['value'], - $test['expected'], - ]; - }; + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + '<div class="ui-patterns-props-links"></div>', + ], + "single item" => [ + [[ + "url" => "https://drupal.org", + "title" => "Drupal", + ], + ], + '<a href="https://drupal.org">Drupal</a>', + ], + "single item with integer title" => [ + [[ + "url" => "https://drupal.org", + "title" => 2, + ], + ], + '<a href="https://drupal.org">2</a>', + ], + "single item with markup title" => [ + [[ + "url" => Url::fromUri("https://drupal.org"), + "title" => Markup::create("Drupal"), + ], + ], + '<a href="https://drupal.org">Drupal</a>', + ], + "single item with nolink url" => [ + [[ + "url" => "<nolink>", + "title" => "Drupal", + ], + ], + '<div class="ui-patterns-props-url"></div>', + ], + "single item with front url and svg" => [ + [[ + "url" => "<front>", + "title" => "<svg xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"> + <path d=\"m8 3.293 4.712 4.712A4.5 4.5 0 0 0 8.758 15H3.5A1.5 1.5 0 0 1 2 13.5V9.293z\"></path> + </svg>", + ], + ], + "><svg xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"><path d=\"m8 3.293 4.712 4.712A4.5 4.5 0 0 0 8.758 15H3.5A1.5 1.5 0 0 1 2 13.5V9.293z\"></path></svg></a>", + ], + ]; } /** @@ -74,10 +194,7 @@ final class LinksPropTypeNormalizationTest extends UnitTestCase { ], ]; $expected = $value; - return [ - "value" => $value, - "expected" => $expected, - ]; + return [$value, $expected]; } /** @@ -119,10 +236,7 @@ final class LinksPropTypeNormalizationTest extends UnitTestCase { "url" => "/foo/bar", ], ]; - return [ - "value" => $value, - "expected" => $expected, - ]; + return [$value, $expected]; } /** @@ -152,10 +266,7 @@ final class LinksPropTypeNormalizationTest extends UnitTestCase { "url" => "/foo", ], ]; - return [ - "value" => $value, - "expected" => $expected, - ]; + return [$value, $expected]; } /** @@ -189,10 +300,7 @@ final class LinksPropTypeNormalizationTest extends UnitTestCase { "url" => "/articles?page=2", ], ]; - return [ - "value" => $value, - "expected" => $expected, - ]; + return [$value, $expected]; } /** @@ -240,10 +348,7 @@ final class LinksPropTypeNormalizationTest extends UnitTestCase { "url" => "?page=3", ], ]; - return [ - "value" => $value, - "expected" => $expected, - ]; + return [$value, $expected]; } /** @@ -290,10 +395,7 @@ final class LinksPropTypeNormalizationTest extends UnitTestCase { "url" => "?page=3", ], ]; - return [ - "value" => $value, - "expected" => $expected, - ]; + return [$value, $expected]; } /** @@ -335,10 +437,7 @@ final class LinksPropTypeNormalizationTest extends UnitTestCase { "url" => "/user/logout", ], ]; - return [ - "value" => $value, - "expected" => $expected, - ]; + return [$value, $expected]; } /** @@ -372,10 +471,7 @@ final class LinksPropTypeNormalizationTest extends UnitTestCase { ], ], ]; - return [ - "value" => $value, - "expected" => $expected, - ]; + return [$value, $expected]; } } diff --git a/tests/src/Kernel/PropTypeNormalization/ListPropTypeTest.php b/tests/src/Kernel/PropTypeNormalization/ListPropTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fbd443564f688e6a388d5dc04dc958dfc82c5ff6 --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/ListPropTypeTest.php @@ -0,0 +1,58 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; +use Drupal\ui_patterns\Plugin\UiPatterns\PropType\ListPropType; + +/** + * Test ListPropType normalization. + * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\ListPropType + * @group ui_patterns + */ +class ListPropTypeTest extends PropTypeNormalizationTestBase { + + /** + * Test normalize static method. + * + * @dataProvider normalizationTests + */ + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = ListPropType::normalize($value, $this->testComponentProps['list_mixed']); + $this->assertEquals($normalized, $expected); + } + + /** + * Test rendered component with prop. + * + * @dataProvider renderingTests + */ + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('list_mixed', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, NULL], + ]; + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + '<div class="ui-patterns-props-list_mixed"></div>', + ], + ]; + } + +} diff --git a/tests/src/Kernel/PropTypeNormalization/NumberPropTypeTest.php b/tests/src/Kernel/PropTypeNormalization/NumberPropTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d29d489e309b66413ea6de5b7b7dbb77baf7e7cb --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/NumberPropTypeTest.php @@ -0,0 +1,58 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; +use Drupal\ui_patterns\Plugin\UiPatterns\PropType\NumberPropType; + +/** + * Test NumberPropType normalization. + * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\NumberPropType + * @group ui_patterns + */ +class NumberPropTypeTest extends PropTypeNormalizationTestBase { + + /** + * Test normalize static method. + * + * @dataProvider normalizationTests + */ + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = NumberPropType::normalize($value, $this->testComponentProps['number']); + $this->assertEquals($normalized, $expected); + } + + /** + * Test rendered component with prop. + * + * @dataProvider renderingTests + */ + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('number', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, NULL], + ]; + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + '<div class="ui-patterns-props-number"></div>', + ], + ]; + } + +} diff --git a/tests/src/Kernel/PropTypeNormalization/SlotPropTypeTest.php b/tests/src/Kernel/PropTypeNormalization/SlotPropTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e0afe86ee14beb5a999d444bdb3e66751f904b79 --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/SlotPropTypeTest.php @@ -0,0 +1,74 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Core\Render\Markup; +use Drupal\Core\StringTranslation\TranslatableMarkup; +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; +use Drupal\ui_patterns\Plugin\UiPatterns\PropType\SlotPropType; + +/** + * Test SlotPropType normalization. + * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\SlotPropType + * @group ui_patterns + */ +class SlotPropTypeTest extends PropTypeNormalizationTestBase { + + /** + * Test normalize static method. + * + * @dataProvider normalizationTests + */ + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = SlotPropType::normalize($value); + $this->assertEquals($normalized, $expected); + } + + /** + * Test rendered component with prop. + * + * @dataProvider renderingTests + */ + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('slot', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, NULL], + ]; + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + '<div class="ui-patterns-slots-slot"></div>', + ], + "string value" => ["my slot", "my slot"], + "string in array" => [["my slot"], "my slot"], + "string as array value" => [["aa" => "my slot"], "my slot"], + "markup value" => [Markup::create("my slot"), "my slot"], + "markup in array" => [[Markup::create("my slot")], "my slot"], + "markup in array value" => [["uu" => Markup::create("my slot")], "my slot"], + "translatable" => [new TranslatableMarkup("my slot"), "my slot"], + "t function" => [t("my slot"), "my slot"], + "array value" => [["#markup" => "my slot"], "my slot"], + "inline template" => [["#type" => "inline_template", "#template" => "my slot"], "my slot"], + "array value with weight" => [ + ["b" => ["#weight" => 2, "#markup" => "slot"], "a" => ["#weight" => 1, "#markup" => "my "]], + "my slot", + ], + ]; + } + +} diff --git a/tests/src/Kernel/PropTypeNormalization/StringPropTypeTest.php b/tests/src/Kernel/PropTypeNormalization/StringPropTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..94418d1b9ac1f8ebff485d7933364c497481fbd8 --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/StringPropTypeTest.php @@ -0,0 +1,79 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Core\Link; +use Drupal\Core\Render\Markup; +use Drupal\Core\Url; +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; +use Drupal\ui_patterns\Plugin\UiPatterns\PropType\StringPropType; + +/** + * Test StringPropType normalization. + * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\StringPropType + * @group ui_patterns + */ +class StringPropTypeTest extends PropTypeNormalizationTestBase { + + /** + * Test normalize static method. + * + * @dataProvider normalizationTests + */ + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = StringPropType::normalize($value, $this->testComponentProps['string']); + $this->assertEquals($normalized, $expected); + } + + /** + * Test rendered component with prop. + * + * @dataProvider renderingTests + */ + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('string', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, ""], + "string" => ["my string", "my string"], + "string empty" => ["", ""], + "int" => [2, "2"], + "render array" => [["#markup" => "my string"], "my string"], + "string with markup" => [Markup::create("my string"), "my string"], + "string with url" => [Url::fromUri("https://drupal.org"), "https://drupal.org"], + ]; + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + '<div class="ui-patterns-props-string"></div>', + ], + "string with link" => [ + Link::fromTextAndUrl(Markup::create("test"), Url::fromUri("https://drupal.org")), + '<div class="ui-patterns-props-string"><a href="https://drupal.org">test</a></div>', + ], + "html string" => [ + "<b>test</b>", + '<div class="ui-patterns-props-string"><b>test</b></div>', + ], + "html markup object" => [ + Markup::create("<b>test</b>"), + '<div class="ui-patterns-props-string"><b>test</b></div>', + ], + ]; + } + +} diff --git a/tests/src/Kernel/PropTypeNormalization/UrlPropTypeTest.php b/tests/src/Kernel/PropTypeNormalization/UrlPropTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..666788dbbbd440fa4927e48b025b33dbfbc2beb3 --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/UrlPropTypeTest.php @@ -0,0 +1,151 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Core\Url; +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; +use Drupal\ui_patterns\Plugin\UiPatterns\PropType\UrlPropType; + +/** + * Test UrlPropType normalization. + * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\UrlPropType + * @group ui_patterns + */ +class UrlPropTypeTest extends PropTypeNormalizationTestBase { + + /** + * Test normalize static method. + * + * @dataProvider normalizationTests + */ + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = UrlPropType::normalize($value, $this->testComponentProps['url']); + $this->assertEquals($normalized, $expected); + } + + /** + * Test normalize static method manually. + * + * We need the container to be initialized to use the Url::fromUri method. + * So it's not possible to use a dataProvider for this test. + */ + public function testNormalizationManualData() : void { + $tests = [ + "uri" => [Url::fromUri("https://drupal.org"), "https://drupal.org"], + "uri internal" => [Url::fromUri("internal:/user"), "/user"], + "uri internal front" => [Url::fromUri("internal:/"), "/"], + ]; + foreach ($tests as $test) { + $value = $test[0]; + $expected = $test[1]; + $normalized = UrlPropType::normalize($value, $this->testComponentProps['url']); + $this->assertEquals($normalized, $expected); + } + } + + /** + * Test rendered component with prop. + * + * @dataProvider renderingTests + */ + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('url', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, ""], + "string" => ["https://drupal.org", "https://drupal.org"], + "string empty" => ["", ""], + "uri internal classic" => ["/user", "/user"], + "uri from shortcut" => ["<front>", "/"], + ] + self::notAnUrl() + self::validUrl(); + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + '<div class="ui-patterns-props-url"></div>', + ], + ]; + } + + /** + * Not an URL. + */ + protected static function notAnUrl() { + return [ + "Empty string" => [ + "", + "", + ], + "Boolean" => [ + TRUE, + "", + ], + "Integer" => [ + 3, + "", + ], + "Array" => [ + [], + "", + ], + ]; + } + + /** + * Valid URL. + */ + protected static function validUrl() { + return [ + "HTTP URL (domain only)" => [ + "http://www.foo.com", + "http://www.foo.com", + ], + "HTTP URL" => [ + "http://www.foo.com/path/to", + "http://www.foo.com/path/to", + ], + "HTTPS URL" => [ + "https://www.foo.com/path/to", + "https://www.foo.com/path/to", + ], + "HTTP(S) URL" => [ + "//www.foo.com/path/to", + "//www.foo.com/path/to", + ], + "SFTP URL" => [ + "sftp://www.foo.com/path/to", + "sftp://www.foo.com/path/to", + ], + "Full path" => [ + "/path/to", + "/path/to", + ], + "Relative path" => [ + "path/to", + "path/to", + ], + "HTTPS IRI" => [ + "https://en.tranché.org/bien-sûr", + "https://en.tranché.org/bien-sûr", + ], + "HTTPS IRI percent encoded" => [ + "https://en.wiktionary.org/wiki/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82", + "https://en.wiktionary.org/wiki/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82", + ], + ]; + } + +} diff --git a/tests/src/Kernel/PropTypeNormalization/VariantPropTypeTest.php b/tests/src/Kernel/PropTypeNormalization/VariantPropTypeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f0624ba471a429dca77ac4c676780ae00a80148c --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalization/VariantPropTypeTest.php @@ -0,0 +1,74 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel\PropTypeNormalization; + +use Drupal\Tests\ui_patterns\Kernel\PropTypeNormalizationTestBase; +use Drupal\ui_patterns\Plugin\UiPatterns\PropType\VariantPropType; + +/** + * Test VariantPropType normalization. + * + * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\VariantPropType + * @group ui_patterns + */ +class VariantPropTypeTest extends PropTypeNormalizationTestBase { + + /** + * Test normalize static method. + * + * @dataProvider normalizationTests + */ + public function testNormalization(mixed $value, mixed $expected) : void { + $normalized = VariantPropType::normalize($value, $this->testComponentProps['variant']); + $this->assertEquals($normalized, $expected); + } + + /** + * Test rendered component with prop. + * + * @dataProvider renderingTests + */ + public function testRendering(mixed $value, mixed $rendered_value) : void { + $this->runRenderPropTest('variant', ["value" => $value, "rendered_value" => $rendered_value]); + } + + /** + * Provides data for testNormalization. + */ + public static function normalizationTests() : array { + return [ + "null value" => [NULL, ""], + "empty string" => ["", ""], + "default value" => ["default", "default"], + "other value" => ["other", "other"], + "bad value" => ["BAD", ""], + "integer value" => [2, ""], + "array value" => [[], ""], + "object value" => [new \stdClass(), ""], + "render array" => [["#markup" => "other"], "other"], + ]; + } + + /** + * Provides data for testNormalization. + */ + public static function renderingTests() : array { + return [ + "null value" => [ + NULL, + ' class="ui-patterns-test-component ui-patterns-test-component-variant-"', + ], + "empty value" => [ + "", + ' class="ui-patterns-test-component ui-patterns-test-component-variant-"', + ], + "other" => [ + "other", + ' class="ui-patterns-test-component ui-patterns-test-component-variant-other"', + ], + ]; + } + +} diff --git a/tests/src/Kernel/PropTypeNormalizationTestBase.php b/tests/src/Kernel/PropTypeNormalizationTestBase.php new file mode 100644 index 0000000000000000000000000000000000000000..33b62d1b6fdadf06955a955b997dbade7933387a --- /dev/null +++ b/tests/src/Kernel/PropTypeNormalizationTestBase.php @@ -0,0 +1,85 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns\Kernel; + +use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\ui_patterns\Traits\TestDataTrait; + +/** + * Base class to test prop type normalization. + * + * @group ui_patterns + */ +abstract class PropTypeNormalizationTestBase extends KernelTestBase { + + use TestDataTrait; + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'system', + 'user', + 'text', + 'field', + 'node', + 'ui_patterns', + 'ui_patterns_test', + 'datetime', + 'filter', + ]; + + /** + * @var array|null + * The test component props. + */ + protected ?array $testComponentProps; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + $this->installSchema('node', 'node_access'); + $this->installEntitySchema('node'); + $this->installEntitySchema('user'); + $this->installConfig(['system', 'filter']); + $component = \Drupal::service('plugin.manager.sdc')->find('ui_patterns_test:test-component'); + $this->testComponentProps = $component->metadata->schema['properties'] ?? []; + } + + /** + * Run tests with a given prop. + * + * @param string $prop + * The prop to test. + * @param array $tested_value + * The tested value. + */ + protected function runRenderPropTest(string $prop, array $tested_value) : void { + $expectedOutput = [ + "rendered_value" => $tested_value["rendered_value"], + "assert" => $tested_value["assert"] ?? "assertStringContainsString", + ]; + $exception_class = $tested_value["exception_class"] ?? NULL; + if (!empty($exception_class)) { + $this->expectException($exception_class); + } + $this->assertExpectedOutput($expectedOutput, [ + "#type" => "inline_template", + "#template" => sprintf("{{ include('ui_patterns_test:test-component', {%s: injected}) }}", $prop), + "#context" => ["injected" => $tested_value["value"]], + ]); + if (!empty($exception_class)) { + $this->expectException($exception_class); + } + $this->assertExpectedOutput($expectedOutput, [ + "#type" => "component", + '#component' => 'ui_patterns_test:test-component', + "#props" => [$prop => $tested_value["value"]], + ]); + } + +} diff --git a/tests/src/Kernel/PropTypesNormalizationTest.php b/tests/src/Kernel/PropTypesNormalizationTest.php deleted file mode 100644 index 2b79bb237eb247b5f524ad71a80115989aa9f806..0000000000000000000000000000000000000000 --- a/tests/src/Kernel/PropTypesNormalizationTest.php +++ /dev/null @@ -1,366 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\Tests\ui_patterns\Kernel; - -use Drupal\Core\Link; -use Drupal\Core\Render\Markup; -use Drupal\Core\StringTranslation\TranslatableMarkup; -use Drupal\Core\Template\Attribute; -use Drupal\Core\Url; -use Drupal\KernelTests\KernelTestBase; -use Drupal\Tests\ui_patterns\Traits\TestDataTrait; - -/** - * Test prop types normalization. - * - * @group ui_patterns - */ -class PropTypesNormalizationTest extends KernelTestBase { - - use TestDataTrait; - - /** - * {@inheritdoc} - */ - protected static $modules = [ - 'system', - 'user', - 'text', - 'field', - 'node', - 'ui_patterns', - 'ui_patterns_test', - 'datetime', - 'filter', - ]; - - /** - * {@inheritdoc} - */ - protected function setUp(): void { - parent::setUp(); - $this->installSchema('node', 'node_access'); - $this->installEntitySchema('node'); - $this->installEntitySchema('user'); - $this->installConfig(['system', 'filter']); - } - - /** - * Test prop normalization. - * - * @dataProvider propTypeDataProvider - */ - public function testPropTypeNormalization(string $prop, array $tested_values) : void { - $render_array_test = [ - "#type" => "inline_template", - "#template" => sprintf("{{ include('ui_patterns_test:test-component', {%s: injected}) }}", $prop), - "#context" => ["injected" => ""], - ]; - foreach ($tested_values as $tested_value) { - $this->assertExpectedOutput( - [ - "rendered_value" => $tested_value["rendered_value"], - "assert" => $tested_value["assert"] ?? "assertStringContainsString", - ], - array_merge($render_array_test, ["#context" => $tested_value["#context"]]) - ); - } - // With render array. - $render_array_test = [ - "#type" => "component", - '#component' => 'ui_patterns_test:test-component', - "#props" => [$prop => []], - ]; - foreach ($tested_values as $tested_value) { - $render_array_test["#props"][$prop] = $tested_value["#context"]["injected"]; - - $this->assertExpectedOutput( - [ - "rendered_value" => $tested_value["rendered_value"], - "assert" => $tested_value["assert"] ?? "assertStringContainsString", - ], - $render_array_test - ); - } - } - - /** - * Provides prop type data. - */ - public static function propTypeDataProvider() : array { - $returned = []; - // Url. - $returned["url"] = [ - "url", - [ - ["#context" => ["injected" => "https://drupal.org"], "rendered_value" => "https://drupal.org"], - ["#context" => ["injected" => Url::fromUri("https://drupal.org")], "rendered_value" => "https://drupal.org"], - ["#context" => ["injected" => "/user"], "rendered_value" => "/user"], - ["#context" => ["injected" => "internal:/user"], "rendered_value" => "/user"], - ], - ]; - // Links. - $returned["links"] = [ - "links", - [ - [ - "#context" => [ - "injected" => [ - [ - "url" => "https://drupal.org", - "title" => "Drupal", - ], - ], - ], - "rendered_value" => '<a href="https://drupal.org">Drupal</a>', - ], - [ - "#context" => [ - "injected" => [ - [ - "url" => "https://drupal.org", - "title" => 2, - ], - ], - ], - "rendered_value" => '<a href="https://drupal.org">2</a>', - ], - [ - "#context" => [ - "injected" => [ - [ - "url" => Url::fromUri("https://drupal.org"), - "title" => Markup::create("Drupal"), - ], - ], - ], - "rendered_value" => '<a href="https://drupal.org">Drupal</a>', - ], - [ - "#context" => [ - "injected" => [ - [ - "url" => "<nolink>", - "title" => "Drupal", - ], - ], - ], - "rendered_value" => '<div class="ui-patterns-props-url"></div>', - ], - [ - "#context" => [ - "injected" => [ - [ - "url" => "<front>", - "title" => "<svg xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"> - <path d=\"m8 3.293 4.712 4.712A4.5 4.5 0 0 0 8.758 15H3.5A1.5 1.5 0 0 1 2 13.5V9.293z\"></path> - </svg>", - ], - ], - ], - "rendered_value" => "><svg xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"><path d=\"m8 3.293 4.712 4.712A4.5 4.5 0 0 0 8.758 15H3.5A1.5 1.5 0 0 1 2 13.5V9.293z\"></path></svg></a>", - ], - ], - ]; - // Enum integer. - $returned["enum_integer"] = [ - "enum_integer", - [ - ["#context" => ["injected" => 2], "rendered_value" => '<div class="ui-patterns-props-enum_integer">2</div>'], - ["#context" => ["injected" => "2"], "rendered_value" => '<div class="ui-patterns-props-enum_integer">2</div>'], - [ - "#context" => ["injected" => "BAD VALUE"], - "rendered_value" => '<div class="ui-patterns-props-enum_integer"></div>', - ], - [ - "#context" => ["injected" => new \stdClass()], - "rendered_value" => '<div class="ui-patterns-props-enum_integer"></div>', - ], - [ - "#context" => ["injected" => [2]], - "rendered_value" => '<div class="ui-patterns-props-enum_integer">2</div>', - ], - [ - "#context" => ["injected" => ["aa" => 2]], - "rendered_value" => '<div class="ui-patterns-props-enum_integer">2</div>', - ], - [ - "#context" => ["injected" => ["1" => NULL, "aa" => 2]], - "rendered_value" => '<div class="ui-patterns-props-enum_integer">2</div>', - ], - [ - "#context" => ["injected" => ['#markup' => "2"]], - "rendered_value" => '<div class="ui-patterns-props-enum_integer">2</div>', - ], - ], - ]; - // enum_list_multiple. - $returned["enum_list_multiple"] = [ - "enum_list_multiple", - [ - [ - "#context" => ["injected" => [2]], - "rendered_value" => '<div class="ui-patterns-props-enum_list_multiple"><span>2</span></div>', - ], - [ - "#context" => ["injected" => ["2"]], - "rendered_value" => '<div class="ui-patterns-props-enum_list_multiple"><span>2</span></div>', - ], - [ - "#context" => ["injected" => "2"], - "rendered_value" => '<div class="ui-patterns-props-enum_list_multiple"><span>2</span></div>', - ], - [ - "#context" => ["injected" => [2, 2, 2]], - "rendered_value" => - '<div class="ui-patterns-props-enum_list_multiple"><span>2</span><span>2</span><span>2</span></div>', - ], - [ - "#context" => ["injected" => [2, "BAD", 2, 2, 444, "BAD", new Attribute(), [2]]], - "rendered_value" => - '<div class="ui-patterns-props-enum_list_multiple"><span>2</span><span>2</span><span>2</span></div>', - ], - ], - ]; - // enum_set. - $returned["enum_set"] = [ - "enum_set", - [ - [ - "#context" => ["injected" => [2]], - "rendered_value" => '<div class="ui-patterns-props-enum_set"><span>2</span></div>', - ], - [ - "#context" => ["injected" => ["2"]], - "rendered_value" => '<div class="ui-patterns-props-enum_set"><span>2</span></div>', - ], - [ - "#context" => ["injected" => "2"], - "rendered_value" => '<div class="ui-patterns-props-enum_set"><span>2</span></div>', - ], - [ - "#context" => ["injected" => [2, 2, 2]], - "rendered_value" => - '<div class="ui-patterns-props-enum_set"><span>2</span></div>', - ], - [ - "#context" => ["injected" => [2, "BAD", 2, 2, 444, "BAD", new Attribute(), [2]]], - "rendered_value" => - '<div class="ui-patterns-props-enum_set"><span>2</span></div>', - ], - ], - ]; - // Strings. - $returned["string"] = [ - "string", - [ - ["#context" => ["injected" => "my string"], "rendered_value" => "my string"], - [ - "#context" => ["injected" => ['#markup' => "my string2"]], - "rendered_value" => "my string2", - ], - [ - "#context" => ["injected" => Markup::create("my string3")], - "rendered_value" => "my string3", - ], - [ - "#context" => ["injected" => Url::fromUri("https://drupal.org")], - "rendered_value" => "https://drupal.org", - ], - [ - "#context" => [ - "injected" => - Link::fromTextAndUrl(Markup::create("test"), Url::fromUri("https://drupal.org")), - ], - "rendered_value" => - '<div class="ui-patterns-props-string"><a href="https://drupal.org">test</a></div>', - ], - ["#context" => ["injected" => ""], "rendered_value" => ""], - ["#context" => ["injected" => NULL], "rendered_value" => ""], - ["#context" => ["injected" => 2], "rendered_value" => "2"], - ], - ]; - // Variants. - $returned["variant"] = [ - "variant", - [ - ["#context" => ["injected" => "default"], "rendered_value" => "ui-patterns-test-component-variant-default"], - ["#context" => ["injected" => ""], "rendered_value" => "ui-patterns-test-component-variant-"], - ["#context" => ["injected" => "other"], "rendered_value" => "ui-patterns-test-component-variant-other"], - ["#context" => ["injected" => "BAD"], "rendered_value" => "ui-patterns-test-component-variant-"], - ["#context" => ["injected" => 2], "rendered_value" => "ui-patterns-test-component-variant-"], - ["#context" => ["injected" => []], "rendered_value" => "ui-patterns-test-component-variant-"], - ["#context" => ["injected" => new \stdClass()], "rendered_value" => "ui-patterns-test-component-variant-"], - ], - ]; - // Test slot values. - $tested_slot_values = [ - Markup::create("my slot"), - new TranslatableMarkup("my slot"), - ["my slot"], - "my slot", - [Markup::create("my slot")], - ["uu" => Markup::create("my slot")], - ["#markup" => "my slot"], - ["a" => ["#markup" => "my "], "b" => ["#markup" => "slot"]], - ["a" => ["#markup" => "my "], "b" => ["slot"]], - ["b" => ["#weight" => 2, "#markup" => "slot"], "a" => ["#weight" => 1, "#markup" => "my "]], - ["aa" => "my slot"], - t("my slot"), - ["#type" => "inline_template", "#template" => "my slot"], - ]; - $returned["slot"] = [ - "slot", - [], - ]; - foreach ($tested_slot_values as $tested_value) { - $returned["slot"][1][] = ["#context" => ["injected" => $tested_value], "rendered_value" => "my slot"]; - } - return $returned; - } - - /** - * Test slot normalization. - */ - public function testNestedComponentWithForm() : void { - // Test nested component with form. - $render_array_tests = [ - [ - "#type" => "inline_template", - "#template" => " - {% set comp_form = include('ui_patterns_test:test-form-component', {}) %} - {{ include('ui_patterns_test:test-component', {slot: comp_form}) }}", - "#context" => [], - ], - [ - "#type" => "component", - '#component' => 'ui_patterns_test:test-component', - "#slots" => [ - "slot" => [ - "#type" => "component", - '#component' => 'ui_patterns_test:test-form-component', - ], - ], - ], - ]; - foreach ($render_array_tests as $render_array_test) { - $this->assertExpectedOutput( - [ - "rendered_value" => "<input ", - "assert" => "assertStringContainsString", - ], - $render_array_test - ); - $this->assertExpectedOutput( - [ - "rendered_value" => "<form ", - "assert" => "assertStringContainsString", - ], - $render_array_test - ); - } - } - -} diff --git a/tests/src/Traits/TestDataTrait.php b/tests/src/Traits/TestDataTrait.php index 78b6f9c0d8c6f641beb953e7a0af7f749b336381..a2baf6aebf1a2226d8a9ff7f6102681c0b739308 100644 --- a/tests/src/Traits/TestDataTrait.php +++ b/tests/src/Traits/TestDataTrait.php @@ -104,14 +104,7 @@ trait TestDataTrait { } if (isset($expected_result['rendered_value']) || isset($expected_result['rendered_value_plain'])) { // $rendered = \Drupal::service('renderer')->renderRoot($result); - $rendered = NULL; - try { - $rendered = is_array($result) ? \Drupal::service('renderer')->renderRoot($result) : $result; - } - catch (\Exception $e) { - // @phpstan-ignore-next-line - $this->assertTrue(FALSE, sprintf("%s: ERROR, failed to render result: %s \n (%s)", $message, $e->getMessage(), print_r($result, TRUE))); - } + $rendered = is_array($result) ? \Drupal::service('renderer')->renderInIsolation($result) : $result; if ($rendered instanceof MarkupInterface) { $rendered = "" . $rendered; } diff --git a/tests/src/Unit/PropTypeNormalization/UrlPropTypeNormalizationTest.php b/tests/src/Unit/PropTypeNormalization/UrlPropTypeNormalizationTest.php deleted file mode 100644 index 0eee9fa1f2c64618a6acf12665f4aef16237ffc0..0000000000000000000000000000000000000000 --- a/tests/src/Unit/PropTypeNormalization/UrlPropTypeNormalizationTest.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\Tests\ui_patterns\Unit; - -use Drupal\Tests\UnitTestCase; -use Drupal\ui_patterns\Plugin\UiPatterns\PropType\UrlPropType; - -/** - * @coversDefaultClass \Drupal\ui_patterns\Plugin\UiPatterns\PropType\UrlPropType - * - * @group ui_patterns - */ -final class UrlPropTypeNormalizationTest extends UnitTestCase { - - /** - * Test the method ::normalize(). - * - * @dataProvider provideNormalizationData - */ - public function testNormalize(mixed $value, string $expected): void { - $normalized = UrlPropType::normalize($value); - self::assertEquals($normalized, $expected); - } - - /** - * Provide data for testNormalize. - */ - public static function provideNormalizationData(): \Generator { - $data = self::notAnUrl() + self::validUrl(); - foreach ($data as $label => $test) { - yield $label => [ - $test['value'], - $test['expected'], - ]; - }; - } - - /** - * Not an URL. - */ - protected static function notAnUrl() { - return [ - "Empty string" => [ - "value" => "", - "expected" => "", - ], - "Boolean" => [ - "value" => TRUE, - "expected" => "", - ], - "Integer" => [ - "value" => 3, - "expected" => "", - ], - "Array" => [ - "value" => [], - "expected" => "", - ], - ]; - } - - /** - * Valid URL. - */ - protected static function validUrl() { - return [ - "HTTP URL (domain only)" => [ - "value" => "http://www.foo.com", - "expected" => "http://www.foo.com", - ], - "HTTP URL" => [ - "value" => "http://www.foo.com/path/to", - "expected" => "http://www.foo.com/path/to", - ], - "HTTPS URL" => [ - "value" => "https://www.foo.com/path/to", - "expected" => "https://www.foo.com/path/to", - ], - "HTTP(S) URL" => [ - "value" => "//www.foo.com/path/to", - "expected" => "//www.foo.com/path/to", - ], - "SFTP URL" => [ - "value" => "sftp://www.foo.com/path/to", - "expected" => "sftp://www.foo.com/path/to", - ], - "Full path" => [ - "value" => "/path/to", - "expected" => "/path/to", - ], - "Relative path" => [ - "value" => "path/to", - "expected" => "path/to", - ], - "HTTPS IRI" => [ - "value" => "https://en.tranché.org/bien-sûr", - "expected" => "https://en.tranché.org/bien-sûr", - ], - "HTTPS IRI percent encoded" => [ - "value" => "https://en.wiktionary.org/wiki/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82", - "expected" => "https://en.wiktionary.org/wiki/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82", - ], - ]; - } - -}