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); } public function test_init_creates_the_folder_and_never_overwrites(): void { $this->artisan('platform:init')->assertExitCode(0); $this->assertFileExists("{$this->root}/README.md"); $this->assertDirectoryExists("{$this->root}/lang"); $this->assertFileDoesNotExist("{$this->root}/config.php"); $this->artisan('platform:init', ['--from-current' => true])->assertExitCode(0); $name = config('app.timebank_config'); $this->assertFileEquals(config_path("{$name}.php"), "{$this->root}/config.php"); $theme = require "{$this->root}/theme.php"; $this->assertSame(theme_id(), $theme['id']); $this->assertSame(theme('colors'), $theme['colors']); File::put("{$this->root}/config.php", ' true];'); $this->artisan('platform:init', ['--from-current' => true])->expectsOutputToContain('kept')->assertExitCode(0); $this->assertSame(' true];', File::get("{$this->root}/config.php")); } public function test_override_copies_a_template_with_the_fingerprint_of_its_original(): void { $this->artisan('platform:override', ['view' => 'emails.layouts.html'])->assertExitCode(0); $copy = File::get("{$this->root}/views/emails/layouts/html.blade.php"); $original = resource_path('views/emails/layouts/html.blade.php'); $this->assertSame('{{-- platform:override of resources/views/emails/layouts/html.blade.php sha1:' . sha1_file($original) . " --}}\n" . File::get($original), $copy); $this->artisan('platform:override', ['view' => 'mail::html.panel'])->assertExitCode(0); $this->assertFileExists("{$this->root}/views/mail/html/panel.blade.php"); $this->artisan('platform:override', ['view' => 'wirechat::components.divider'])->assertExitCode(0); $this->assertFileExists("{$this->root}/views/vendor/wirechat/components/divider.blade.php"); $this->artisan('platform:override', ['view' => 'emails.layouts.html'])->expectsOutputToContain('exists already')->assertExitCode(1); $this->artisan('platform:override', ['view' => 'emails.no-such-template'])->expectsOutputToContain('No template')->assertExitCode(1); } public function test_check_without_a_folder(): void { $this->artisan('platform:check')->expectsOutputToContain('No platform folder')->assertExitCode(0); } public function test_check_reports_stale_overrides(): void { $base = json_decode(File::get(lang_path('en.json')), true); $existing = array_key_first($base); $this->putFile('lang/en.json', json_encode([ $existing => 'Changed', 'A sentence the code reworded long ago' => 'Old override', 'Own text in an own template' => 'Platform text', ])); $this->putFile('views/own-block.blade.php', "{{ __('Own text in an own template') }}"); $this->putFile('lang/en/messages.php', " 'x'];\n"); $this->artisan('platform:override', ['view' => 'emails.layouts.html'])->assertExitCode(0); $this->artisan('platform:override', ['view' => 'mail::html.panel'])->assertExitCode(0); // The panel's original "changed" after the copy: simulate with another fingerprint $panel = "{$this->root}/views/mail/html/panel.blade.php"; File::put($panel, preg_replace('/sha1:[0-9a-f]{40}/', 'sha1:' . str_repeat('0', 40), File::get($panel))); $this->artisan('platform:check') ->expectsOutputToContain('A sentence the code reworded long ago') ->expectsOutputToContain('no_such_message_key') ->expectsOutputToContain('views/mail/html/panel.blade.php: the original changed') ->expectsOutputToContain("views/own-block.blade.php: the platform's own template") ->doesntExpectOutputToContain('Own text in an own template') ->doesntExpectOutputToContain('views/emails/layouts/html.blade.php: the original changed') ->assertExitCode(0); } public function test_check_fails_on_invalid_json_and_warns_about_config_and_link(): void { $this->putFile('lang/nl.json', '{"broken": '); $this->putFile('config.php', 'putFile('public/favicon.ico', 'icon'); $this->artisan('platform:check') ->expectsOutputToContain('lang/nl.json is not valid JSON') ->expectsOutputToContain('Both platform/config.php and config/') ->expectsOutputToContain('run php artisan platform:link') ->assertExitCode(1); $this->artisan('platform:link')->assertExitCode(0); $this->putFile('lang/nl.json', '{}'); $this->artisan('platform:check')->expectsOutputToContain('linked at /platform')->assertExitCode(0); } }