The package makes no HTTP calls, so there is nothing to fake. Point
canonical.domain at a known host and assert on the string or tag that comes out.
Setting the domain
Section titled “Setting the domain”use Fkrzski\LaravelCanonical\Facades\Canonical;
beforeEach(function (): void { config(['canonical.domain' => 'https://example.com']);});use Fkrzski\LaravelCanonical\Facades\Canonical;
protected function setUp(): void{ parent::setUp();
config(['canonical.domain' => 'https://example.com']);}Asserting on generated URLs
Section titled “Asserting on generated URLs”it('generates a canonical URL for a path', function (): void { expect(Canonical::generate('/products/item')) ->toBe('https://example.com/products/item');});
it('normalises the root path to the bare domain', function (): void { expect(Canonical::generate('/'))->toBe('https://example.com');});public function test_it_generates_a_canonical_url_for_a_path(): void{ $this->assertSame( 'https://example.com/products/item', Canonical::generate('/products/item'), );}
public function test_it_normalises_the_root_path_to_the_bare_domain(): void{ $this->assertSame('https://example.com', Canonical::generate('/'));}Asserting on the current request
Section titled “Asserting on the current request”Bind a request into the container to exercise the no-argument path. The staging host proves the URL is built from the canonical domain, not the request:
use Illuminate\Http\Request;
it('canonicalises the current request', function (): void { $this->app->instance('request', Request::create('https://staging.example.com/blog/post'));
expect(Canonical::generate())->toBe('https://example.com/blog/post');});use Illuminate\Http\Request;
public function test_it_canonicalises_the_current_request(): void{ $this->app->instance( 'request', Request::create('https://staging.example.com/blog/post'), );
$this->assertSame('https://example.com/blog/post', Canonical::generate());}Asserting on rendered Blade
Section titled “Asserting on rendered Blade”Blade::render() keeps the template’s surrounding whitespace, so trim before
comparing:
use Illuminate\Support\Facades\Blade;
it('renders the canonical component', function (): void { $html = trim(Blade::render('<x-canonical path="/products/item" />'));
expect($html)->toBe('<link rel="canonical" href="https://example.com/products/item" />');});
it('renders the directive', function (): void { $html = trim(Blade::render("@canonical('/products/item')"));
expect($html)->toBe('<link rel="canonical" href="https://example.com/products/item" />');});use Illuminate\Support\Facades\Blade;
public function test_it_renders_the_canonical_component(): void{ $html = trim(Blade::render('<x-canonical path="/products/item" />'));
$this->assertSame( '<link rel="canonical" href="https://example.com/products/item" />', $html, );}
public function test_it_renders_the_directive(): void{ $html = trim(Blade::render("@canonical('/products/item')"));
$this->assertSame( '<link rel="canonical" href="https://example.com/products/item" />', $html, );}Asserting on the configuration exception
Section titled “Asserting on the configuration exception”The domain is only validated on first use, so the assertion has to trigger one:
use Fkrzski\LaravelCanonical\Exceptions\CanonicalConfigurationException;
it('rejects a domain without a scheme', function (): void { config(['canonical.domain' => 'example.com']);
expect(fn (): string => Canonical::generate('/page')) ->toThrow(CanonicalConfigurationException::class);});use Fkrzski\LaravelCanonical\Exceptions\CanonicalConfigurationException;
public function test_it_rejects_a_domain_without_a_scheme(): void{ config(['canonical.domain' => 'example.com']);
$this->expectException(CanonicalConfigurationException::class);
Canonical::generate('/page');}Running the package’s own suite
Section titled “Running the package’s own suite”-
Install the development dependencies.
Terminal window composer install -
Run the full quality gate — Pint, Rector, PHPStan, type coverage, and a mutation-tested Pest run.
Terminal window composer test -
Or just the unit suite while iterating.
Terminal window composer test:unit