Files

169 lines
7.8 KiB
PHP

<?php
namespace Tests\Feature;
use App\Providers\PlatformServiceProvider;
use Illuminate\Mail\Markdown;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\View;
use Tests\TestCase;
/**
* The platform folder (platform_path(), outside git) holds everything that makes an installation one platform.
* Every part is optional; without it the installation runs from the code as before. Each test builds its own
* folder, and a public/ of its own, so the real platform/ and public/platform are never touched.
*/
class PlatformFolderTest extends TestCase
{
private string $root;
private string $public;
private string $originalPublic;
protected function setUp(): void
{
parent::setUp();
$base = sys_get_temp_dir() . '/platform-folder-test-' . uniqid();
$this->root = "{$base}/platform";
$this->public = "{$base}/public";
File::makeDirectory($this->public, 0755, true);
$this->originalPublic = public_path();
$this->app->usePublicPath($this->public);
config(['app.platform_path' => $this->root]);
}
protected function tearDown(): void
{
$this->app->usePublicPath($this->originalPublic);
File::deleteDirectory(dirname($this->root));
parent::tearDown();
}
private function putFile(string $path, string $content): void
{
File::ensureDirectoryExists(dirname("{$this->root}/{$path}"));
File::put("{$this->root}/{$path}", $content);
}
/** Load the folder as the app does at start, and drop what was already cached. */
private function loadPlatform(): void
{
$provider = new PlatformServiceProvider($this->app);
$provider->register();
$provider->boot();
$this->app['translator']->setLoaded([]);
View::getFinder()->flush();
$this->app->forgetInstance(Markdown::class);
}
public function test_without_a_folder_nothing_changes(): void
{
$name = config('app.timebank_config');
$before = [config($name), config('themes'), config('mail.markdown.paths'), __('Search'), View::getFinder()->getPaths()];
$this->loadPlatform();
$this->assertSame($before, [config($name), config('themes'), config('mail.markdown.paths'), __('Search'), View::getFinder()->getPaths()]);
$this->assertSame(asset('favicon.ico'), theme_favicon('favicon.ico'));
$this->assertSame(asset('storage/' . theme_email_logo()), theme_email_logo_url());
}
public function test_its_config_is_the_platform_config(): void
{
$this->putFile('config.php', "<?php\n\nreturn ['platform_folder_marker' => 'from the folder', 'local_pages' => []];\n");
$this->loadPlatform();
$this->assertSame('from the folder', timebank_config('platform_folder_marker'));
$this->assertNull(timebank_config('footer'), 'the folder replaces config/<name>.php, it does not merge with it');
}
public function test_its_theme_becomes_the_active_theme(): void
{
$this->putFile('theme.php', "<?php\n\nreturn ['id' => 'acme', 'name' => 'Acme', 'colors' => ['brand' => '#123456']];\n");
$this->loadPlatform();
$this->assertSame('acme', theme_id());
$this->assertSame('Acme', theme_name());
$this->assertSame('#123456', theme_color('brand'));
$this->assertStringContainsString('--color-brand: 18 52 86;', theme_css_vars());
}
public function test_translations_are_overridden_key_by_key(): void
{
app()->setLocale('en');
$base = json_decode(File::get(lang_path('en.json')), true);
[$changed, $kept] = array_slice(array_keys($base), 10, 2);
$baseWirechat = trans('wirechat::chat.labels.you');
$this->putFile('lang/en.json', json_encode([$changed => 'Changed by the platform', 'Only on this platform' => 'Platform text']));
$this->putFile('lang/en/messages.php', "<?php\n\nreturn ['platform_folder_marker' => 'Group text'];\n");
$this->putFile('lang/vendor/wirechat/en/chat.php', "<?php\n\nreturn ['labels' => ['you' => 'Me']];\n");
$this->loadPlatform();
$this->assertSame('Changed by the platform', __($changed));
$this->assertSame($base[$kept], __($kept), 'keys the platform does not override keep their text');
$this->assertSame('Platform text', __('Only on this platform'));
$this->assertSame('Group text', __('messages.platform_folder_marker'));
$this->assertNotSame('messages.platform_folder_marker', __('messages.' . array_key_first(require lang_path('en/messages.php'))), 'the rest of the group stays');
$this->assertSame('Me', trans('wirechat::chat.labels.you'));
$this->assertNotSame($baseWirechat, 'Me');
$this->assertSame(trans('wirechat::chat.labels.attachment'), 'Attachment', 'the rest of the package group stays');
}
public function test_templates_are_overridden_as_whole_files(): void
{
$this->putFile('views/logos/timebank_cc.blade.php', 'PLATFORM LOGO');
$this->putFile('views/vendor/wirechat/components/divider.blade.php', 'PLATFORM DIVIDER');
$this->putFile('views/mail/html/panel.blade.php', '<div>PLATFORM PANEL {{ $slot }}</div>');
$this->putFile('views/platform-test-markdown.blade.php', "<x-mail::panel>\nHello\n</x-mail::panel>\n");
$this->loadPlatform();
$this->assertSame('PLATFORM LOGO', trim(view('logos.timebank_cc')->render()));
$this->assertSame("{$this->root}/views/vendor/wirechat/components/divider.blade.php", View::getFinder()->find('wirechat::components.divider'));
$this->assertStringContainsString('PLATFORM PANEL', (string) app(Markdown::class)->render('platform-test-markdown'));
$this->assertStringContainsString('resources/views/emails', View::getFinder()->find('emails.layouts.html'), 'templates the platform does not override come from the code');
}
public function test_public_files_are_served_from_the_folder_once_linked(): void
{
$this->putFile('public/favicon.ico', 'icon');
$this->putFile('public/mail-logo.png', 'logo');
$this->loadPlatform();
$this->assertSame(asset('favicon.ico'), theme_favicon('favicon.ico'), 'not served before the link exists');
$this->artisan('platform:link')->assertExitCode(0);
$this->assertSame("{$this->root}/public", readlink("{$this->public}/platform"));
$this->assertSame(asset('platform/favicon.ico'), theme_favicon('favicon.ico'));
$this->assertSame(asset('favicon-32x32.png'), theme_favicon('favicon-32x32.png'), 'a file the platform lacks comes from the code');
$this->assertSame(asset('platform/mail-logo.png'), theme_email_logo_url());
$this->assertSame("{$this->public}/platform/mail-logo.png", theme_email_logo_file());
$this->assertSame(asset('storage/' . theme_email_logo(true)), theme_email_logo_url(true), 'no inverted logo in the folder');
}
public function test_platform_link_is_idempotent_and_never_replaces_a_real_folder(): void
{
$this->artisan('platform:link')->expectsOutputToContain('nothing to link')->assertExitCode(0);
$this->assertFalse(file_exists("{$this->public}/platform"));
$this->putFile('public/favicon.ico', 'icon');
$this->artisan('platform:link')->assertExitCode(0);
$this->artisan('platform:link')->expectsOutputToContain('already links')->assertExitCode(0);
File::deleteDirectory("{$this->root}/public");
$this->artisan('platform:link')->expectsOutputToContain('Removed')->assertExitCode(0);
$this->assertFalse(is_link("{$this->public}/platform"));
File::makeDirectory("{$this->public}/platform");
$this->putFile('public/favicon.ico', 'icon');
$this->artisan('platform:link')->expectsOutputToContain('not a link')->assertExitCode(1);
$this->assertTrue(is_dir("{$this->public}/platform") && !is_link("{$this->public}/platform"));
}
}