Closed benr77 closed 2 years ago
Hey @benr77!
I'm sort of thinking this shouldn't be part of this package for the reason you describe above (It is considered best practice to hard-code the URL paths into your tests). I wouldn't want new users (building a standard app) using ->visitRoute()
instead of ->visit()
.
Of course, if this is a common need by the community, than I'd reconsider.
Here's how you can add to your custom browser:
class AppBrowser extends KernelBrowser
{
public function visitRoute(string $name, array $parameters = []): self
{
return $this->visit($this->client()->getContainer()->get('router')->generate($name, $parameters));
}
public function assertOnRoute(string $name, array $parameters = []): self
{
// this, I think, is the only way to access this data
return $this->use(function(RequestDataCollector $collector) use ($name, $parameters) {
Assert::that($name)->is($collector->getRoute());
Assert::that($parameters)->is($collector->getRouteParams());
});
}
}
Usage in a test:
$this->browser()
->withProfiling() // required as we use the request data collector for assertOnRoute
->visitRoute('route_name', ['param' => 'value'])
->assertOnRoute('route_name', ['param' => 'value'])
Refined assertOnRoute
a bit so it doesn't require the data collector:
final public function assertOnRoute(string $name, array $parameters = []): self
{
$expected = $this->client()->getContainer()->get('router')->generate($name, $parameters, UrlGeneratorInterface::ABSOLUTE_URL);
Assert::that($this->client()->getRequest()->getUri())->is($expected);
return $this;
}
Thanks Kevin - I totally agree with you about not including it in the package.
I have implemented the custom browser as you suggest and it's working nicely.
Thanks for being so helpful as always.
It is considered best practice to hard-code the URL paths into your tests, so that if a route is modified, the test fails. This ensures a consistent user experience, is good for SEO etc. However, this only really applies to public website type apps.
I build private, Saas type apps, where the URL changing is no big deal. I find it much easier to work with route names, which are defined as constants in the controller classes.
The browser has methods which require the path to test against - e.g.
visit(string $path)
assertOn(string $path)
I think it would be handy to have a matching set of methods, that support passing a route name and parameters instead of the path:
visitRoute(string $route, array $parameters = [])
assertOnRoute(string $route, array $parameters = [])
Is this something that could be incorporated into this package, or something better implemented by my app extending things?
If extending things is the way to go, where can I inject the router service?
Thanks