Skip to content

Commit

Permalink
[TwigComponent] Improve exception message when component not found
Browse files Browse the repository at this point in the history
  • Loading branch information
norkunas committed Aug 2, 2023
1 parent 670a37a commit da3b611
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 6 deletions.
27 changes: 26 additions & 1 deletion src/TwigComponent/src/ComponentFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,31 @@ private function postMount(object $component, array $data): array
*/
private function throwUnknownComponentException(string $name): void
{
throw new \InvalidArgumentException(sprintf('Unknown component "%s". The registered components are: %s', $name, implode(', ', array_keys($this->config))));
$message = sprintf('Unknown component "%s".', $name);

$alternatives = [];

foreach (array_keys($this->config) as $type) {
$lowerName = strtolower($name);
$lowerType = strtolower($type);

$lev = levenshtein($lowerName, $lowerType);

if ($lev <= \strlen($lowerName) / 3 || str_contains($lowerType, $lowerName)) {
$alternatives[] = $type;
}
}

if ($alternatives) {
if (1 === \count($alternatives)) {
$message .= ' Did you mean this: "';
} else {
$message .= ' Did you mean one of these: "';
}

$message .= implode('", "', $alternatives).'"?';
}

throw new \InvalidArgumentException($message);
}
}
16 changes: 11 additions & 5 deletions src/TwigComponent/tests/Integration/ComponentFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,17 +152,23 @@ public function testCanGetMetadataForSameComponentWithDifferentName(): void
public function testCannotGetConfigByNameForNonRegisteredComponent(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessageMatches('/^Unknown component "invalid"\. The registered components are:.* component_a/');
$this->expectExceptionMessage('Unknown component "tabl". Did you mean this: "table"?');

$this->factory()->metadataFor('invalid');
$this->factory()->metadataFor('tabl');
}

public function testCannotGetInvalidComponent(): void
/**
* @testWith ["tabl", "Unknown component \"tabl\". 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\"?"]
*/
public function testCannotGetInvalidComponent(string $name, string $expectedExceptionMessage): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessageMatches('/^Unknown component "invalid"\. The registered components are:.* component_a/');
$this->expectExceptionMessage($expectedExceptionMessage);

$this->factory()->get('invalid');
$this->factory()->get($name);
}

public function testInputPropsStoredOnMountedComponent(): void
Expand Down

0 comments on commit da3b611

Please sign in to comment.