From 4daa323f256de2b8773d9ae4d30be3be4f50e4bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Andr=C3=A9?= Date: Thu, 21 Aug 2025 21:42:58 +0200 Subject: [PATCH] [TwigComponent][UX3] Remove deprecations --- src/TwigComponent/src/CVA.php | 140 ---- src/TwigComponent/src/ComponentAttributes.php | 38 +- .../src/ComponentTemplateFinder.php | 41 +- .../Compiler/TwigComponentPass.php | 20 +- .../TwigComponentExtension.php | 28 +- .../src/Event/PostMountEvent.php | 23 +- .../src/Event/PreCreateForRenderEvent.php | 8 - src/TwigComponent/src/Event/PreMountEvent.php | 10 +- .../src/Twig/ComponentExtension.php | 36 - src/TwigComponent/src/Twig/ComponentNode.php | 13 +- src/TwigComponent/tests/Fixtures/Kernel.php | 28 +- .../Integration/ComponentExtensionTest.php | 28 - .../Integration/ComponentFactoryTest.php | 36 +- src/TwigComponent/tests/Unit/CVATest.php | 673 ------------------ .../tests/Unit/ComponentAttributesTest.php | 78 -- .../Unit/ComponentTemplateFinderTest.php | 64 -- .../TwigComponentExtensionTest.php | 25 +- .../tests/Unit/Event/MountEventsTest.php | 45 -- 18 files changed, 43 insertions(+), 1291 deletions(-) delete mode 100644 src/TwigComponent/src/CVA.php delete mode 100644 src/TwigComponent/tests/Unit/CVATest.php delete mode 100644 src/TwigComponent/tests/Unit/Event/MountEventsTest.php diff --git a/src/TwigComponent/src/CVA.php b/src/TwigComponent/src/CVA.php deleted file mode 100644 index 68cc7978f66..00000000000 --- a/src/TwigComponent/src/CVA.php +++ /dev/null @@ -1,140 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\UX\TwigComponent; - -/** - * Class Variant Authority (CVA) resolver. - * - * The CVA concept is used to render multiple variations of components, applying - * a set of conditions and recipes to dynamically compose CSS class strings. - * - * @see https://cva.style/docs - * - * @doc https://symfony.com/bundles/ux-twig-component/current/index.html - * - * @author Mathéo Daninos - * - * @experimental - * - * @deprecated since Symfony UX 2.20, use CVA from the "twig/html-extra:^3.12.0" package instead. - */ -final class CVA -{ - /** - * @var list - */ - private readonly array $base; - - /** - * @param string|list $base The base classes to apply to the component - */ - public function __construct( - string|array $base = [], - /** - * The variants to apply based on recipes. - * - * Format: [variantCategory => [variantName => classes]] - * - * Example: - * 'colors' => [ - * 'primary' => 'bleu-8000', - * 'danger' => 'red-800 text-bold', - * ], - * 'size' => [...], - * - * @var array>> - */ - private readonly array $variants = [], - - /** - * The compound variants to apply based on recipes. - * - * Format: [variantsCategory => ['variantName', 'variantName'], class: classes] - * - * Example: - * [ - * 'colors' => ['primary'], - * 'size' => ['small'], - * 'class' => 'text-red-500', - * ], - * [ - * 'size' => ['large'], - * 'class' => 'font-weight-500', - * ] - * - * @var array>> - */ - private readonly array $compoundVariants = [], - - /** - * The default variants to apply if specific recipes aren't provided. - * - * Format: [variantCategory => variantName] - * - * Example: - * 'colors' => 'primary', - * - * @var array - */ - private readonly array $defaultVariants = [], - ) { - $this->base = (array) $base; - } - - public function apply(array $recipes, ?string ...$additionalClasses): string - { - $classes = [...$this->base]; - - // Resolve recipes against variants - foreach ($recipes as $recipeName => $recipeValue) { - if (\is_bool($recipeValue)) { - $recipeValue = $recipeValue ? 'true' : 'false'; - } - $recipeClasses = $this->variants[$recipeName][$recipeValue] ?? []; - $classes = [...$classes, ...(array) $recipeClasses]; - } - - // Resolve compound variants - foreach ($this->compoundVariants as $compound) { - $compoundClasses = $this->resolveCompoundVariant($compound, $recipes) ?? []; - $classes = [...$classes, ...$compoundClasses]; - } - - // Apply default variants if specific recipes aren't provided - foreach ($this->defaultVariants as $defaultVariantName => $defaultVariantValue) { - if (!isset($recipes[$defaultVariantName])) { - $variantClasses = $this->variants[$defaultVariantName][$defaultVariantValue] ?? []; - $classes = [...$classes, ...(array) $variantClasses]; - } - } - $classes = [...$classes, ...array_values($additionalClasses)]; - - $classes = implode(' ', array_filter($classes, is_string(...))); - $classes = preg_split('#\s+#', $classes, -1, \PREG_SPLIT_NO_EMPTY) ?: []; - - return implode(' ', array_unique($classes)); - } - - private function resolveCompoundVariant(array $compound, array $recipes): array - { - foreach ($compound as $compoundName => $compoundValues) { - if ('class' === $compoundName) { - continue; - } - if (!isset($recipes[$compoundName]) || !\in_array($recipes[$compoundName], (array) $compoundValues)) { - return []; - } - } - - return (array) ($compound['class'] ?? []); - } -} diff --git a/src/TwigComponent/src/ComponentAttributes.php b/src/TwigComponent/src/ComponentAttributes.php index bd4029145e2..a63057decec 100644 --- a/src/TwigComponent/src/ComponentAttributes.php +++ b/src/TwigComponent/src/ComponentAttributes.php @@ -12,7 +12,7 @@ namespace Symfony\UX\TwigComponent; use Symfony\UX\StimulusBundle\Dto\StimulusAttributes; -use Symfony\WebpackEncoreBundle\Dto\AbstractStimulusDto; +use Symfony\UX\TwigComponent\Exception\RuntimeException; use Twig\Runtime\EscaperRuntime; /** @@ -47,6 +47,10 @@ public function __toString(): string continue; } + if (null === $value) { + throw new RuntimeException('Attribute values cannot be null. If you want to remove an attribute, use the "remove()" method.'); + } + if (false === $value) { continue; } @@ -60,11 +64,6 @@ public function __toString(): string continue; } - if (null === $value) { - trigger_deprecation('symfony/ux-twig-component', '2.8.0', 'Passing "null" as an attribute value is deprecated and will throw an exception in 3.0.'); - $value = true; - } - if (!\is_scalar($value) && !($value instanceof \Stringable)) { throw new \LogicException(\sprintf('A "%s" prop was passed when creating the component. No matching "%s" property or mount() argument was found, so we attempted to use this as an HTML attribute. But, the value is not a scalar (it\'s a "%s"). Did you mean to pass this to your component or is there a typo on its name?', $key, $key, get_debug_type($value))); } @@ -198,33 +197,6 @@ public function without(string ...$keys): self return $clone; } - public function add($stimulusDto): self - { - if ($stimulusDto instanceof AbstractStimulusDto) { - trigger_deprecation('symfony/ux-twig-component', '2.9.0', 'Passing a StimulusDto to ComponentAttributes::add() is deprecated. Run "composer require symfony/stimulus-bundle" then use "attributes.defaults(stimulus_controller(\'...\'))".'); - } elseif ($stimulusDto instanceof StimulusAttributes) { - trigger_deprecation('symfony/ux-twig-component', '2.9.0', 'Calling ComponentAttributes::add() is deprecated. Instead use "attributes.defaults(stimulus_controller(\'...\'))".'); - - return $this->defaults($stimulusDto); - } else { - throw new \InvalidArgumentException(\sprintf('Argument 1 passed to "%s()" must be an instance of "%s" or "%s", "%s" given.', __METHOD__, AbstractStimulusDto::class, StimulusAttributes::class, get_debug_type($stimulusDto))); - } - - $controllersAttributes = $stimulusDto->toArray(); - $attributes = $this->attributes; - - $attributes['data-controller'] = trim(implode(' ', array_merge( - explode(' ', $attributes['data-controller'] ?? ''), - explode(' ', $controllersAttributes['data-controller'] ?? []) - ))); - unset($controllersAttributes['data-controller']); - - $clone = new self($attributes, $this->escaper); - - // add the remaining attributes for values/classes - return $clone->defaults($controllersAttributes); - } - public function remove($key): self { $attributes = $this->attributes; diff --git a/src/TwigComponent/src/ComponentTemplateFinder.php b/src/TwigComponent/src/ComponentTemplateFinder.php index 0ceb583e1f3..10e5d1f250a 100644 --- a/src/TwigComponent/src/ComponentTemplateFinder.php +++ b/src/TwigComponent/src/ComponentTemplateFinder.php @@ -11,7 +11,6 @@ namespace Symfony\UX\TwigComponent; -use Twig\Environment; use Twig\Loader\LoaderInterface; /** @@ -19,50 +18,18 @@ */ final class ComponentTemplateFinder implements ComponentTemplateFinderInterface { - private readonly LoaderInterface $loader; - public function __construct( - Environment|LoaderInterface $loader, - private readonly ?string $directory = null, + private readonly LoaderInterface $loader, + private readonly string $directory, ) { - if ($loader instanceof Environment) { - trigger_deprecation('symfony/ux-twig-component', '2.13', 'The "%s()" method will require "%s $loader" as first argument in 3.0. Passing an "Environment" instance is deprecated.', __METHOD__, LoaderInterface::class); - $loader = $loader->getLoader(); - } - $this->loader = $loader; - if (null === $this->directory) { - trigger_deprecation('symfony/ux-twig-component', '2.13', 'The "%s()" method will require "string $directory" argument in 3.0. Not defining it or passing null is deprecated.', __METHOD__); - } } public function findAnonymousComponentTemplate(string $name): ?string { - $loader = $this->loader; $componentPath = rtrim(str_replace(':', '/', $name)); - // Legacy auto-naming rules < 2.13 - if (null === $this->directory) { - if ($loader->exists('components/'.$componentPath.'.html.twig')) { - return 'components/'.$componentPath.'.html.twig'; - } - - if ($loader->exists($componentPath.'.html.twig')) { - return $componentPath.'.html.twig'; - } - - if ($loader->exists('components/'.$componentPath)) { - return 'components/'.$componentPath; - } - - if ($loader->exists($componentPath)) { - return $componentPath; - } - - return null; - } - $template = rtrim($this->directory, '/').'/'.$componentPath.'.html.twig'; - if ($loader->exists($template)) { + if ($this->loader->exists($template)) { return $template; } @@ -72,7 +39,7 @@ public function findAnonymousComponentTemplate(string $name): ?string } $template = '@'.$parts[0].'/components/'.$parts[1].'.html.twig'; - if ($loader->exists($template)) { + if ($this->loader->exists($template)) { return $template; } diff --git a/src/TwigComponent/src/DependencyInjection/Compiler/TwigComponentPass.php b/src/TwigComponent/src/DependencyInjection/Compiler/TwigComponentPass.php index 9accecbeef5..a30275624ed 100644 --- a/src/TwigComponent/src/DependencyInjection/Compiler/TwigComponentPass.php +++ b/src/TwigComponent/src/DependencyInjection/Compiler/TwigComponentPass.php @@ -35,8 +35,6 @@ public function process(ContainerBuilder $container): void $componentNames = []; $componentDefaults = $container->getParameter('ux.twig_component.component_defaults'); $container->getParameterBag()->remove('ux.twig_component.component_defaults'); - $legacyAutoNaming = $container->hasParameter('ux.twig_component.legacy_autonaming'); - $container->getParameterBag()->remove('ux.twig_component.legacy_autonaming'); foreach ($container->findTaggedServiceIds('twig.component') as $id => $tags) { $definition = $container->findDefinition($id); @@ -48,17 +46,13 @@ public function process(ContainerBuilder $container): void foreach ($tags as $tag) { if (!\array_key_exists('key', $tag)) { - if ($legacyAutoNaming) { - $name = substr($fqcn, strrpos($fqcn, '\\') + 1); - } else { - if (null === $defaults) { - throw new LogicException(\sprintf('Could not generate a component name for class "%s": no matching namespace found under the "twig_component.defaults" to use as a root. Check the config or give your component an explicit name.', $fqcn)); - } - - $name = str_replace('\\', ':', substr($fqcn, \strlen($defaults['namespace']))); - if ($defaults['name_prefix']) { - $name = \sprintf('%s:%s', $defaults['name_prefix'], $name); - } + if (null === $defaults) { + throw new LogicException(\sprintf('Could not generate a component name for class "%s": no matching namespace found under the "twig_component.defaults" to use as a root. Check the config or give your component an explicit name.', $fqcn)); + } + + $name = str_replace('\\', ':', substr($fqcn, \strlen($defaults['namespace']))); + if ($defaults['name_prefix']) { + $name = \sprintf('%s:%s', $defaults['name_prefix'], $name); } if (\in_array($name, $componentNames, true)) { throw new LogicException(\sprintf('Failed creating the "%s" component with the automatic name "%s": another component already has this name. To fix this, give the component an explicit name (hint: using "%s" will override the existing component).', $fqcn, $name, $name)); diff --git a/src/TwigComponent/src/DependencyInjection/TwigComponentExtension.php b/src/TwigComponent/src/DependencyInjection/TwigComponentExtension.php index dc71c610931..6010a182591 100644 --- a/src/TwigComponent/src/DependencyInjection/TwigComponentExtension.php +++ b/src/TwigComponent/src/DependencyInjection/TwigComponentExtension.php @@ -49,8 +49,6 @@ */ final class TwigComponentExtension extends Extension implements ConfigurationInterface { - private const DEPRECATED_DEFAULT_KEY = '__deprecated__use_old_naming_behavior'; - public function load(array $configs, ContainerBuilder $container): void { $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../../config')); @@ -62,12 +60,6 @@ public function load(array $configs, ContainerBuilder $container): void $configuration = $this->getConfiguration($configs, $container); $config = $this->processConfiguration($configuration, $configs); $defaults = $config['defaults']; - if ($defaults === [self::DEPRECATED_DEFAULT_KEY]) { - trigger_deprecation('symfony/ux-twig-component', '2.13', 'Not setting the "twig_component.defaults" config option is deprecated. Check the documentation for an example configuration.'); - $container->setParameter('ux.twig_component.legacy_autonaming', true); - - $defaults = []; - } $container->setParameter('ux.twig_component.component_defaults', $defaults); $container->register('ux.twig_component.component_template_finder', ComponentTemplateFinder::class) @@ -147,9 +139,6 @@ static function (ChildDefinition $definition, AsTwigComponent $attribute) { ->addTag('console.command') ; - $container->setAlias('console.command.stimulus_component_debug', 'ux.twig_component.command.debug') - ->setDeprecated('symfony/ux-twig-component', '2.13', '%alias_id%'); - if ($container->getParameter('kernel.debug') && $config['profiler']) { $loader->load('debug.php'); } @@ -170,19 +159,9 @@ public function getConfigTreeBuilder(): TreeBuilder \assert($rootNode instanceof ArrayNodeDefinition); $rootNode - ->validate() - ->always(function ($v) { - if (!isset($v['anonymous_template_directory'])) { - trigger_deprecation('symfony/twig-component-bundle', '2.13', 'Not setting the "twig_component.anonymous_template_directory" config option is deprecated. It will default to "components" in 3.0.'); - $v['anonymous_template_directory'] = null; - } - - return $v; - }) - ->end() ->children() ->arrayNode('defaults') - ->defaultValue([self::DEPRECATED_DEFAULT_KEY]) + ->isRequired() ->useAttributeAsKey('namespace') ->validate() ->always(function ($v) { @@ -213,16 +192,13 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->end() ->scalarNode('anonymous_template_directory') + ->isRequired() ->info('Defaults to `components`') ->end() ->booleanNode('profiler') ->info('Enables the profiler for Twig Component (in debug mode)') ->defaultValue('%kernel.debug%') ->end() - ->scalarNode('controllers_json') - ->setDeprecated('symfony/ux-twig-component', '2.18', 'The "twig_component.controllers_json" config option is deprecated, and will be removed in 3.0.') - ->defaultNull() - ->end() ->end(); return $treeBuilder; diff --git a/src/TwigComponent/src/Event/PostMountEvent.php b/src/TwigComponent/src/Event/PostMountEvent.php index 45dfed3bf65..72c0d2586b7 100644 --- a/src/TwigComponent/src/Event/PostMountEvent.php +++ b/src/TwigComponent/src/Event/PostMountEvent.php @@ -19,31 +19,12 @@ */ final class PostMountEvent extends Event { - private ?ComponentMetadata $metadata; - private array $extraMetadata; - public function __construct( private object $component, private array $data, - array|ComponentMetadata $metadata = [], - $extraMetadata = [], + private ?ComponentMetadata $metadata = null, + private array $extraMetadata = [], ) { - if (\is_array($metadata)) { - trigger_deprecation('symfony/ux-twig-component', '2.13', 'In TwigComponent 3.0, the third argument of "%s()" will be a "%s" object and the "$extraMetadata" array should be passed as the fourth argument.', __METHOD__, ComponentMetadata::class); - - $this->metadata = null; - $this->extraMetadata = $metadata; - } else { - if (null !== $metadata && !$metadata instanceof ComponentMetadata) { - throw new \InvalidArgumentException(\sprintf('Expecting "$metadata" to be null or an instance of "%s", given: "%s."', ComponentMetadata::class, get_debug_type($metadata))); - } - if (!\is_array($extraMetadata)) { - throw new \InvalidArgumentException(\sprintf('Expecting "$extraMetadata" to be array, given: "%s".', get_debug_type($extraMetadata))); - } - - $this->metadata = $metadata; - $this->extraMetadata = $extraMetadata; - } } public function getComponent(): object diff --git a/src/TwigComponent/src/Event/PreCreateForRenderEvent.php b/src/TwigComponent/src/Event/PreCreateForRenderEvent.php index 12826261a14..21a9fd0e2ed 100644 --- a/src/TwigComponent/src/Event/PreCreateForRenderEvent.php +++ b/src/TwigComponent/src/Event/PreCreateForRenderEvent.php @@ -33,14 +33,6 @@ public function getName(): string return $this->name; } - /** - * @deprecated since Symfony UX 2.8, use getInputProps() instead. - */ - public function getProps(): array - { - return $this->inputProps; - } - /** * @return array the array of "input" data passed to originally create this component */ diff --git a/src/TwigComponent/src/Event/PreMountEvent.php b/src/TwigComponent/src/Event/PreMountEvent.php index 9472bfed5b5..1a582502b0c 100644 --- a/src/TwigComponent/src/Event/PreMountEvent.php +++ b/src/TwigComponent/src/Event/PreMountEvent.php @@ -19,11 +19,11 @@ */ final class PreMountEvent extends Event { - public function __construct(private object $component, private array $data, private readonly ?ComponentMetadata $metadata = null) - { - if (null === $this->metadata) { - trigger_deprecation('symfony/ux-twig-component', '2.13', 'In TwigComponent 3.0, "%s()" method will require a "%s $metadata" argument. Not passing it is deprecated.', __METHOD__, ComponentMetadata::class); - } + public function __construct( + private object $component, + private array $data, + private readonly ComponentMetadata $metadata, + ) { } public function getComponent(): object diff --git a/src/TwigComponent/src/Twig/ComponentExtension.php b/src/TwigComponent/src/Twig/ComponentExtension.php index f577ae08dcc..38180688870 100644 --- a/src/TwigComponent/src/Twig/ComponentExtension.php +++ b/src/TwigComponent/src/Twig/ComponentExtension.php @@ -11,8 +11,6 @@ namespace Symfony\UX\TwigComponent\Twig; -use Symfony\UX\TwigComponent\CVA; -use Twig\DeprecatedCallableInfo; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; @@ -27,11 +25,6 @@ public function getFunctions(): array { return [ new TwigFunction('component', [ComponentRuntime::class, 'render'], ['is_safe' => ['all']]), - new TwigFunction('cva', [$this, 'cva'], [ - ...(class_exists(DeprecatedCallableInfo::class) - ? ['deprecation_info' => new DeprecatedCallableInfo('symfony/ux-twig-component', '2.20', 'html_cva', 'twig/html-extra')] - : ['deprecated' => '2.20', 'deprecating_package' => 'symfony/ux-twig-component', 'alternative' => 'html_cva']), - ]), ]; } @@ -42,33 +35,4 @@ public function getTokenParsers(): array new PropsTokenParser(), ]; } - - /** - * Create a CVA instance. - * - * base some base class you want to have in every matching recipes - * variants your recipes class - * compoundVariants compounds allow you to add extra class when multiple variation are matching in the same time - * defaultVariants allow you to add a default class when no recipe is matching - * - * @see https://symfony.com/bundles/ux-twig-component/current/index.html#component-with-complex-variants-cva - * - * @param array{ - * base: string|string[]|null, - * variants: array>, - * compoundVariants: list>, - * defaultVariants: array, - * } $cva - */ - public function cva(array $cva): CVA - { - trigger_deprecation('symfony/ux-twig-component', '2.20', 'Twig Function "cva" is deprecated; use "html_cva" from the "twig/html-extra" package (available since version 3.12) instead.'); - - return new CVA( - $cva['base'] ?? '', - $cva['variants'] ?? [], - $cva['compoundVariants'] ?? [], - $cva['defaultVariants'] ?? [], - ); - } } diff --git a/src/TwigComponent/src/Twig/ComponentNode.php b/src/TwigComponent/src/Twig/ComponentNode.php index 96ef9c7ca0b..291f507a93f 100644 --- a/src/TwigComponent/src/Twig/ComponentNode.php +++ b/src/TwigComponent/src/Twig/ComponentNode.php @@ -15,7 +15,6 @@ use Twig\Attribute\YieldReady; use Twig\Compiler; use Twig\Environment; -use Twig\Extension\CoreExtension; use Twig\Node\Expression\AbstractExpression; use Twig\Node\Node; use Twig\Node\NodeOutputInterface; @@ -51,15 +50,7 @@ public function compile(Compiler $compiler): void $useYield = method_exists(Environment::class, 'useYield') && $compiler->getEnvironment()->useYield(); - // since twig/twig 3.9.0: Using the internal "twig_to_array" function is deprecated. - if (method_exists(CoreExtension::class, 'toArray')) { - $twig_to_array = 'Twig\Extension\CoreExtension::toArray'; - } else { - $twig_to_array = 'twig_to_array'; - } - $componentRuntime = $compiler->getVarName(); - $compiler ->write(\sprintf('$%s = $this->env->getRuntime(', $componentRuntime)) ->string(ComponentRuntime::class) @@ -75,7 +66,7 @@ public function compile(Compiler $compiler): void ->write(\sprintf('$preRendered = $%s->preRender(', $componentRuntime)) ->string($this->getAttribute('component')) ->raw(', ') - ->raw($twig_to_array) + ->raw('Twig\Extension\CoreExtension::toArray') ->raw('('); $this->writeProps($compiler) ->raw(')') @@ -107,7 +98,7 @@ public function compile(Compiler $compiler): void ->write(\sprintf('$preRenderEvent = $%s->startEmbedComponent(', $componentRuntime)) ->string($this->getAttribute('component')) ->raw(', ') - ->raw($twig_to_array) + ->raw('Twig\Extension\CoreExtension::toArray') ->raw('('); $this->writeProps($compiler) ->raw('), ') diff --git a/src/TwigComponent/tests/Fixtures/Kernel.php b/src/TwigComponent/tests/Fixtures/Kernel.php index e320ecbaca7..dd7fe5b4ace 100644 --- a/src/TwigComponent/tests/Fixtures/Kernel.php +++ b/src/TwigComponent/tests/Fixtures/Kernel.php @@ -59,24 +59,20 @@ protected function configureContainer(ContainerConfigurator $c): void ]); $twigComponentConfig = []; - if ('legacy_autonaming' != $this->environment) { - $acmeDefaults = [ - 'name_prefix' => 'AcmePrefix', - ]; - if ('no_template_directory' !== $this->environment) { - $acmeDefaults['template_directory'] = 'acme_components'; - } - $twigComponentConfig['defaults'] = [ - 'Symfony\UX\TwigComponent\Tests\Fixtures\Component\\' => 'components/', - 'Symfony\UX\TwigComponent\Tests\Fixtures\AcmeComponent\\' => $acmeDefaults, - ]; + $acmeDefaults = [ + 'name_prefix' => 'AcmePrefix', + ]; + if ('no_template_directory' !== $this->environment) { + $acmeDefaults['template_directory'] = 'acme_components'; } + $twigComponentConfig['defaults'] = [ + 'Symfony\UX\TwigComponent\Tests\Fixtures\Component\\' => 'components/', + 'Symfony\UX\TwigComponent\Tests\Fixtures\AcmeComponent\\' => $acmeDefaults, + ]; - if ('legacy_anonymous' != $this->environment) { - $twigComponentConfig['anonymous_template_directory'] = 'components'; - if ('anonymous_directory' == $this->environment) { - $twigComponentConfig['anonymous_template_directory'] = 'anonymous'; - } + $twigComponentConfig['anonymous_template_directory'] = 'components'; + if ('anonymous_directory' === $this->environment) { + $twigComponentConfig['anonymous_template_directory'] = 'anonymous'; } $c->extension('twig_component', $twigComponentConfig); diff --git a/src/TwigComponent/tests/Integration/ComponentExtensionTest.php b/src/TwigComponent/tests/Integration/ComponentExtensionTest.php index 81cd3fdcefd..be86a08cb57 100644 --- a/src/TwigComponent/tests/Integration/ComponentExtensionTest.php +++ b/src/TwigComponent/tests/Integration/ComponentExtensionTest.php @@ -11,7 +11,6 @@ namespace Symfony\UX\TwigComponent\Tests\Integration; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\UX\TwigComponent\Tests\Fixtures\User; use Twig\Environment; @@ -22,8 +21,6 @@ */ final class ComponentExtensionTest extends KernelTestCase { - use ExpectDeprecationTrait; - public function testCanRenderComponent() { $output = $this->renderComponent('component_a', [ @@ -267,18 +264,6 @@ class="block" ]; } - /** - * @group legacy - */ - public function testComponentWithClassMerge() - { - $this->expectDeprecation('Since symfony/ux-twig-component 2.20: Twig Function "cva" is deprecated; use "html_cva" from the "twig/html-extra" package (available since version 3.12) instead.'); - - $output = self::getContainer()->get(Environment::class)->render('class_merge.html.twig'); - - $this->assertStringContainsString('class="alert alert-red alert-lg font-semibold rounded-md dark:bg-gray-600 flex p-4"', $output); - } - public function testRenderingComponentWithNestedAttributes() { $output = $this->renderComponent('NestedAttributes'); @@ -475,19 +460,6 @@ public static function provideUnsafeAttributes(): iterable ]); } - /** - * @group legacy - */ - public function testAnonymousComponentWithPropsOverwriteParentsProps() - { - $this->expectDeprecation('Since symfony/ux-twig-component 2.20: Twig Function "cva" is deprecated; use "html_cva" from the "twig/html-extra" package (available since version 3.12) instead.'); - - $output = self::getContainer()->get(Environment::class)->render('anonymous_component_with_props_overwrite_parents_props.html.twig'); - - $this->assertStringContainsString('I am an icon', $output); - $this->assertStringNotContainsString('I am md', $output); - } - private function renderComponent(string $name, array $data = []): string { return self::getContainer()->get(Environment::class)->render('render_component.html.twig', [ diff --git a/src/TwigComponent/tests/Integration/ComponentFactoryTest.php b/src/TwigComponent/tests/Integration/ComponentFactoryTest.php index c2189c955f4..df8c65754fb 100644 --- a/src/TwigComponent/tests/Integration/ComponentFactoryTest.php +++ b/src/TwigComponent/tests/Integration/ComponentFactoryTest.php @@ -122,36 +122,6 @@ public function testTwigComponentServiceTagWithoutKeyButCollissionCausesAnExcept self::assertInstanceOf(ComponentB::class, $component); } - /** - * @group legacy - */ - public function testLegacyAutoNaming() - { - self::bootKernel(['environment' => 'legacy_autonaming']); - $component = $this->createComponent('BasicComponent'); - self::assertInstanceOf(BasicComponent::class, $component); - } - - /** - * @group legacy - */ - public function testLegacyAnonymous() - { - self::bootKernel(['environment' => 'legacy_anonymous']); - - // Named templates should be found - $metadata = $this->factory()->metadataFor('foo:bar:baz'); - $this->assertSame('components/foo/bar/baz.html.twig', $metadata->getTemplate()); - - // Prefixed nonymous templates should be found - $metadata = $this->factory()->metadataFor('anonymous:AButton'); - $this->assertSame('anonymous/AButton.html.twig', $metadata->getTemplate()); - - // Unprefixed anonymous templates should not be found - $this->expectException(\InvalidArgumentException::class); - $this->factory()->metadataFor('AButton'); - } - public function testAnonymous() { self::bootKernel(['environment' => 'anonymous_directory']); @@ -229,13 +199,13 @@ public function testCanGetMetadataForSameComponentWithDifferentName() public function testCannotGetConfigByNameForNonRegisteredComponent() { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Unknown component "tabl". Did you mean this: "table"?'); + $this->expectExceptionMessage('Unknown component "tabler". Did you mean this: "table"?'); - $this->factory()->metadataFor('tabl'); + $this->factory()->metadataFor('tabler'); } /** - * @testWith ["tabl", "Unknown component \"tabl\". Did you mean this: \"table\"?"] + * @testWith ["tabler", "Unknown component \"tabler\". Did you mean this: \"table\"?"] * ["Basic", "Unknown component \"Basic\". Did you mean this: \"BasicComponent\"?"] * ["basic", "Unknown component \"basic\". Did you mean this: \"BasicComponent\"?"] * ["with", "Unknown component \"with\". Did you mean one of these: \"with_attributes\", \"with_exposed_variables\", \"WithSlots\"?"] diff --git a/src/TwigComponent/tests/Unit/CVATest.php b/src/TwigComponent/tests/Unit/CVATest.php deleted file mode 100644 index cf17794b126..00000000000 --- a/src/TwigComponent/tests/Unit/CVATest.php +++ /dev/null @@ -1,673 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\UX\TwigComponent\Tests\Unit; - -use PHPUnit\Framework\TestCase; -use Symfony\UX\TwigComponent\CVA; - -/** - * To remove in TwigComponent 3.0. - * - * @author Mathéo Daninos - * - * @group legacy - */ -class CVATest extends TestCase -{ - /** - * @dataProvider recipeProvider - */ - public function testRecipes(array $recipe, array $recipes, string $expected) - { - $recipeClass = new CVA( - base: $recipe['base'] ?? '', - variants: (array) ($recipe['variants'] ?? []), - compoundVariants: (array) ($recipe['compounds'] ?? []), - defaultVariants: (array) ($recipe['defaultVariants'] ?? []), - ); - - $this->assertEquals($expected, $recipeClass->apply($recipes)); - } - - public function testApply() - { - $recipe = new CVA('font-semibold border rounded', [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ], [ - [ - 'colors' => ['primary'], - 'sizes' => ['sm'], - 'class' => 'text-red-500', - ], - ]); - - $this->assertEquals('font-semibold border rounded text-primary text-sm text-red-500', $recipe->apply(['colors' => 'primary', 'sizes' => 'sm'])); - } - - public function testApplyWithNullString() - { - $recipe = new CVA('font-semibold border rounded', [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ], [ - [ - 'colors' => ['primary'], - 'sizes' => ['sm'], - 'class' => 'text-red-500', - ], - ]); - - $this->assertEquals('font-semibold border rounded text-primary text-sm text-red-500 flex justify-center', $recipe->apply(['colors' => 'primary', 'sizes' => 'sm'], 'flex', null, 'justify-center')); - } - - public static function recipeProvider(): iterable - { - yield 'base null' => [ - ['variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ]], - ['colors' => 'primary', 'sizes' => 'sm'], - 'text-primary text-sm', - ]; - - yield 'base empty' => [ - [ - 'base' => '', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ]], - ['colors' => 'primary', 'sizes' => 'sm'], - 'text-primary text-sm', - ]; - - yield 'base array' => [ - [ - 'base' => ['font-semibold', 'border', 'rounded'], - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ]], - ['colors' => 'primary', 'sizes' => 'sm'], - 'font-semibold border rounded text-primary text-sm', - ]; - - yield 'no recipes match' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ], - ], - ['colors' => 'red', 'sizes' => 'test'], - 'font-semibold border rounded', - ]; - - yield 'simple variants' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ], - ], - ['colors' => 'primary', 'sizes' => 'sm'], - 'font-semibold border rounded text-primary text-sm', - ]; - - yield 'simple variants as array' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => ['text-primary', 'uppercase'], - 'secondary' => ['text-secondary', 'uppercase'], - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ], - ], - ['colors' => 'primary', 'sizes' => 'sm'], - 'font-semibold border rounded text-primary uppercase text-sm', - ]; - - yield 'simple variants with custom' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ], - ], - ['colors' => 'secondary', 'sizes' => 'md'], - 'font-semibold border rounded text-secondary text-md', - ]; - - yield 'compound variants' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ], - 'compounds' => [ - [ - 'colors' => 'primary', - 'sizes' => ['sm'], - 'class' => 'text-red-100', - ], - ], - ], - ['colors' => 'primary', 'sizes' => 'sm'], - 'font-semibold border rounded text-primary text-sm text-red-100', - ]; - - yield 'compound variants with true' => [ - [ - 'base' => 'button', - 'variants' => [ - 'colors' => [ - 'blue' => 'btn-blue', - 'red' => 'btn-red', - ], - 'disabled' => [ - 'true' => 'disabled', - ], - ], - 'compounds' => [ - [ - 'colors' => 'blue', - 'disabled' => ['true'], - 'class' => 'font-bold', - ], - ], - ], - ['colors' => 'blue', 'disabled' => 'true'], - 'button btn-blue disabled font-bold', - ]; - - yield 'compound variants as array' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ], - 'compounds' => [ - [ - 'colors' => ['primary'], - 'sizes' => ['sm'], - 'class' => ['text-red-900', 'bold'], - ], - ], - ], - ['colors' => 'primary', 'sizes' => 'sm'], - 'font-semibold border rounded text-primary text-sm text-red-900 bold', - ]; - - yield 'multiple compound variants' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ], - 'compounds' => [ - [ - 'colors' => ['primary'], - 'sizes' => ['sm'], - 'class' => 'text-red-300', - ], - [ - 'colors' => ['primary'], - 'sizes' => ['md'], - 'class' => 'text-blue-300', - ], - ], - ], - ['colors' => 'primary', 'sizes' => 'sm'], - 'font-semibold border rounded text-primary text-sm text-red-300', - ]; - - yield 'compound with multiple variants' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ], - 'compounds' => [ - [ - 'colors' => ['primary', 'secondary'], - 'sizes' => ['sm'], - 'class' => 'text-red-800', - ], - ], - ], - ['colors' => 'primary', 'sizes' => 'sm'], - 'font-semibold border rounded text-primary text-sm text-red-800', - ]; - - yield 'compound doesn\'t match' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - ], - 'compounds' => [ - [ - 'colors' => ['danger', 'secondary'], - 'sizes' => ['sm'], - 'class' => 'text-red-500', - ], - ], - ], - ['colors' => 'primary', 'sizes' => 'sm'], - 'font-semibold border rounded text-primary text-sm', - ]; - yield 'default variables' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - 'rounded' => [ - 'sm' => 'rounded-sm', - 'md' => 'rounded-md', - 'lg' => 'rounded-lg', - ], - ], - 'compounds' => [ - [ - 'colors' => ['danger', 'secondary'], - 'sizes' => 'sm', - 'class' => 'text-red-500', - ], - ], - 'defaultVariants' => [ - 'colors' => 'primary', - 'sizes' => 'sm', - 'rounded' => 'md', - ], - ], - ['colors' => 'primary', 'sizes' => 'sm'], - 'font-semibold border rounded text-primary text-sm rounded-md', - ]; - yield 'default variables all overwrite' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - 'rounded' => [ - 'sm' => 'rounded-sm', - 'md' => 'rounded-md', - 'lg' => 'rounded-lg', - ], - ], - 'compounds' => [ - [ - 'colors' => ['danger', 'secondary'], - 'sizes' => ['sm'], - 'class' => 'text-red-500', - ], - ], - 'defaultVariants' => [ - 'colors' => 'primary', - 'sizes' => 'sm', - 'rounded' => 'md', - ], - ], - ['colors' => 'primary', 'sizes' => 'sm', 'rounded' => 'lg'], - 'font-semibold border rounded text-primary text-sm rounded-lg', - ]; - yield 'default variables without matching variants' => [ - [ - 'base' => 'font-semibold border rounded', - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'sizes' => [ - 'sm' => 'text-sm', - 'md' => 'text-md', - 'lg' => 'text-lg', - ], - 'rounded' => [ - 'sm' => 'rounded-sm', - 'md' => 'rounded-md', - 'lg' => 'rounded-lg', - ], - ], - 'compounds' => [ - [ - 'colors' => ['danger', 'secondary'], - 'sizes' => ['sm'], - 'class' => 'text-red-500', - ], - ], - 'defaultVariants' => [ - 'colors' => 'primary', - 'sizes' => 'sm', - 'rounded' => 'md', - ], - ], - [], - 'font-semibold border rounded text-primary text-sm rounded-md', - ]; - - yield 'default variables with boolean' => [ - [ - 'base' => 'button', - 'variants' => [ - 'colors' => [ - 'blue' => 'btn-blue', - 'red' => 'btn-red', - ], - 'disabled' => [ - 'true' => 'disabled', - 'false' => 'opacity-100', - ], - ], - 'defaultVariants' => [ - 'colors' => 'blue', - 'disabled' => 'false', - ], - ], - [], - 'button btn-blue opacity-100', - ]; - - yield 'boolean string variants true / true' => [ - [ - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'disabled' => [ - 'true' => 'disable', - ], - ], - ], - ['colors' => 'primary', 'disabled' => true], - 'text-primary disable', - ]; - - yield 'boolean string variants true / false' => [ - [ - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'disabled' => [ - 'true' => 'disable', - ], - ], - ], - ['colors' => 'primary', 'disabled' => false], - 'text-primary', - ]; - - yield 'boolean string variants false / true' => [ - [ - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'disabled' => [ - 'false' => 'disable', - ], - ], - ], - ['colors' => 'primary', 'disabled' => true], - 'text-primary', - ]; - - yield 'boolean string variants false / false' => [ - [ - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'disabled' => [ - 'false' => 'disable', - ], - ], - ], - ['colors' => 'primary', 'disabled' => false], - 'text-primary disable', - ]; - - yield 'boolean string variants missing' => [ - [ - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'disabled' => [ - 'true' => 'disable', - ], - ], - ], - ['colors' => 'primary'], - 'text-primary', - ]; - - yield 'boolean list variants true' => [ - [ - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'disabled' => [ - 'true' => ['disable', 'opacity-50'], - ], - ], - ], - ['colors' => 'primary', 'disabled' => true], - 'text-primary disable opacity-50', - ]; - - yield 'boolean list variants false' => [ - [ - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'disabled' => [ - 'true' => ['disable', 'opacity-50'], - ], - ], - ], - ['colors' => 'primary', 'disabled' => false], - 'text-primary', - ]; - - yield 'boolean list variants missing' => [ - [ - 'variants' => [ - 'colors' => [ - 'primary' => 'text-primary', - 'secondary' => 'text-secondary', - ], - 'disabled' => [ - 'true' => ['disable', 'opacity-50'], - ], - ], - ], - ['colors' => 'primary'], - 'text-primary', - ]; - } - - /** - * @dataProvider provideAdditionalClassesCases - */ - public function testAdditionalClasses(string|array $base, array|string $additional, string $expected) - { - $cva = new CVA($base); - if ([] === $additional || '' === $additional) { - $this->assertEquals($expected, $cva->apply([])); - } else { - $this->assertEquals($expected, $cva->apply([], ...(array) $additional)); - } - } - - public static function provideAdditionalClassesCases(): iterable - { - yield 'additionals_are_optional' => [ - '', - 'foo', - 'foo', - ]; - yield 'additional_are_used' => [ - '', - 'foo', - 'foo', - ]; - yield 'additionals_are_used' => [ - '', - ['foo', 'bar'], - 'foo bar', - ]; - yield 'additionals_preserve_order' => [ - ['foo'], - ['bar', 'foo'], - 'foo bar', - ]; - yield 'additional_are_deduplicated' => [ - '', - ['bar', 'bar'], - 'bar', - ]; - } -} diff --git a/src/TwigComponent/tests/Unit/ComponentAttributesTest.php b/src/TwigComponent/tests/Unit/ComponentAttributesTest.php index 04764e42c92..c674c39d0be 100644 --- a/src/TwigComponent/tests/Unit/ComponentAttributesTest.php +++ b/src/TwigComponent/tests/Unit/ComponentAttributesTest.php @@ -12,10 +12,8 @@ namespace Symfony\UX\TwigComponent\Tests\Unit; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\UX\StimulusBundle\Dto\StimulusAttributes; use Symfony\UX\TwigComponent\ComponentAttributes; -use Symfony\WebpackEncoreBundle\Dto\AbstractStimulusDto; use Twig\Environment; use Twig\Loader\ArrayLoader; use Twig\Runtime\EscaperRuntime; @@ -25,8 +23,6 @@ */ final class ComponentAttributesTest extends TestCase { - use ExpectDeprecationTrait; - public function testCanConvertToString() { $attributes = new ComponentAttributes([ @@ -74,69 +70,6 @@ public function testCanGetWithout() $this->assertSame(['class' => 'foo'], $attributes->without('style')->all()); } - /** - * @group legacy - */ - public function testCanAddStimulusController() - { - if (!class_exists(AbstractStimulusDto::class)) { - $this->markTestSkipped('AbstractStimulusDto class does not exist, skipping test.'); - } - - $attributes = new ComponentAttributes([ - 'class' => 'foo', - 'data-controller' => 'live', - 'data-live-data-value' => '{}', - ], new EscaperRuntime()); - - $controllerDto = $this->createMock(AbstractStimulusDto::class); - $controllerDto->expects(self::once()) - ->method('toArray') - ->willReturn([ - 'data-controller' => 'foo bar', - 'data-foo-name-value' => 'ryan', - ]); - - $attributes = $attributes->add($controllerDto); - - $this->assertEquals([ - 'class' => 'foo', - 'data-controller' => 'live foo bar', - 'data-live-data-value' => '{}', - 'data-foo-name-value' => 'ryan', - ], $attributes->all()); - } - - /** - * @group legacy - */ - public function testCanAddStimulusControllerIfNoneAlreadyPresent() - { - if (!class_exists(AbstractStimulusDto::class)) { - $this->markTestSkipped('AbstractStimulusDto class does not exist, skipping test.'); - } - - $attributes = new ComponentAttributes([ - 'class' => 'foo', - ], new EscaperRuntime()); - - $controllerDto = $this->createMock(AbstractStimulusDto::class); - $controllerDto->expects(self::once()) - ->method('toArray') - ->willReturn([ - 'data-controller' => 'foo bar', - 'data-foo-name-value' => 'ryan', - ]); - - $attributes = $attributes->add($controllerDto); - - $this->assertEquals([ - 'class' => 'foo', - 'data-controller' => 'foo bar', - 'data-foo-name-value' => 'ryan', - ], $attributes->all()); - } - public function testCanAddStimulusControllerViaStimulusAttributes() { $attributes = new ComponentAttributes([ @@ -191,17 +124,6 @@ public function testBooleanBehaviour() $this->assertSame('', (string) $attributes); } - /** - * @group legacy - */ - public function testNullBehaviour() - { - $attributes = new ComponentAttributes(['disabled' => null], new EscaperRuntime()); - - $this->assertSame(['disabled' => null], $attributes->all()); - $this->assertSame(' disabled', (string) $attributes); - } - public function testIsTraversableAndCountable() { $attributes = new ComponentAttributes(['foo' => 'bar'], new EscaperRuntime()); diff --git a/src/TwigComponent/tests/Unit/ComponentTemplateFinderTest.php b/src/TwigComponent/tests/Unit/ComponentTemplateFinderTest.php index 66a19bd0646..a741786c75b 100644 --- a/src/TwigComponent/tests/Unit/ComponentTemplateFinderTest.php +++ b/src/TwigComponent/tests/Unit/ComponentTemplateFinderTest.php @@ -12,7 +12,6 @@ namespace Symfony\UX\TwigComponent\Tests\Unit; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\UX\TwigComponent\ComponentTemplateFinder; use Twig\Environment; use Twig\Loader\ArrayLoader; @@ -23,8 +22,6 @@ */ final class ComponentTemplateFinderTest extends TestCase { - use ExpectDeprecationTrait; - public function testFindTemplate() { $templates = [ @@ -49,67 +46,6 @@ public function testFindTemplate() $this->assertNull($finder->findAnonymousComponentTemplate('c')); } - /** - * @group legacy - */ - public function testFindTemplateWithLegacyAutonaming() - { - $templates = [ - 'components/aa.html.twig', - 'components/aa:bb.html.twig', - 'components/aa/bb.html.twig', - 'a', - 'components/b', - 'components/b.html.twig', - 'b', - 'b.html.twig', - 'components/c', - 'c', - 'c.html.twig', - 'd', - 'components/d', - ]; - $environment = $this->createEnvironment($templates); - - $this->expectDeprecation('Since symfony/ux-twig-component 2.13: The "Symfony\UX\TwigComponent\ComponentTemplateFinder::__construct()" method will require "string $directory" argument in 3.0. Not defining it or passing null is deprecated.'); - $finder = new ComponentTemplateFinder($environment); - - $this->assertEquals('components/aa.html.twig', $finder->findAnonymousComponentTemplate('aa')); - $this->assertEquals('components/aa/bb.html.twig', $finder->findAnonymousComponentTemplate('aa:bb')); - $this->assertEquals('components/b.html.twig', $finder->findAnonymousComponentTemplate('b')); - $this->assertEquals('components/b.html.twig', $finder->findAnonymousComponentTemplate('components:b')); - $this->assertEquals('c.html.twig', $finder->findAnonymousComponentTemplate('c')); - $this->assertEquals('components/d', $finder->findAnonymousComponentTemplate('d')); - - $this->assertNull($finder->findAnonymousComponentTemplate('nope')); - $this->assertNull($finder->findAnonymousComponentTemplate('nope:bar')); - } - - /** - * @group legacy - */ - public function testTriggerDeprecationWhenEnvironmentAsFirstArgument() - { - $environment = $this->createEnvironment([]); - - $this->expectDeprecation('Since symfony/ux-twig-component 2.13: The "Symfony\UX\TwigComponent\ComponentTemplateFinder::__construct()" method will require "Twig\Loader\LoaderInterface $loader" as first argument in 3.0. Passing an "Environment" instance is deprecated.'); - $finder = new ComponentTemplateFinder($environment, 'foo'); - } - - /** - * @group legacy - */ - public function testTriggerDeprecationWhenDirectoryArgumentIsNullOrNotProvided() - { - $environment = $this->createEnvironment([]); - - $this->expectDeprecation('Since symfony/ux-twig-component 2.13: The "Symfony\UX\TwigComponent\ComponentTemplateFinder::__construct()" method will require "string $directory" argument in 3.0. Not defining it or passing null is deprecated.'); - $finder = new ComponentTemplateFinder($environment); - - $this->expectDeprecation('Since symfony/ux-twig-component 2.13: The "Symfony\UX\TwigComponent\ComponentTemplateFinder::__construct()" method will require "string $directory" argument in 3.0. Not defining it or passing null is deprecated.'); - $finder = new ComponentTemplateFinder($environment, null); - } - public function testFindTemplateWithinDirectory() { $templates = [ diff --git a/src/TwigComponent/tests/Unit/DependencyInjection/TwigComponentExtensionTest.php b/src/TwigComponent/tests/Unit/DependencyInjection/TwigComponentExtensionTest.php index 6695e064caf..ebd92786b3d 100644 --- a/src/TwigComponent/tests/Unit/DependencyInjection/TwigComponentExtensionTest.php +++ b/src/TwigComponent/tests/Unit/DependencyInjection/TwigComponentExtensionTest.php @@ -9,10 +9,9 @@ * file that was distributed with this source code. */ -namespace Symfony\UX\TwigComponent\Test\DependencyInjection; +namespace Symfony\UX\TwigComponent\Tests\Unit\DependencyInjection; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\UX\TwigComponent\DependencyInjection\TwigComponentExtension; @@ -23,8 +22,6 @@ */ class TwigComponentExtensionTest extends TestCase { - use ExpectDeprecationTrait; - public function testDataCollectorWithDebugMode() { $container = $this->createContainer(); @@ -69,26 +66,6 @@ public function testDataCollectorWithoutDebugMode() $this->assertFalse($container->hasDefinition('ux.twig_component.data_collector')); } - /** - * @group legacy - */ - public function testSettingControllerJsonKeyTriggerDeprecation() - { - $container = $this->createContainer(); - $container->setParameter('kernel.debug', true); - $container->registerExtension(new TwigComponentExtension()); - $container->loadFromExtension('twig_component', [ - 'defaults' => [], - 'anonymous_template_directory' => 'components/', - 'profiler' => false, - 'controllers_json' => null, - ]); - - $this->expectDeprecation('Since symfony/ux-twig-component 2.18: The "twig_component.controllers_json" config option is deprecated, and will be removed in 3.0.'); - - $this->compileContainer($container); - } - private function createContainer() { $container = new ContainerBuilder(new ParameterBag([ diff --git a/src/TwigComponent/tests/Unit/Event/MountEventsTest.php b/src/TwigComponent/tests/Unit/Event/MountEventsTest.php deleted file mode 100644 index cddf6d28e0a..00000000000 --- a/src/TwigComponent/tests/Unit/Event/MountEventsTest.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\UX\TwigComponent\Tests\Unit\Event; - -use PHPUnit\Framework\TestCase; -use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; -use Symfony\UX\TwigComponent\Event\PostMountEvent; -use Symfony\UX\TwigComponent\Event\PreMountEvent; - -/** - * Remove in TwigComponent 3.0. - * - * @group legacy - */ -class MountEventsTest extends TestCase -{ - use ExpectDeprecationTrait; - - public function testPreMountEventCreation() - { - $this->expectDeprecation('Since symfony/ux-twig-component 2.13: In TwigComponent 3.0, "Symfony\UX\TwigComponent\Event\PreMountEvent::__construct()" method will require a "Symfony\UX\TwigComponent\ComponentMetadata $metadata" argument. Not passing it is deprecated.'); - new PreMountEvent(new \stdClass(), []); - - $this->expectDeprecation('Since symfony/ux-twig-component 2.13: In TwigComponent 3.0, "Symfony\UX\TwigComponent\Event\PreMountEvent::__construct()" method will require a "Symfony\UX\TwigComponent\ComponentMetadata $metadata" argument. Not passing it is deprecated.'); - new PreMountEvent(new \stdClass(), [], null); - } - - public function testPostMountEventCreation() - { - $this->expectDeprecation('Since symfony/ux-twig-component 2.13: In TwigComponent 3.0, the third argument of "Symfony\UX\TwigComponent\Event\PostMountEvent::__construct()" will be a "Symfony\UX\TwigComponent\ComponentMetadata" object and the "$extraMetadata" array should be passed as the fourth argument.'); - new PostMountEvent(new \stdClass(), []); - - $this->expectDeprecation('Since symfony/ux-twig-component 2.13: In TwigComponent 3.0, the third argument of "Symfony\UX\TwigComponent\Event\PostMountEvent::__construct()" will be a "Symfony\UX\TwigComponent\ComponentMetadata" object and the "$extraMetadata" array should be passed as the fourth argument.'); - new PostMountEvent(new \stdClass(), [], []); - } -}