From 9723fa0821986aec93cbbf77e880abaaf340330e Mon Sep 17 00:00:00 2001 From: Chris Di Carlo Date: Thu, 19 Sep 2024 00:09:24 -0400 Subject: [PATCH] Add tests, refactor to improve testability --- src/Actions/ListFiles.php | 23 -- src/Commands/LaravelConfigCheckerCommand.php | 217 +++++------------- src/Support/BladeFiles.php | 30 +++ src/Support/FileCheckInfo.php | 12 + src/Support/FileChecker.php | 83 +++++++ src/{Actions => Support}/LoadConfigKeys.php | 16 +- src/Support/PhpFiles.php | 34 +++ tests/BladeFilesTest.php | 21 ++ tests/FileCheckerTest.php | 216 +++++++++++++++++ tests/LaravelConfigCheckerCommandTest.php | 119 ++-------- tests/LoadConfigKeysTest.php | 52 +++++ tests/PhpFilesTest.php | 22 ++ tests/fixtures/base/app/TestClassOne.php | 15 ++ tests/fixtures/base/app/TestClassTwo.php | 15 ++ tests/fixtures/base/config/app.php | 8 + .../resources/views/test-view-one.blade.php | 10 + .../resources/views/test-view-two.blade.php | 10 + tests/fixtures/config/app.php | 10 - tests/fixtures/invalid/app/TestClassOne.php | 15 ++ tests/fixtures/invalid/app/TestClassTwo.php | 15 ++ tests/fixtures/invalid/app/invalid-get.php | 5 - tests/fixtures/invalid/app/invalid-has.php | 5 - tests/fixtures/invalid/app/invalid-helper.php | 3 - .../invalid/app/invalid-nested-get.php | 5 - .../invalid/app/invalid-nested-has.php | 5 - .../invalid/app/invalid-nested-helper.php | 5 - tests/fixtures/invalid/config/app.php | 6 +- .../resources/views/invalid-get.blade.php | 3 - .../resources/views/invalid-has.blade.php | 3 - .../resources/views/invalid-helper.blade.php | 3 - .../views/invalid-nested-get.blade.php | 3 - .../views/invalid-nested-has.blade.php | 3 - .../views/invalid-nested-helper.blade.php | 3 - .../resources/views/test-view-one.blade.php | 10 + .../resources/views/test-view-two.blade.php | 10 + tests/fixtures/valid/app/TestClassOne.php | 15 ++ tests/fixtures/valid/app/TestClassTwo.php | 15 ++ tests/fixtures/valid/app/valid-get.php | 5 - tests/fixtures/valid/app/valid-has.php | 5 - tests/fixtures/valid/app/valid-helper.php | 3 - tests/fixtures/valid/config/app.php | 6 +- .../resources/views/test-view-one.blade.php | 7 + .../resources/views/test-view-two.blade.php | 7 + .../valid/resources/views/valid-get.blade.php | 3 - .../valid/resources/views/valid-has.blade.php | 3 - .../resources/views/valid-helper.blade.php | 3 - 46 files changed, 717 insertions(+), 370 deletions(-) delete mode 100644 src/Actions/ListFiles.php create mode 100644 src/Support/BladeFiles.php create mode 100644 src/Support/FileCheckInfo.php create mode 100644 src/Support/FileChecker.php rename src/{Actions => Support}/LoadConfigKeys.php (75%) create mode 100644 src/Support/PhpFiles.php create mode 100644 tests/BladeFilesTest.php create mode 100644 tests/FileCheckerTest.php create mode 100644 tests/LoadConfigKeysTest.php create mode 100644 tests/PhpFilesTest.php create mode 100644 tests/fixtures/base/app/TestClassOne.php create mode 100644 tests/fixtures/base/app/TestClassTwo.php create mode 100644 tests/fixtures/base/config/app.php create mode 100644 tests/fixtures/base/resources/views/test-view-one.blade.php create mode 100644 tests/fixtures/base/resources/views/test-view-two.blade.php delete mode 100644 tests/fixtures/config/app.php create mode 100644 tests/fixtures/invalid/app/TestClassOne.php create mode 100644 tests/fixtures/invalid/app/TestClassTwo.php delete mode 100644 tests/fixtures/invalid/app/invalid-get.php delete mode 100644 tests/fixtures/invalid/app/invalid-has.php delete mode 100644 tests/fixtures/invalid/app/invalid-helper.php delete mode 100644 tests/fixtures/invalid/app/invalid-nested-get.php delete mode 100644 tests/fixtures/invalid/app/invalid-nested-has.php delete mode 100644 tests/fixtures/invalid/app/invalid-nested-helper.php delete mode 100644 tests/fixtures/invalid/resources/views/invalid-get.blade.php delete mode 100644 tests/fixtures/invalid/resources/views/invalid-has.blade.php delete mode 100644 tests/fixtures/invalid/resources/views/invalid-helper.blade.php delete mode 100644 tests/fixtures/invalid/resources/views/invalid-nested-get.blade.php delete mode 100644 tests/fixtures/invalid/resources/views/invalid-nested-has.blade.php delete mode 100644 tests/fixtures/invalid/resources/views/invalid-nested-helper.blade.php create mode 100644 tests/fixtures/invalid/resources/views/test-view-one.blade.php create mode 100644 tests/fixtures/invalid/resources/views/test-view-two.blade.php create mode 100644 tests/fixtures/valid/app/TestClassOne.php create mode 100644 tests/fixtures/valid/app/TestClassTwo.php delete mode 100644 tests/fixtures/valid/app/valid-get.php delete mode 100644 tests/fixtures/valid/app/valid-has.php delete mode 100644 tests/fixtures/valid/app/valid-helper.php create mode 100644 tests/fixtures/valid/resources/views/test-view-one.blade.php create mode 100644 tests/fixtures/valid/resources/views/test-view-two.blade.php delete mode 100644 tests/fixtures/valid/resources/views/valid-get.blade.php delete mode 100644 tests/fixtures/valid/resources/views/valid-has.blade.php delete mode 100644 tests/fixtures/valid/resources/views/valid-helper.blade.php diff --git a/src/Actions/ListFiles.php b/src/Actions/ListFiles.php deleted file mode 100644 index e3d5864..0000000 --- a/src/Actions/ListFiles.php +++ /dev/null @@ -1,23 +0,0 @@ -files()->in($basePath) - ->name('*.php') - ->name('*.blade.php') - ->path('app') - ->path('database') - ->path('routes') - ->path('bootstrap') - ->path('resources/views') - ->notPath('vendor'); - } -} diff --git a/src/Commands/LaravelConfigCheckerCommand.php b/src/Commands/LaravelConfigCheckerCommand.php index ef19182..65de539 100644 --- a/src/Commands/LaravelConfigCheckerCommand.php +++ b/src/Commands/LaravelConfigCheckerCommand.php @@ -2,8 +2,12 @@ namespace ChrisDiCarlo\LaravelConfigChecker\Commands; +use ChrisDiCarlo\LaravelConfigChecker\Support\BladeFiles; +use ChrisDiCarlo\LaravelConfigChecker\Support\FileChecker; +use ChrisDiCarlo\LaravelConfigChecker\Support\LoadConfigKeys; +use ChrisDiCarlo\LaravelConfigChecker\Support\PhpFiles; use Illuminate\Console\Command; -use Symfony\Component\Finder\Finder; +use Illuminate\Support\Collection; use function Laravel\Prompts\error; use function Laravel\Prompts\info; @@ -16,192 +20,95 @@ class LaravelConfigCheckerCommand extends Command public $description = 'Check all references to config values in PHP and Blade files'; - private $configKeys = []; + private Collection $configKeys; - private array $issues = []; + private array $bladeIssues = []; - public function handle(): int - { - $this->loadConfigKeys(); - - if ($this->output->isVerbose()) { - $this->outputConfigKeys(); - } - - $this->checkPhpFiles(); - $this->checkBladeFiles(); - - $this->displayResults(); - - return self::SUCCESS; - } - - private function outputConfigKeys(): void - { - table( - ['File', '# of Keys'], - collect($this->configKeys)->groupBy(fn ($key) => explode('.', $key)[0]) - ->map(fn ($subkeys, $key) => ['key' => $key, 'count' => $subkeys->count()]) - ->sort() - ->values() - ->toArray() - ); - } + private array $phpIssues = []; - private function flattenConfig($config, $prefix = '') + public function getIssues(): Collection { - foreach ($config as $key => $value) { - $fullKey = $prefix ? "{$prefix}.{$key}" : $key; - - $this->configKeys[] = $fullKey; - - if (is_array($value)) { - $this->flattenConfig($value, $fullKey); - } - } - } - - private function loadConfigKeys() - { - $configPath = $this->laravel->configPath(); - $finder = new Finder; - $finder->files()->in($configPath)->name('*.php'); - - foreach ($finder as $file) { - $this->configKeys[] = basename($file->getFilename(), '.php'); - - $config = include $file->getRealPath(); - - $this->flattenConfig($config, basename($file->getFilename(), '.php')); - } - } - - private function displayResults(): void - { - $issues = collect($this->issues)->filter(fn ($issue) => ! empty($issue)); - - if ($issues->isEmpty()) { - info('No issues found. All config references are valid.'); + $combinedIssues = collect([...$this->phpIssues, ...$this->bladeIssues]) + ->filter(fn ($issue) => ! empty($issue)); - return; - } - - error('Issues found! Invalid config references detected:'); - - table( - ['File', 'Line Number', 'Key', 'Reference Type'], - $issues->sort()->map(function ($issues, $file) { - return collect($issues)->map(function ($issue) use ($file) { - return [ - 'file' => $file, - 'line' => $issue['line'], - 'key' => $issue['key'], - 'type' => $issue['type'], - ]; - }); - })->flatten(1)->toArray() - ); + return $combinedIssues; } - private function checkPhpFiles(): void - { - $finder = new Finder; - $finder->files()->in($this->laravel->basePath()) - ->name('*.php') - ->path('app') - ->path('database') - ->path('routes') - ->path('bootstrap') - ->notPath('vendor'); + public function handle( + LoadConfigKeys $loadConfigKeys, + PhpFiles $phpFiles, + BladeFiles $bladeFiles + ): int { + $this->configKeys = $loadConfigKeys(); $progress = progress( label: 'Checking PHP files...', - steps: $finder, + steps: $phpFiles(), callback: function ($file, $progress) { $progress->hint = "Checking {$file->getRelativePathname()}"; - $this->issues[$file->getRelativePathname()] = array_merge( - $this->issues[$file->getRelativePathname()] ?? [], - $this->checkForFacadeUsage($file), - $this->checkForHelperUsage($file) - ); + $content = file_get_contents($file->getRealPath()); + + $fileChecker = new FileChecker($this->configKeys, $content); + + foreach ($fileChecker->check() as $issue) { + $this->phpIssues[$file->getRelativePathname()][] = $issue; + } } ); - } - - private function checkBladeFiles(): void - { - $finder = new Finder; - $finder->files()->in($this->laravel->basePath()) - ->name('*.blade.php') - ->notPath('vendor'); $progress = progress( label: 'Checking Blade files...', - steps: $finder, + steps: $bladeFiles(), callback: function ($file, $progress) { $progress->hint = "Checking {$file->getRelativePathname()}"; - $this->issues[$file->getRelativePathname()] = array_merge( - $this->issues[$file->getRelativePathname()] ?? [], - $this->checkForFacadeUsage($file), - $this->checkForHelperUsage($file) - ); + $content = file_get_contents($file->getRealPath()); + $fileChecker = new FileChecker($this->configKeys, $content); + + foreach ($fileChecker->check() as $issue) { + $this->bladeIssues[$file->getRelativePathname()][] = $issue; + } } ); - } - - private function checkForFacadeUsage($file): array - { - $content = file_get_contents($file->getRealPath()); - $matches = []; - - preg_match_all('/Config::(get|has)\([\'"]([^\'"]+)[\'"]\)/', $content, $matches, PREG_OFFSET_CAPTURE); - $issues = []; - - foreach ($matches[2] as $index => $match) { - $key = $match[0]; - $offset = (int) $match[1]; - $lineNumber = substr_count(substr($content, 0, $offset), "\n") + 1; + if ($this->getIssues()->isEmpty()) { + info('No issues found. All config references are valid.'); - if (! in_array($key, $this->configKeys)) { - $issues[] = [ - 'file' => $file->getRelativePathname(), - 'key' => $key, - 'type' => sprintf('Config::%s()', $matches[1][$index][0]), - 'line' => $lineNumber, - ]; - } + return self::SUCCESS; } - return $issues; + $this->displayResults(); + + return self::SUCCESS; } - private function checkForHelperUsage($file): array + private function displayResults(): void { - $content = file_get_contents($file->getRealPath()); - $matches = []; - - preg_match_all('/config\([\'"]([^\'"]+)[\'"]\)/', $content, $matches, PREG_OFFSET_CAPTURE); + error('Invalid config references found:'); - $issues = []; + $rowData = $this->formatIssuesOutput(); - foreach ($matches[1] as $match) { - $key = $match[0]; - $offset = (int) $match[1]; - $lineNumber = substr_count(substr($content, 0, $offset), "\n") + 1; - - if (! in_array($key, $this->configKeys)) { - $issues[] = [ - 'file' => $file->getRelativePathname(), - 'key' => $key, - 'type' => 'config()', - 'line' => $lineNumber, - ]; - } - } + table( + ['File', 'Line Number', 'Key Referenced', 'Reference Type'], + $rowData, + ); + } - return $issues; + private function formatIssuesOutput(): array + { + return $this->getIssues()->sort() + ->flatMap(function ($issues, $file) { + return collect($issues) + ->sortBy('line') + ->map(fn ($issue) => [ + $file, + $issue->line, + $issue->key, + $issue->type, + ]); + }) + // ->flatten(1) + ->toArray(); } } diff --git a/src/Support/BladeFiles.php b/src/Support/BladeFiles.php new file mode 100644 index 0000000..c3acb31 --- /dev/null +++ b/src/Support/BladeFiles.php @@ -0,0 +1,30 @@ +basePath = $basePath; + } + + public function __invoke(): Finder + { + $finder = new Finder; + $finder->files()->in($this->basePath) + ->name('*.blade.php') + ->path('resources/views') + ->notPath('vendor'); + + return $finder; + } +} diff --git a/src/Support/FileCheckInfo.php b/src/Support/FileCheckInfo.php new file mode 100644 index 0000000..e7b467f --- /dev/null +++ b/src/Support/FileCheckInfo.php @@ -0,0 +1,12 @@ +checkForFacadeUsage($this->content), + $this->checkForHelperUsage($this->content) + ); + + foreach ($errors as $error) { + $issues[] = new FileCheckInfo( + line: $error['line'], + key: $error['key'], + type: $error['type'], + ); + } + + return collect($issues); + } + + private function checkForFacadeUsage($content): array + { + $matches = []; + + preg_match_all('/Config::(get|has)\([\'"]([^\'"]+)[\'"]\)/', $content, $matches, PREG_OFFSET_CAPTURE); + + $issues = []; + + foreach ($matches[2] as $index => $match) { + $key = $match[0]; + $offset = (int) $match[1]; + $lineNumber = substr_count(substr($content, 0, $offset), "\n") + 1; + + if ($this->configKeys->doesntContain($key)) { + $issues[] = [ + 'key' => $key, + 'type' => sprintf('Config::%s()', $matches[1][$index][0]), + 'line' => $lineNumber, + ]; + } + } + + return $issues; + } + + private function checkForHelperUsage($content): array + { + $matches = []; + + preg_match_all('/config\([\'"]([^\'"]+)[\'"]\)/', $content, $matches, PREG_OFFSET_CAPTURE); + + $issues = []; + + foreach ($matches[1] as $match) { + $key = $match[0]; + $offset = (int) $match[1]; + $lineNumber = substr_count(substr($content, 0, $offset), "\n") + 1; + + if ($this->configKeys->doesntContain($key)) { + $issues[] = [ + 'key' => $key, + 'type' => 'config()', + 'line' => $lineNumber, + ]; + } + } + + return $issues; + } +} diff --git a/src/Actions/LoadConfigKeys.php b/src/Support/LoadConfigKeys.php similarity index 75% rename from src/Actions/LoadConfigKeys.php rename to src/Support/LoadConfigKeys.php index c4af905..0db5335 100644 --- a/src/Actions/LoadConfigKeys.php +++ b/src/Support/LoadConfigKeys.php @@ -1,22 +1,30 @@ configPath = $configPath; + } - $this->loadConfigKeys($configPath); + public function __invoke(): array|Collection + { + $this->loadConfigKeys(); + // return $this->configKeys; return collect($this->configKeys); } diff --git a/src/Support/PhpFiles.php b/src/Support/PhpFiles.php new file mode 100644 index 0000000..f9ad399 --- /dev/null +++ b/src/Support/PhpFiles.php @@ -0,0 +1,34 @@ +basePath = $basePath; + } + + public function __invoke(): Finder + { + $finder = new Finder; + $finder->files()->in($this->basePath) + ->name('*.php') + ->path('app') + ->path('database') + ->path('routes') + ->path('bootstrap') + ->notPath('vendor') + ->notPath('config'); + + return $finder; + } +} diff --git a/tests/BladeFilesTest.php b/tests/BladeFilesTest.php new file mode 100644 index 0000000..54c3425 --- /dev/null +++ b/tests/BladeFilesTest.php @@ -0,0 +1,21 @@ +getRealPath(); + } + + expect($finder->count())->toBe(2); + expect($filePaths)->toContain(__DIR__.'/fixtures/base/resources/views/test-view-one.blade.php'); + expect($filePaths)->toContain(__DIR__.'/fixtures/base/resources/views/test-view-two.blade.php'); + expect($filePaths)->not()->toContain(__DIR__.'/fixtures/base/app/TestClassOne.php'); + expect($filePaths)->not()->toContain(__DIR__.'/fixtures/base/config/app.php'); + expect($filePaths)->not()->toContain(__DIR__.'/fixtures/base/vendor/VendorClassOne.php'); +}); diff --git a/tests/FileCheckerTest.php b/tests/FileCheckerTest.php new file mode 100644 index 0000000..3c6779a --- /dev/null +++ b/tests/FileCheckerTest.php @@ -0,0 +1,216 @@ +configKeys = collect([ + 'file', + 'file.valid_key', + 'file.nested', + 'file.nested.key', + ]); +}); +it('returns a collection of FileCheckInfo objects', function () { + $content = <<<'PHP' + configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues)->toBeInstanceOf(Collection::class); + expect($issues->first())->toBeInstanceOf(FileCheckInfo::class); +}); + +it('handles content with no facade or helper usage gracefully', function () { + $content = <<<'PHP' + configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues)->toBeEmpty(); + + $content = <<<'BLADE' + {{ "Hello, World!" }} + BLADE; + + $fileChecker = new FileChecker($this->configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues)->toBeEmpty(); +}); + +it('handles content without any issues gracefully', function () { + $content = <<<'PHP' + configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues)->toBeEmpty(); + + $content = <<<'BLADE' + {{ Config::get("file.valid_key") }} + {{ Config::has("file.valid_key") }} + {{ config("file.valid_key") }} + BLADE; + + $fileChecker = new FileChecker($this->configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues)->toBeEmpty(); +}); + +it('detects facade and helper usage issues correctly', function () { + $content = <<<'PHP' + configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues)->toBeInstanceOf(Collection::class); + expect($issues->count())->toBe(3); + expect($issues->contains(function ($issue) { + return $issue->key === 'file.invalid_key' && + $issue->type === 'Config::get()'; + }))->toBeTrue(); + expect($issues->contains(function ($issue) { + return $issue->key === 'file.invalid_key' && + $issue->type === 'Config::has()'; + }))->toBeTrue(); + expect($issues->contains(function ($issue) { + return $issue->key === 'file.invalid_key' && + $issue->type === 'config()'; + }))->toBeTrue(); + + $content = <<<'BLADE' + {{ Config::get("file.invalid_key") }} + {{ Config::has("file.invalid_key") }} + {{ config("file.invalid_key") }} + {{ Config::get("file.valid_key") }} + {{ Config::has("file.valid_key") }} + {{ config("file.valid_key") }} + BLADE; + + $fileChecker = new FileChecker($this->configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues)->toBeInstanceOf(Collection::class); + expect($issues->count())->toBe(3); + expect($issues->contains(function ($issue) { + return $issue->key === 'file.invalid_key' && + $issue->type === 'Config::get()'; + }))->toBeTrue(); + expect($issues->contains(function ($issue) { + return $issue->key === 'file.invalid_key' && + $issue->type === 'Config::has()'; + }))->toBeTrue(); + expect($issues->contains(function ($issue) { + return $issue->key === 'file.invalid_key' && + $issue->type === 'config()'; + }))->toBeTrue(); +}); + +it('handles empty content gracefully', function () { + $content = ''; + + $fileChecker = new FileChecker($this->configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues)->toBeEmpty(); +}); + +it('detects issues when there are both valid and invalid references', function () { + $content = <<<'PHP' + configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues->contains('key', 'file.valid_key'))->toBeFalse(); + expect($issues->contains('key', 'file.invalid_key'))->toBeTrue(); + + $content = <<<'BLADE' + {{ Config::get("file.invalid_key") }} + {{ Config::has("file.invalid_key") }} + {{ config("file.invalid_key") }} + {{ Config::get("file.valid_key") }} + {{ Config::has("file.valid_key") }} + {{ config("file.valid_key") }} + BLADE; + + $fileChecker = new FileChecker($this->configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues->contains('key', 'file.valid_key'))->toBeFalse(); + expect($issues->contains('key', 'file.invalid_key'))->toBeTrue(); +}); + +it('detects issues for invalid nested keys', function () { + $content = <<<'PHP' + configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues->contains('key', 'file.valid_key'))->toBeFalse(); + expect($issues->contains('key', 'file.nested.invalid_key'))->toBeTrue(); + + $content = <<<'BLADE' + {{ Config::get("file.nested.invalid_key") }} + {{ Config::has("file.nested.invalid_key") }} + {{ config("file.nested.invalid_key") }} + {{ Config::get("file.valid_key") }} + {{ Config::has("file.valid_key") }} + {{ config("file.valid_key") }} + BLADE; + + $fileChecker = new FileChecker($this->configKeys, $content); + + $issues = $fileChecker->check(); + + expect($issues->contains('key', 'file.valid_key'))->toBeFalse(); + expect($issues->contains('key', 'file.nested.invalid_key'))->toBeTrue(); +}); diff --git a/tests/LaravelConfigCheckerCommandTest.php b/tests/LaravelConfigCheckerCommandTest.php index 744ad87..67511d7 100644 --- a/tests/LaravelConfigCheckerCommandTest.php +++ b/tests/LaravelConfigCheckerCommandTest.php @@ -1,110 +1,25 @@ app->setBasePath(__DIR__ . '/fixtures'); - $this->command = new LaravelConfigCheckerCommand(); - $this->command->setLaravel($this->app); -}); - -it('handles the command correctly', function () { - Artisan::call('config:check'); - $output = Artisan::output(); - - expect($output)->toContain('No issues found. All config references are valid.'); -}); - -it('outputs config keys correctly', function () { - $this->command->configKeys = ['app.name', 'database.connections.mysql']; - - ob_start(); - $this->command->outputConfigKeys(); - $output = ob_get_clean(); - - expect($output)->toContain('app')->toContain('database'); -}); - -it('flattens config correctly', function () { - $config = [ - 'app' => [ - 'name' => 'Laravel', - 'env' => 'local', - ], - 'database' => [ - 'connections' => [ - 'mysql' => [ - 'host' => '127.0.0.1', - ], - ], - ], - ]; - - $this->command->flattenConfig($config); - - expect($this->command->configKeys)->toBe([ - 'app.name', - 'app.env', - 'database.connections.mysql.host', - ]); -}); - -it('loads config keys correctly', function () { - $this->command->loadConfigKeys(); - - expect($this->command->configKeys)->toContain('app.name')->toContain('database.connections.mysql.host'); -}); - -it('displays results correctly', function () { - $this->command->issues = [ - 'file1.php' => [ - ['line' => 10, 'key' => 'app.name', 'type' => 'config()'], - ], - ]; - - ob_start(); - $this->command->displayResults(); - $output = ob_get_clean(); - - expect($output)->toContain('file1.php')->toContain('app.name'); -}); - -it('checks PHP files correctly', function () { - $this->command->checkPhpFiles(); - - expect($this->command->issues)->toBeEmpty(); -}); - -it('checks Blade files correctly', function () { - $this->command->checkBladeFiles(); - - expect($this->command->issues)->toBeEmpty(); -}); +use function Pest\Laravel\artisan; -it('checks for facade usage correctly', function () { - $file = new SplFileInfo(__DIR__ . '/fixtures/php/invalid.php', '', 'invalid.php'); - $issues = $this->command->checkForFacadeUsage($file); +it('displays a message when there are no issues', function () { + // set the base path for the application + $this->app->setBasePath(__DIR__.'/fixtures/valid'); - expect($issues)->toContain([ - 'file' => 'invalid.php', - 'key' => 'app.invalid_key', - 'type' => 'Config::get()', - 'line' => 3, - ]); + artisan('config:check') + ->expectsOutputToContain('No issues found. All config references are valid.') + ->assertExitCode(0); }); -it('checks for helper usage correctly', function () { - $file = new SplFileInfo(__DIR__ . '/fixtures/php/invalid.php', '', 'invalid.php'); - $issues = $this->command->checkForHelperUsage($file); +it('displays a message when there are issues', function () { + // set the base path for the application + $this->app->setBasePath(__DIR__.'/fixtures/invalid'); - expect($issues)->toContain([ - 'file' => 'invalid.php', - 'key' => 'app.invalid_key', - 'type' => 'config()', - 'line' => 5, - ]); + artisan('config:check') + ->expectsOutputToContain('Invalid config references found:') + ->expectsOutputToContain('app/TestClassOne.php') + ->expectsOutputToContain('app/TestClassTwo.php') + ->expectsOutputToContain('resources/views/test-view-one.blade.php') + ->expectsOutputToContain('resources/views/test-view-two.blade.php') + ->assertExitCode(0); }); diff --git a/tests/LoadConfigKeysTest.php b/tests/LoadConfigKeysTest.php new file mode 100644 index 0000000..dcebb0a --- /dev/null +++ b/tests/LoadConfigKeysTest.php @@ -0,0 +1,52 @@ +configKeys = collect([ + 'app', + 'app.valid_key', + 'app.nested', + 'app.nested.key', + ]); +}); + +it('loads config keys from the config directory', function () { + $loadConfigKeys = new LoadConfigKeys(__DIR__.'/fixtures/base/config'); + + $configKeys = $loadConfigKeys(); + + expect($configKeys)->toMatchArray($this->configKeys); +}); + +it('loads config keys from the default config directory', function () { + $loadConfigKeys = new LoadConfigKeys; + + $configKeys = $loadConfigKeys(); + + expect($configKeys)->contains('app.nested.key')->toBeFalse(); + expect($configKeys)->contains('app.env')->toBeTrue(); + expect($configKeys->count())->toBeGreaterThan(2); +}); + +it('returns a collection of config keys', function () { + $loadConfigKeys = new LoadConfigKeys(__DIR__.'/fixtures/base/config'); + + $configKeys = $loadConfigKeys(); + + expect($configKeys)->toBeInstanceOf(Collection::class); +}); + +it('converts an array of config keys to dotted notation', function () { + $loadConfigKeys = new LoadConfigKeys(__DIR__.'/fixtures/base/config'); + + $configKeys = [ + 'app', + 'app.valid_key', + 'app.nested', + 'app.nested.key', + ]; + + expect($loadConfigKeys())->toMatchArray($configKeys); +}); diff --git a/tests/PhpFilesTest.php b/tests/PhpFilesTest.php new file mode 100644 index 0000000..9bd4451 --- /dev/null +++ b/tests/PhpFilesTest.php @@ -0,0 +1,22 @@ +getRealPath(); + } + + expect($finder->count())->toBe(2); + expect($filePaths)->toContain(__DIR__.'/fixtures/base/app/TestClassOne.php'); + expect($filePaths)->toContain(__DIR__.'/fixtures/base/app/TestClassTwo.php'); + expect($filePaths)->not()->toContain(__DIR__.'/fixtures/base/resources/views/test-view-one.blade.php'); + expect($filePaths)->not()->toContain(__DIR__.'/fixtures/base/resources/views/test-view-two.blade.php'); + expect($filePaths)->not()->toContain(__DIR__.'/fixtures/base/config/app.php'); + expect($filePaths)->not()->toContain(__DIR__.'/fixtures/base/vendor/VendorClassOne.php'); +}); diff --git a/tests/fixtures/base/app/TestClassOne.php b/tests/fixtures/base/app/TestClassOne.php new file mode 100644 index 0000000..244c283 --- /dev/null +++ b/tests/fixtures/base/app/TestClassOne.php @@ -0,0 +1,15 @@ + 'Laravel Config Checker', + 'nested' => [ + 'key' => 'value', + ], +]; diff --git a/tests/fixtures/base/resources/views/test-view-one.blade.php b/tests/fixtures/base/resources/views/test-view-one.blade.php new file mode 100644 index 0000000..c122855 --- /dev/null +++ b/tests/fixtures/base/resources/views/test-view-one.blade.php @@ -0,0 +1,10 @@ +
+

Test View One

+ {{ config('app.invalid_key') }} + {{ Config::get('app.invalid_key') }} + {{ Config::has('app.invalid_key') }} + + {{ config('app.valid_key') }} + {{ Config::get('app.valid_key') }} + {{ Config::has('app.valid_key') }} +
diff --git a/tests/fixtures/base/resources/views/test-view-two.blade.php b/tests/fixtures/base/resources/views/test-view-two.blade.php new file mode 100644 index 0000000..d8647f8 --- /dev/null +++ b/tests/fixtures/base/resources/views/test-view-two.blade.php @@ -0,0 +1,10 @@ +
+

Test View Two

+ {{ config('app.invalid_key') }} + {{ Config::get('app.invalid_key') }} + {{ Config::has('app.invalid_key') }} + + {{ config('app.valid_key') }} + {{ Config::get('app.valid_key') }} + {{ Config::has('app.valid_key') }} +
diff --git a/tests/fixtures/config/app.php b/tests/fixtures/config/app.php deleted file mode 100644 index d55e792..0000000 --- a/tests/fixtures/config/app.php +++ /dev/null @@ -1,10 +0,0 @@ - 'Testing', - 'env' => 'testing', - - 'nested' => [ - 'valid_nested_key' => 'Nested Testing', - ], -]; diff --git a/tests/fixtures/invalid/app/TestClassOne.php b/tests/fixtures/invalid/app/TestClassOne.php new file mode 100644 index 0000000..244c283 --- /dev/null +++ b/tests/fixtures/invalid/app/TestClassOne.php @@ -0,0 +1,15 @@ + 'Testing', - 'env' => 'testing', - + 'valid_key' => 'Laravel Config Checker', 'nested' => [ - 'valid_nested_key' => 'Nested Testing', + 'key' => 'value', ], ]; diff --git a/tests/fixtures/invalid/resources/views/invalid-get.blade.php b/tests/fixtures/invalid/resources/views/invalid-get.blade.php deleted file mode 100644 index 8af0a4a..0000000 --- a/tests/fixtures/invalid/resources/views/invalid-get.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - +

Test View One

+ {{ config('app.invalid_key') }} + {{ Config::get('app.invalid_key') }} + {{ Config::has('app.invalid_key') }} + + {{ config('app.valid_key') }} + {{ Config::get('app.valid_key') }} + {{ Config::has('app.valid_key') }} + diff --git a/tests/fixtures/invalid/resources/views/test-view-two.blade.php b/tests/fixtures/invalid/resources/views/test-view-two.blade.php new file mode 100644 index 0000000..d8647f8 --- /dev/null +++ b/tests/fixtures/invalid/resources/views/test-view-two.blade.php @@ -0,0 +1,10 @@ +
+

Test View Two

+ {{ config('app.invalid_key') }} + {{ Config::get('app.invalid_key') }} + {{ Config::has('app.invalid_key') }} + + {{ config('app.valid_key') }} + {{ Config::get('app.valid_key') }} + {{ Config::has('app.valid_key') }} +
diff --git a/tests/fixtures/valid/app/TestClassOne.php b/tests/fixtures/valid/app/TestClassOne.php new file mode 100644 index 0000000..7c72193 --- /dev/null +++ b/tests/fixtures/valid/app/TestClassOne.php @@ -0,0 +1,15 @@ + 'Testing', - 'env' => 'testing', - + 'valid_key' => 'Laravel Config Checker', 'nested' => [ - 'valid_nested_key' => 'Nested Testing', + 'key' => 'value', ], ]; diff --git a/tests/fixtures/valid/resources/views/test-view-one.blade.php b/tests/fixtures/valid/resources/views/test-view-one.blade.php new file mode 100644 index 0000000..c5bbfde --- /dev/null +++ b/tests/fixtures/valid/resources/views/test-view-one.blade.php @@ -0,0 +1,7 @@ +
+

Test View One

+ + {{ config('app.valid_key') }} + {{ Config::get('app.valid_key') }} + {{ Config::has('app.valid_key') }} +
diff --git a/tests/fixtures/valid/resources/views/test-view-two.blade.php b/tests/fixtures/valid/resources/views/test-view-two.blade.php new file mode 100644 index 0000000..1aedd4c --- /dev/null +++ b/tests/fixtures/valid/resources/views/test-view-two.blade.php @@ -0,0 +1,7 @@ +
+

Test View Two

+ + {{ config('app.valid_key') }} + {{ Config::get('app.valid_key') }} + {{ Config::has('app.valid_key') }} +
diff --git a/tests/fixtures/valid/resources/views/valid-get.blade.php b/tests/fixtures/valid/resources/views/valid-get.blade.php deleted file mode 100644 index 8fe2e9f..0000000 --- a/tests/fixtures/valid/resources/views/valid-get.blade.php +++ /dev/null @@ -1,3 +0,0 @@ -