root = "{$base}/platform";
$this->public = "{$base}/public";
File::makeDirectory("{$this->root}/public", 0755, true);
File::makeDirectory($this->public, 0755, true);
$this->originalPublic = public_path();
$this->app->usePublicPath($this->public);
config(['app.platform_path' => $this->root]);
// The layouts' @vite would look for the build manifest in the temporary public/
$this->withoutVite();
}
protected function tearDown(): void
{
View::flushSections();
$this->app->usePublicPath($this->originalPublic);
File::deleteDirectory(dirname($this->root));
parent::tearDown();
}
private function renderHead(): string
{
return view('layouts.guest', ['slot' => new HtmlString('')])->render();
}
public function test_open_graph_tags_use_property_and_the_title_is_escaped_once(): void
{
View::startSection('title', 'Terms & conditions');
$html = $this->renderHead();
$this->assertStringContainsString('
Terms & conditions - ' . e(config('app.name')) . '', $html);
$this->assertStringContainsString('', $html);
$this->assertStringContainsString('assertStringContainsString('', $html);
$this->assertStringNotContainsString('&', $html);
$this->assertStringNotContainsString('name="og:', $html);
$this->assertStringNotContainsString('og:image', $html, 'no preview image without a file');
}
public function test_the_preview_image_comes_from_the_platform_folder_then_the_theme(): void
{
File::put("{$this->public}/theme-preview.png", 'png');
config(['themes.themes.' . theme_id() . '.logos.og_image' => 'theme-preview.png']);
$this->assertStringContainsString('', $this->renderHead());
File::put("{$this->root}/public/og-image.png", 'png');
$this->artisan('platform:link')->assertExitCode(0);
$html = $this->renderHead();
$this->assertStringContainsString('', $html);
$this->assertStringContainsString('', $html);
}
public function test_optional_icons_are_linked_only_when_present(): void
{
$html = $this->renderHead();
$this->assertStringNotContainsString('favicon.svg', $html);
$this->assertStringNotContainsString('rel="manifest"', $html);
$this->assertStringContainsString('favicon-32x32.png', $html, 'the standard icons are always linked');
File::put("{$this->root}/public/favicon.svg", '');
File::put("{$this->root}/public/site.webmanifest", '{}');
File::put("{$this->public}/favicon-96x96.png", 'png');
$this->artisan('platform:link')->assertExitCode(0);
$html = $this->renderHead();
$this->assertStringContainsString('', $html);
$this->assertStringContainsString('', $html);
$this->assertStringContainsString('', $html);
}
/**
* Uuro's branch added onQueue('high') to this notification (2025-12-15), which is not a queued notification:
* every admin or bank password reset then failed with "Call to undefined method ...::onQueue()".
*/
public function test_the_admin_and_bank_password_reset_mail_can_be_built(): void
{
$notification = new NonUserPasswordResetNotification('https://example.test/reset/abc', new Admin(['name' => 'admin-test']));
$this->assertStringContainsString('https://example.test/reset/abc', (string) $notification->toMail(new Admin(['name' => 'admin-test']))->render());
}
}