diff --git a/monorepo/HydeStan/.gitignore b/monorepo/HydeStan/.gitignore new file mode 100644 index 00000000000..3f6dfa69862 --- /dev/null +++ b/monorepo/HydeStan/.gitignore @@ -0,0 +1 @@ +todo.md \ No newline at end of file diff --git a/monorepo/HydeStan/HydeStan.php b/monorepo/HydeStan/HydeStan.php index 05aa7eafe55..279fed01ce4 100644 --- a/monorepo/HydeStan/HydeStan.php +++ b/monorepo/HydeStan/HydeStan.php @@ -20,6 +20,8 @@ final class HydeStan private const TEST_FILE_ANALYSERS = [ NoFixMeAnalyser::class, NoUsingAssertEqualsForScalarTypesTestAnalyser::class, + NoParentSetUpTearDownInUnitTestCaseAnalyser::class, + UnitTestCaseExtensionAnalyzer::class, ]; private const LINE_ANALYSERS = [ @@ -85,6 +87,8 @@ public function run(): void $this->analyseFile($file, $this->getFileContents($file)); } + $this->console->info('Finished analyzing files!'); + $this->runTestStan(); $endTime = microtime(true) - $time; @@ -382,3 +386,59 @@ public function run(string $file, int $lineNumber, string $line): void } } } + +class NoParentSetUpTearDownInUnitTestCaseAnalyser extends FileAnalyser +{ + public function run(string $file, string $contents): void + { + if (! str_contains($contents, 'extends UnitTestCase')) { + return; + } + + $methods = ['setUp', 'tearDown']; + + foreach ($methods as $method) { + AnalysisStatisticsContainer::analysedExpression(); + if (str_contains($contents, "parent::$method()")) { + $lineNumber = substr_count(substr($contents, 0, strpos($contents, $method)), "\n") + 1; + $this->fail(sprintf("Found '%s' method in UnitTestCase at %s", "parent::$method()", fileLink($file, $lineNumber, false))); + HydeStan::addActionsMessage('error', $file, $lineNumber, "HydeStan: UnnecessaryParent{$method}MethodError", "{$method} method in UnitTestCase performs no operation and should be removed."); + } + } + } +} + +class UnitTestCaseExtensionAnalyzer extends FileAnalyser +{ + public function run(string $file, string $contents): void + { + // Check if the file is in the unit namespace + if (! str_contains($file, 'Unit')) { + AnalysisStatisticsContainer::analysedExpression(); + + return; + } + + AnalysisStatisticsContainer::analysedExpression(); + + // Unit view tests are allowed to extend TestCase + if (str_contains($file, 'ViewTest')) { + AnalysisStatisticsContainer::analysedExpression(); + + return; + } + + AnalysisStatisticsContainer::analysedExpression(); + + // Check if the class extends TestCase but not UnitTestCase + if (str_contains($contents, 'extends TestCase') && ! str_contains($contents, 'extends UnitTestCase')) { + AnalysisStatisticsContainer::analysedExpressions(2); + + $lineNumber = substr_count(substr($contents, 0, strpos($contents, 'extends TestCase')), "\n") + 1; + + todo(realpath(__DIR__.'/../../packages/framework/'.$file), $lineNumber, 'Refactor unit test to extend UnitTestCase instead of TestCase'); + + echo sprintf('Test in unit namespace extends TestCase instead of UnitTestCase at %s', fileLink($file, $lineNumber, false))."\n"; + } + } +} diff --git a/monorepo/HydeStan/includes/helpers.php b/monorepo/HydeStan/includes/helpers.php index f3a9c8dcb31..6f3e2d94e1d 100644 --- a/monorepo/HydeStan/includes/helpers.php +++ b/monorepo/HydeStan/includes/helpers.php @@ -51,11 +51,14 @@ function check_str_contains_any(array $searches, string $line): bool return $strContainsAny; } -function fileLink(string $file, ?int $line = null): string +function fileLink(string $file, ?int $line = null, bool $substr = true): string { $path = (realpath(__DIR__.'/../../packages/framework/'.$file) ?: $file).($line ? ':'.$line : ''); - $trim = strlen(getcwd()) + 2; - $path = substr($path, $trim); + + if ($substr) { + $trim = strlen(getcwd()) + 2; + $path = substr($path, $trim); + } return str_replace('\\', '/', $path); } @@ -74,3 +77,61 @@ function recursiveFileFinder(string $directory): array return $files; } + +class TodoBuffer +{ + private static array $todos = []; + + public static function add(string $file, int $line, string $todo): void + { + self::$todos[] = [ + 'file' => $file, + 'line' => $line, + 'todo' => $todo, + ]; + } + + public static function getTodos(): array + { + return self::$todos; + } + + public static function writeTaskFile(): void + { + $todos = self::getTodos(); + + if (empty($todos)) { + return; + } + + $taskFile = __DIR__.'/../todo.md'; + + $content = '# Todos'."\n\n"; + $groupedTodos = []; + + $baseDir = realpath(__DIR__.'/../../../'); + + foreach ($todos as $todo) { + $path = "{$todo['file']}:{$todo['line']}"; + $path = str_replace('\\', '/', $path); + + $path = substr($path, strlen($baseDir) + 1); + + $groupedTodos[$todo['todo']][] = "[$path]($path)"; + } + + foreach ($groupedTodos as $todo => $items) { + $content .= "## $todo\n\n"; + foreach ($items as $item) { + $content .= "- $item\n"; + } + } + + file_put_contents($taskFile, $content); + } +} + +function todo(string $file, int $line, string $todo): void +{ + TodoBuffer::add($file, $line, $todo); +} diff --git a/monorepo/HydeStan/run.php b/monorepo/HydeStan/run.php index 00582d506ba..9bb308320dc 100644 --- a/monorepo/HydeStan/run.php +++ b/monorepo/HydeStan/run.php @@ -12,6 +12,9 @@ $analyser = new HydeStan($debug); $analyser->run(); +// Todo: Could add a flag for this +TodoBuffer::writeTaskFile(); + if ($analyser->hasErrors()) { exit(1); } diff --git a/packages/framework/src/Facades/Filesystem.php b/packages/framework/src/Facades/Filesystem.php index 3229bc584c3..fa0434212e1 100644 --- a/packages/framework/src/Facades/Filesystem.php +++ b/packages/framework/src/Facades/Filesystem.php @@ -113,7 +113,7 @@ public static function unlinkIfExists(string $path): bool */ public static function getContents(string $path, bool $lock = false): string { - return self::get($path, $lock); + return self::get(...func_get_args()); } /** @@ -126,7 +126,7 @@ public static function getContents(string $path, bool $lock = false): string */ public static function putContents(string $path, string $contents, bool $lock = false): bool|int { - return self::put($path, $contents, $lock); + return self::put(...func_get_args()); } protected static function filesystem(): \Illuminate\Filesystem\Filesystem diff --git a/packages/framework/src/Foundation/Kernel/FileCollection.php b/packages/framework/src/Foundation/Kernel/FileCollection.php index 9013be74f77..b52355ddef8 100644 --- a/packages/framework/src/Foundation/Kernel/FileCollection.php +++ b/packages/framework/src/Foundation/Kernel/FileCollection.php @@ -4,13 +4,13 @@ namespace Hyde\Foundation\Kernel; +use Hyde\Facades\Filesystem; use Hyde\Foundation\Concerns\BaseFoundationCollection; use Hyde\Framework\Exceptions\FileNotFoundException; use Hyde\Pages\Concerns\HydePage; use Hyde\Support\Filesystem\SourceFile; use function basename; -use function glob; use function str_starts_with; /** @@ -59,7 +59,7 @@ protected function runExtensionHandlers(): void protected function discoverFilesFor(string $pageClass): void { // Scan the source directory, and directories therein, for files that match the model's file extension. - foreach (glob($this->kernel->path($pageClass::sourcePath('{*,**/*}')), GLOB_BRACE) as $path) { + foreach (Filesystem::smartGlob($pageClass::sourcePath('{*,**/*}'), GLOB_BRACE) as $path) { if (! str_starts_with(basename((string) $path), '_')) { $this->addFile(SourceFile::make($path, $pageClass)); } diff --git a/packages/framework/src/Framework/Actions/BladeMatterParser.php b/packages/framework/src/Framework/Actions/BladeMatterParser.php index 2f2dcc6eb9c..df3c402d427 100644 --- a/packages/framework/src/Framework/Actions/BladeMatterParser.php +++ b/packages/framework/src/Framework/Actions/BladeMatterParser.php @@ -4,10 +4,9 @@ namespace Hyde\Framework\Actions; -use Hyde\Hyde; use RuntimeException; +use Hyde\Facades\Filesystem; -use function file_get_contents; use function str_ends_with; use function str_starts_with; use function substr_count; @@ -53,7 +52,7 @@ class BladeMatterParser public static function parseFile(string $path): array { - return static::parseString(file_get_contents(Hyde::path($path))); + return static::parseString(Filesystem::getContents($path)); } public static function parseString(string $contents): array diff --git a/packages/framework/tests/Unit/DocumentationPageTest.php b/packages/framework/tests/Feature/DocumentationPageTest.php similarity index 99% rename from packages/framework/tests/Unit/DocumentationPageTest.php rename to packages/framework/tests/Feature/DocumentationPageTest.php index 06645054f53..7967d643b17 100644 --- a/packages/framework/tests/Unit/DocumentationPageTest.php +++ b/packages/framework/tests/Feature/DocumentationPageTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Hyde\Framework\Testing\Unit; +namespace Hyde\Framework\Testing\Feature; use Hyde\Facades\Filesystem; use Hyde\Foundation\Facades\Routes; diff --git a/packages/framework/tests/Feature/FilesystemFacadeTest.php b/packages/framework/tests/Feature/FilesystemFacadeTest.php index db00aefc30c..1c4216c438a 100644 --- a/packages/framework/tests/Feature/FilesystemFacadeTest.php +++ b/packages/framework/tests/Feature/FilesystemFacadeTest.php @@ -7,14 +7,13 @@ use Hyde\Facades\Filesystem; use Hyde\Hyde; use Hyde\Testing\TestCase; -use Illuminate\Support\Collection; -use Illuminate\Support\Facades\File; -use Illuminate\Support\LazyCollection; /** * @covers \Hyde\Facades\Filesystem * @covers \Hyde\Foundation\Kernel\Filesystem * @covers \Hyde\Framework\Concerns\Internal\ForwardsIlluminateFilesystem + * + * @see \Hyde\Framework\Testing\Unit\FilesystemFacadeUnitTest */ class FilesystemFacadeTest extends TestCase { @@ -36,21 +35,6 @@ public function testRelativePath() $this->assertSame('foo', Filesystem::relativePath('foo')); } - public function testSmartGlob() - { - $this->createExpectation('glob', [ - Hyde::path('foo'), - Hyde::path('bar'), - Hyde::path('baz'), - ], Hyde::path('pattern/*.md'), 0); - - $expected = Collection::make(['foo', 'bar', 'baz']); - $actual = Filesystem::smartGlob('pattern/*.md'); - - $this->assertEquals($expected, $actual); - $this->assertSame($expected->all(), $actual->all()); - } - public function testTouch() { Filesystem::touch('foo'); @@ -78,342 +62,6 @@ public function testUnlinkIfExists() $this->assertFileDoesNotExist(Hyde::path('foo')); } - public function testGetContents() - { - $this->createExpectation('get', 'string', Hyde::path('path'), false); - - Filesystem::getContents('path'); - } - - public function testPutContents() - { - $this->createExpectation('put', true, Hyde::path('path'), 'string', false); - - Filesystem::putContents('path', 'string'); - } - - public function testExists() - { - $this->createExpectation('exists', true, Hyde::path('path')); - - Filesystem::exists('path'); - } - - public function testMissing() - { - $this->createExpectation('missing', true, Hyde::path('path')); - - Filesystem::missing('path'); - } - - public function testGet() - { - $this->createExpectation('get', 'string', Hyde::path('path')); - - Filesystem::get('path'); - } - - public function testSharedGet() - { - $this->createExpectation('sharedGet', 'string', Hyde::path('path')); - - Filesystem::sharedGet('path'); - } - - public function testGetRequire() - { - $this->createExpectation('getRequire', 'string', Hyde::path('path')); - - Filesystem::getRequire('path'); - } - - public function testRequireOnce() - { - $this->createExpectation('requireOnce', 'string', Hyde::path('path')); - - Filesystem::requireOnce('path'); - } - - public function testLines() - { - $this->createExpectation('lines', new LazyCollection(), Hyde::path('path')); - - Filesystem::lines('path'); - } - - public function testHash() - { - $this->createExpectation('hash', 'string', Hyde::path('path')); - - Filesystem::hash('path'); - } - - public function testPut() - { - $this->createExpectation('put', 10, Hyde::path('path'), 'contents'); - - Filesystem::put('path', 'contents'); - } - - public function testReplace() - { - $this->createExpectation('replace', null, Hyde::path('path'), 'content'); - - Filesystem::replace('path', 'content'); - } - - public function testReplaceInFile() - { - $this->createExpectation('replaceInFile', null, 'search', 'replace', Hyde::path('path')); - - Filesystem::replaceInFile('search', 'replace', 'path'); - } - - public function testPrepend() - { - $this->createExpectation('prepend', 10, Hyde::path('path'), 'data'); - - Filesystem::prepend('path', 'data'); - } - - public function testAppend() - { - $this->createExpectation('append', 10, Hyde::path('path'), 'data'); - - Filesystem::append('path', 'data'); - } - - public function testChmod() - { - $this->createExpectation('chmod', null, Hyde::path('path'), 0755); - - Filesystem::chmod('path', 0755); - } - - public function testDelete() - { - $this->createExpectation('delete', true, Hyde::path('path')); - - Filesystem::delete('path'); - } - - public function testDeleteWithArray() - { - $this->createExpectation('delete', true, [Hyde::path('path'), Hyde::path('another')]); - - Filesystem::delete(['path', 'another']); - } - - public function testMove() - { - $this->createExpectation('move', true, Hyde::path('path'), Hyde::path('target')); - - Filesystem::move('path', 'target'); - } - - public function testCopy() - { - $this->createExpectation('copy', true, Hyde::path('path'), Hyde::path('target')); - - Filesystem::copy('path', 'target'); - } - - public function testLink() - { - $this->createExpectation('link', true, Hyde::path('target'), Hyde::path('link')); - - Filesystem::link('target', 'link'); - } - - public function testRelativeLink() - { - $this->createExpectation('relativeLink', true, Hyde::path('target'), Hyde::path('link')); - - Filesystem::relativeLink('target', 'link'); - } - - public function testName() - { - $this->createExpectation('name', 'string', Hyde::path('path')); - - Filesystem::name('path'); - } - - public function testBasename() - { - $this->createExpectation('basename', 'string', Hyde::path('path')); - - Filesystem::basename('path'); - } - - public function testDirname() - { - $this->createExpectation('dirname', 'string', Hyde::path('path')); - - Filesystem::dirname('path'); - } - - public function testExtension() - { - $this->createExpectation('extension', 'string', Hyde::path('path')); - - Filesystem::extension('path'); - } - - public function testGuessExtension() - { - $this->createExpectation('guessExtension', 'string', Hyde::path('path')); - - Filesystem::guessExtension('path'); - } - - public function testType() - { - $this->createExpectation('type', 'string', Hyde::path('path')); - - Filesystem::type('path'); - } - - public function testMimeType() - { - $this->createExpectation('mimeType', 'string', Hyde::path('path')); - - Filesystem::mimeType('path'); - } - - public function testSize() - { - $this->createExpectation('size', 10, Hyde::path('path')); - - Filesystem::size('path'); - } - - public function testLastModified() - { - $this->createExpectation('lastModified', 10, Hyde::path('path')); - - Filesystem::lastModified('path'); - } - - public function testIsDirectory() - { - $this->createExpectation('isDirectory', true, Hyde::path('directory')); - - Filesystem::isDirectory('directory'); - } - - public function testIsEmptyDirectory() - { - $this->createExpectation('isEmptyDirectory', true, Hyde::path('directory')); - - Filesystem::isEmptyDirectory('directory'); - } - - public function testIsReadable() - { - $this->createExpectation('isReadable', true, Hyde::path('path')); - - Filesystem::isReadable('path'); - } - - public function testIsWritable() - { - $this->createExpectation('isWritable', true, Hyde::path('path')); - - Filesystem::isWritable('path'); - } - - public function testHasSameHash() - { - $this->createExpectation('hasSameHash', true, Hyde::path('firstFile'), Hyde::path('secondFile')); - - Filesystem::hasSameHash('firstFile', 'secondFile'); - } - - public function testIsFile() - { - $this->createExpectation('isFile', true, Hyde::path('file')); - - Filesystem::isFile('file'); - } - - public function testGlob() - { - $this->createExpectation('glob', [], Hyde::path('pattern')); - - Filesystem::glob('pattern'); - } - - public function testFiles() - { - $this->createExpectation('files', [], Hyde::path('directory')); - - Filesystem::files('directory'); - } - - public function testAllFiles() - { - $this->createExpectation('allFiles', [], Hyde::path('directory')); - - Filesystem::allFiles('directory'); - } - - public function testDirectories() - { - $this->createExpectation('directories', [], Hyde::path('directory')); - - Filesystem::directories('directory'); - } - - public function testEnsureDirectoryExists() - { - $this->createExpectation('ensureDirectoryExists', null, Hyde::path('path')); - - Filesystem::ensureDirectoryExists('path'); - } - - public function testMakeDirectory() - { - $this->createExpectation('makeDirectory', true, Hyde::path('path')); - - Filesystem::makeDirectory('path'); - } - - public function testMoveDirectory() - { - $this->createExpectation('moveDirectory', true, Hyde::path('from'), Hyde::path('to')); - - Filesystem::moveDirectory('from', 'to'); - } - - public function testCopyDirectory() - { - $this->createExpectation('copyDirectory', true, Hyde::path('directory'), Hyde::path('destination')); - - Filesystem::copyDirectory('directory', 'destination'); - } - - public function testDeleteDirectory() - { - $this->createExpectation('deleteDirectory', true, Hyde::path('directory')); - - Filesystem::deleteDirectory('directory'); - } - - public function testDeleteDirectories() - { - $this->createExpectation('deleteDirectories', true, Hyde::path('directory')); - - Filesystem::deleteDirectories('directory'); - } - - public function testCleanDirectory() - { - $this->createExpectation('cleanDirectory', true, Hyde::path('directory')); - - Filesystem::cleanDirectory('directory'); - } - public function testMethodWithoutMocking() { $this->assertSame(3, Filesystem::put('foo', 'bar')); @@ -446,9 +94,4 @@ public function testMethodWithMixedSequentialAndNamedArgumentsSkippingMiddleOne( rmdir(Hyde::path('foo')); } - - protected function createExpectation(string $method, mixed $returns, ...$args): void - { - File::shouldReceive($method)->withArgs($args)->once()->andReturn($returns); - } } diff --git a/packages/framework/tests/Feature/Foundation/FilesystemTest.php b/packages/framework/tests/Feature/Foundation/FilesystemTest.php index 6c2c2811cd8..5527f9ce127 100644 --- a/packages/framework/tests/Feature/Foundation/FilesystemTest.php +++ b/packages/framework/tests/Feature/Foundation/FilesystemTest.php @@ -31,8 +31,6 @@ class FilesystemTest extends UnitTestCase protected function setUp(): void { - parent::setUp(); - $this->originalBasePath = Hyde::getBasePath(); $this->filesystem = new Filesystem(Hyde::getInstance()); } @@ -40,8 +38,6 @@ protected function setUp(): void protected function tearDown(): void { Hyde::getInstance()->setBasePath($this->originalBasePath); - - parent::tearDown(); } public function testGetBasePathReturnsKernelsBasePath() diff --git a/packages/framework/tests/Feature/HydeKernelTest.php b/packages/framework/tests/Feature/HydeKernelTest.php index 8c1470b4206..368dd3a6bcd 100644 --- a/packages/framework/tests/Feature/HydeKernelTest.php +++ b/packages/framework/tests/Feature/HydeKernelTest.php @@ -363,6 +363,12 @@ public function testSetOutputDirectoryTrimsTrailingSlashes() $this->assertSame('/foo', Hyde::getOutputDirectory()); } + public function testSiteOutputDirectoryPathIsNormalizedToTrimTrailingSlashes() + { + Hyde::setOutputDirectory('foo/bar/'); + $this->assertSame('foo/bar', Hyde::kernel()->getOutputDirectory()); + } + public function testCanGetMediaDirectory() { $this->assertSame('_media', Hyde::getMediaDirectory()); diff --git a/packages/framework/tests/Feature/MarkdownFileParserTest.php b/packages/framework/tests/Feature/MarkdownFileParserTest.php index 09e5b1dc06e..75ba8afcb1c 100644 --- a/packages/framework/tests/Feature/MarkdownFileParserTest.php +++ b/packages/framework/tests/Feature/MarkdownFileParserTest.php @@ -4,8 +4,6 @@ namespace Hyde\Framework\Testing\Feature; -use Hyde\Hyde; -use Hyde\Facades\Filesystem; use Hyde\Framework\Actions\MarkdownFileParser; use Hyde\Markdown\Models\FrontMatter; use Hyde\Markdown\Models\MarkdownDocument; @@ -15,33 +13,9 @@ class MarkdownFileParserTest extends UnitTestCase { protected static bool $needsKernel = true; - protected function makeTestPost(): void - { - Filesystem::putContents('_posts/test-post.md', <<<'MD' - --- - title: My New Post - category: blog - author: Mr. Hyde - --- - - # My New Post - - This is a post stub used in the automated tests - - MD - ); - } - - protected function tearDown(): void - { - Filesystem::unlink('_posts/test-post.md'); - - parent::tearDown(); - } - public function testCanParseMarkdownFile() { - file_put_contents(Hyde::path('_posts/test-post.md'), 'Foo bar'); + $this->mockFilesystem(['get' => 'Foo bar']); $document = MarkdownFileParser::parse('_posts/test-post.md'); @@ -52,7 +26,17 @@ public function testCanParseMarkdownFile() public function testCanParseMarkdownFileWithFrontMatter() { - $this->makeTestPost(); + $this->mockFilesystem(['get' => <<<'MD' + --- + title: My New Post + category: blog + author: Mr. Hyde + --- + + # My New Post + + This is a post stub used in the automated tests + MD]); $document = MarkdownFileParser::parse('_posts/test-post.md'); @@ -76,7 +60,17 @@ public function testCanParseMarkdownFileWithFrontMatter() public function testParsedMarkdownPostContainsValidFrontMatter() { - $this->makeTestPost(); + $this->mockFilesystem(['get' => <<<'MD' + --- + title: My New Post + category: blog + author: Mr. Hyde + --- + + # My New Post + + This is a post stub used in the automated tests + MD]); $post = MarkdownFileParser::parse('_posts/test-post.md'); @@ -87,7 +81,7 @@ public function testParsedMarkdownPostContainsValidFrontMatter() public function testCanParseMarkdownFileWithFrontMatterAndNoMarkdownBody() { - file_put_contents(Hyde::path('_posts/test-post.md'), "---\nfoo: bar\n---"); + $this->mockFilesystem(['get' => "---\nfoo: bar\n---"]); $document = MarkdownFileParser::parse('_posts/test-post.md'); diff --git a/packages/framework/tests/Feature/MarkdownPostTest.php b/packages/framework/tests/Feature/MarkdownPostTest.php index 9716c9c78bf..847562dda91 100644 --- a/packages/framework/tests/Feature/MarkdownPostTest.php +++ b/packages/framework/tests/Feature/MarkdownPostTest.php @@ -4,6 +4,10 @@ namespace Hyde\Framework\Testing\Feature; +use Hyde\Hyde; +use Hyde\Pages\BladePage; +use Hyde\Facades\Filesystem; +use Hyde\Framework\Actions\StaticPageBuilder; use Hyde\Framework\Features\Blogging\Models\FeaturedImage; use Hyde\Framework\Features\Blogging\Models\PostAuthor; use Hyde\Markdown\Models\FrontMatter; @@ -124,4 +128,34 @@ public function testFeaturedImageCanBeConstructedReturnsImageObjectWithSuppliedD $this->assertSame('media/foo.png', $image->getSource()); $this->assertSame('bar', $image->getTitleText()); } + + public function testBlogPostCanBeCreatedWithoutFrontMatter() + { + file_put_contents(Hyde::path('_posts/test-post.md'), '# My New Post'); + + StaticPageBuilder::handle(MarkdownPost::get('test-post')); + + $this->assertFileExists(Hyde::path('_site/posts/test-post.html')); + + Filesystem::unlink('_posts/test-post.md'); + Filesystem::unlink('_site/posts/test-post.html'); + } + + public function testBlogPostFeedCanBeRenderedWhenPostHasNoFrontMatter() + { + file_put_contents(Hyde::path('_posts/test-post.md'), '# My New Post'); + + // Create a temporary page to test the feed + copy(Hyde::vendorPath('resources/views/components/blog-post-feed.blade.php'), + Hyde::path('_pages/feed-test.blade.php') + ); + + StaticPageBuilder::handle(BladePage::get('feed-test')); + + $this->assertFileExists(Hyde::path('_site/feed-test.html')); + + Filesystem::unlink('_posts/test-post.md'); + Filesystem::unlink('_pages/feed-test.blade.php'); + Filesystem::unlink('_site/feed-test.html'); + } } diff --git a/packages/framework/tests/Feature/NavigationAPITest.php b/packages/framework/tests/Feature/NavigationAPITest.php index f396837b0e9..22b5257cc99 100644 --- a/packages/framework/tests/Feature/NavigationAPITest.php +++ b/packages/framework/tests/Feature/NavigationAPITest.php @@ -8,6 +8,7 @@ use Hyde\Pages\BladePage; use Hyde\Testing\TestCase; use Illuminate\Support\Arr; +use AllowDynamicProperties; use Hyde\Foundation\Facades\Routes; use Hyde\Testing\MocksKernelFeatures; use Illuminate\Support\Facades\Blade; @@ -28,6 +29,7 @@ * @covers \Hyde\Framework\Features\Navigation\MainNavigationMenu * @covers \Hyde\Framework\Features\Navigation\DocumentationSidebar */ +#[AllowDynamicProperties] class NavigationAPITest extends TestCase { use MocksKernelFeatures; diff --git a/packages/framework/tests/Feature/ReadingTimeTest.php b/packages/framework/tests/Feature/ReadingTimeTest.php index 93dbe654526..c55014d6bb2 100644 --- a/packages/framework/tests/Feature/ReadingTimeTest.php +++ b/packages/framework/tests/Feature/ReadingTimeTest.php @@ -4,11 +4,9 @@ namespace Hyde\Framework\Testing\Feature; -use Mockery; use Hyde\Hyde; use Hyde\Support\ReadingTime; use Hyde\Testing\UnitTestCase; -use Illuminate\Filesystem\Filesystem; /** * @covers \Hyde\Support\ReadingTime @@ -111,13 +109,12 @@ public function testFromString() public function testFromFile() { - app()->instance(Filesystem::class, Mockery::mock(Filesystem::class)->shouldReceive('get')->with(Hyde::path('foo.md'), false)->andReturn('Hello world')->getMock()); + $this->mockFilesystemStrict()->shouldReceive('get')->twice()->with(Hyde::path('foo.md'))->andReturn('Hello world'); $this->assertInstanceOf(ReadingTime::class, ReadingTime::fromFile('foo.md')); $this->assertEquals(new ReadingTime('Hello world'), ReadingTime::fromFile('foo.md')); - Mockery::close(); - app()->forgetInstance(Filesystem::class); + $this->verifyMockeryExpectations(); } protected function words(int $words): string diff --git a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php index 67acd7ffe39..f658a95a57e 100644 --- a/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php +++ b/packages/framework/tests/Feature/Services/Markdown/DynamicMarkdownLinkProcessorTest.php @@ -27,8 +27,6 @@ class DynamicMarkdownLinkProcessorTest extends UnitTestCase protected function setUp(): void { - parent::setUp(); - Render::swap(new RenderData()); Routes::addRoute(new Route(new BladePage('index'))); diff --git a/packages/framework/tests/Feature/StaticSiteServiceTest.php b/packages/framework/tests/Feature/StaticSiteServiceTest.php index 558a2f835ff..8c740d851c5 100644 --- a/packages/framework/tests/Feature/StaticSiteServiceTest.php +++ b/packages/framework/tests/Feature/StaticSiteServiceTest.php @@ -8,8 +8,11 @@ use Hyde\Hyde; use Hyde\Support\BuildWarnings; use Hyde\Testing\TestCase; +use Hyde\Foundation\Facades\Pages; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Process; +use Hyde\Framework\HydeServiceProvider; +use Hyde\Framework\Actions\StaticPageBuilder; /** * @covers \Hyde\Console\Commands\BuildSiteCommand @@ -304,4 +307,65 @@ public function testWithWarningsConvertedToExceptions() ->doesntExpectOutput(' 1. This is a warning') ->assertExitCode(2); } + + public function testSiteOutputDirectoryCanBeChangedForSiteBuilds() + { + $this->file('_posts/test-post.md'); + + Hyde::setOutputDirectory('_site/build'); + + $this->withoutMockingConsoleOutput(); + $this->artisan('build'); + + $this->assertFileExists(Hyde::path('_site/build/posts/test-post.html')); + $this->assertFileExists(Hyde::path('_site/build/media/app.css')); + $this->assertFileExists(Hyde::path('_site/build/index.html')); + + File::deleteDirectory(Hyde::path('_site/build')); + } + + public function testSiteOutputDirectoryCanBeChangedInStaticPageBuilder() + { + $this->file('_posts/test-post.md'); + + Hyde::setOutputDirectory('_site/build'); + + StaticPageBuilder::handle(Pages::getPage('_posts/test-post.md')); + + $this->assertFileExists(Hyde::path('_site/build/posts/test-post.html')); + + File::deleteDirectory(Hyde::path('_site/build')); + } + + public function testOutputDirectoryIsCreatedIfItDoesNotExistInStaticPageBuilder() + { + $this->file('_posts/test-post.md'); + + File::deleteDirectory(Hyde::path('_site/build/foo')); + Hyde::setOutputDirectory('_site/build/foo'); + + StaticPageBuilder::handle(Pages::getPage('_posts/test-post.md')); + + $this->assertFileExists(Hyde::path('_site/build/foo/posts/test-post.html')); + + File::deleteDirectory(Hyde::path('_site/build/foo')); + } + + public function testSiteOutputDirectoryCanBeChangedInConfiguration() + { + $this->assertSame('_site', Hyde::kernel()->getOutputDirectory()); + + config(['hyde.output_directory' => '_site/build']); + (new HydeServiceProvider($this->app))->register(); + + $this->assertSame('_site/build', Hyde::kernel()->getOutputDirectory()); + + $this->file('_posts/test-post.md'); + + StaticPageBuilder::handle(Pages::getPage('_posts/test-post.md')); + + $this->assertFileExists(Hyde::path('_site/build/posts/test-post.html')); + + File::deleteDirectory(Hyde::path('_site/build')); + } } diff --git a/packages/framework/tests/Unit/AssetServiceUnitTest.php b/packages/framework/tests/Unit/AssetServiceUnitTest.php index 9267b4715a6..4554ec53df0 100644 --- a/packages/framework/tests/Unit/AssetServiceUnitTest.php +++ b/packages/framework/tests/Unit/AssetServiceUnitTest.php @@ -17,7 +17,7 @@ class AssetServiceUnitTest extends UnitTestCase { protected function setUp(): void { - self::needsKernel(); + self::resetKernel(); self::mockConfig(); } diff --git a/packages/framework/tests/Unit/BaseFoundationCollectionTest.php b/packages/framework/tests/Unit/BaseFoundationCollectionTest.php index 9fb8edb7d5e..95725ec5751 100644 --- a/packages/framework/tests/Unit/BaseFoundationCollectionTest.php +++ b/packages/framework/tests/Unit/BaseFoundationCollectionTest.php @@ -15,9 +15,9 @@ */ class BaseFoundationCollectionTest extends UnitTestCase { - public function testInit() + public function testBaseFoundationCollectionInitialization() { - $this->needsKernel(); + self::resetKernel(); $booted = BaseFoundationCollectionTestClass::init(HydeKernel::getInstance())->boot(); diff --git a/packages/framework/tests/Unit/BlogPostFrontMatterIsOptionalTest.php b/packages/framework/tests/Unit/BlogPostFrontMatterIsOptionalTest.php deleted file mode 100644 index b90fe0a0c19..00000000000 --- a/packages/framework/tests/Unit/BlogPostFrontMatterIsOptionalTest.php +++ /dev/null @@ -1,45 +0,0 @@ -assertFileExists(Hyde::path('_site/posts/test-post.html')); - - Filesystem::unlink('_posts/test-post.md'); - Filesystem::unlink('_site/posts/test-post.html'); - } - - public function testBlogPostFeedCanBeRenderedWhenPostHasNoFrontMatter() - { - file_put_contents(Hyde::path('_posts/test-post.md'), '# My New Post'); - - // Create a temporary page to test the feed - copy(Hyde::vendorPath('resources/views/components/blog-post-feed.blade.php'), - Hyde::path('_pages/feed-test.blade.php') - ); - - StaticPageBuilder::handle(BladePage::get('feed-test')); - - $this->assertFileExists(Hyde::path('_site/feed-test.html')); - - Filesystem::unlink('_posts/test-post.md'); - Filesystem::unlink('_pages/feed-test.blade.php'); - Filesystem::unlink('_site/feed-test.html'); - } -} diff --git a/packages/framework/tests/Unit/BreadcrumbsComponentTest.php b/packages/framework/tests/Unit/BreadcrumbsComponentTest.php index 154fddbfb00..dc5231ada67 100644 --- a/packages/framework/tests/Unit/BreadcrumbsComponentTest.php +++ b/packages/framework/tests/Unit/BreadcrumbsComponentTest.php @@ -23,7 +23,7 @@ class BreadcrumbsComponentTest extends UnitTestCase { protected function setUp(): void { - self::needsKernel(); + self::resetKernel(); self::mockConfig(); } @@ -52,7 +52,7 @@ public function testCanRender() $this->assertSame($view, (new BreadcrumbsComponent())->render()); - Mockery::close(); + $this->verifyMockeryExpectations(); } public function testCanGenerateBreadcrumbs() diff --git a/packages/framework/tests/Unit/BuildOutputDirectoryCanBeChangedTest.php b/packages/framework/tests/Unit/BuildOutputDirectoryCanBeChangedTest.php deleted file mode 100644 index 8205f17dae7..00000000000 --- a/packages/framework/tests/Unit/BuildOutputDirectoryCanBeChangedTest.php +++ /dev/null @@ -1,83 +0,0 @@ -file('_posts/test-post.md'); - - Hyde::setOutputDirectory('_site/build'); - - $this->withoutMockingConsoleOutput(); - $this->artisan('build'); - - $this->assertFileExists(Hyde::path('_site/build/posts/test-post.html')); - $this->assertFileExists(Hyde::path('_site/build/media/app.css')); - $this->assertFileExists(Hyde::path('_site/build/index.html')); - - File::deleteDirectory(Hyde::path('_site/build')); - } - - public function testSiteOutputDirectoryCanBeChangedInStaticPageBuilder() - { - $this->file('_posts/test-post.md'); - - Hyde::setOutputDirectory('_site/build'); - - StaticPageBuilder::handle(Pages::getPage('_posts/test-post.md')); - - $this->assertFileExists(Hyde::path('_site/build/posts/test-post.html')); - - File::deleteDirectory(Hyde::path('_site/build')); - } - - public function testOutputDirectoryIsCreatedIfItDoesNotExistInStaticPageBuilder() - { - $this->file('_posts/test-post.md'); - - File::deleteDirectory(Hyde::path('_site/build/foo')); - Hyde::setOutputDirectory('_site/build/foo'); - - StaticPageBuilder::handle(Pages::getPage('_posts/test-post.md')); - - $this->assertFileExists(Hyde::path('_site/build/foo/posts/test-post.html')); - - File::deleteDirectory(Hyde::path('_site/build/foo')); - } - - public function testSiteOutputDirectoryCanBeChangedInConfiguration() - { - $this->assertSame('_site', Hyde::kernel()->getOutputDirectory()); - - config(['hyde.output_directory' => '_site/build']); - (new HydeServiceProvider($this->app))->register(); - - $this->assertSame('_site/build', Hyde::kernel()->getOutputDirectory()); - - $this->file('_posts/test-post.md'); - - StaticPageBuilder::handle(Pages::getPage('_posts/test-post.md')); - - $this->assertFileExists(Hyde::path('_site/build/posts/test-post.html')); - - File::deleteDirectory(Hyde::path('_site/build')); - } - - public function testSiteOutputDirectoryPathIsNormalizedToTrimTrailingSlashes() - { - Hyde::setOutputDirectory('foo/bar/'); - - $this->assertSame('foo/bar', Hyde::kernel()->getOutputDirectory()); - } -} diff --git a/packages/framework/tests/Unit/BuildTaskServiceUnitTest.php b/packages/framework/tests/Unit/BuildTaskServiceUnitTest.php index 6b9f61cc4e4..f16b2790788 100644 --- a/packages/framework/tests/Unit/BuildTaskServiceUnitTest.php +++ b/packages/framework/tests/Unit/BuildTaskServiceUnitTest.php @@ -45,8 +45,6 @@ protected function setUp(): void protected function tearDown(): void { - parent::tearDown(); - $this->verifyMockeryExpectations(); } @@ -153,16 +151,12 @@ public function testCanOverloadFrameworkTasks() public function testCanSetOutputWithNull() { - $this->can(function () { - $this->service->setOutput(null); - }); + $this->can(fn () => $this->service->setOutput(null)); } public function testCanSetOutputWithOutputStyle() { - $this->can(function () { - $this->service->setOutput(Mockery::mock(OutputStyle::class)); - }); + $this->can(fn () => $this->service->setOutput($this->mockOutput())); } public function testGenerateBuildManifestExtendsPostBuildTask() @@ -182,12 +176,12 @@ public function testGenerateSitemapExtendsPostBuildTask() public function testCanRunPreBuildTasks() { - $this->can($this->service->runPreBuildTasks(...)); + $this->can(fn () => $this->service->runPreBuildTasks(...)); } public function testCanRunPostBuildTasks() { - $this->can($this->service->runPostBuildTasks(...)); + $this->can(fn () => $this->service->runPostBuildTasks(...)); } public function testCanRunPreBuildTasksWithTasks() @@ -208,7 +202,7 @@ public function testCanRunPostBuildTasksWithTasks() public function testRunPreBuildTasksCallsHandleMethods() { - $task = Mockery::mock(TestPreBuildTask::class)->makePartial()->shouldReceive('handle')->once()->getMock(); + $task = $this->setupMock(TestPreBuildTask::class, 'handle')->getMock(); $this->service->registerTask($task); $this->service->runPreBuildTasks(); @@ -216,7 +210,7 @@ public function testRunPreBuildTasksCallsHandleMethods() public function testRunPostBuildTasksCallsHandleMethods() { - $task = Mockery::mock(TestPostBuildTask::class)->makePartial()->shouldReceive('handle')->once()->getMock(); + $task = $this->setupMock(TestPostBuildTask::class, 'handle')->getMock(); $this->service->registerTask($task); $this->service->runPostBuildTasks(); @@ -224,7 +218,7 @@ public function testRunPostBuildTasksCallsHandleMethods() public function testRunPreBuildTasksCallsRunMethods() { - $task = Mockery::mock(TestPreBuildTask::class)->makePartial()->shouldReceive('run')->once()->getMock(); + $task = $this->setupMock(TestPreBuildTask::class, 'run')->getMock(); $this->service->registerTask($task); $this->service->runPreBuildTasks(); @@ -232,7 +226,7 @@ public function testRunPreBuildTasksCallsRunMethods() public function testRunPostBuildTasksCallsRunMethods() { - $task = Mockery::mock(TestPostBuildTask::class)->makePartial()->shouldReceive('run')->once()->getMock(); + $task = $this->setupMock(TestPostBuildTask::class, 'run')->getMock(); $this->service->registerTask($task); $this->service->runPostBuildTasks(); @@ -240,7 +234,7 @@ public function testRunPostBuildTasksCallsRunMethods() public function testRunPreBuildTasksCallsRunMethodsWithNullWhenServiceHasNoOutput() { - $task = Mockery::mock(TestPreBuildTask::class)->makePartial()->shouldReceive('run')->with(null)->once()->getMock(); + $task = $this->setupMock(TestPreBuildTask::class, 'run')->with(null)->once()->getMock(); $this->service->registerTask($task); $this->service->runPreBuildTasks(); @@ -248,7 +242,7 @@ public function testRunPreBuildTasksCallsRunMethodsWithNullWhenServiceHasNoOutpu public function testRunPostBuildTasksCallsRunMethodsWithNullWhenServiceHasNoOutput() { - $task = Mockery::mock(TestPostBuildTask::class)->makePartial()->shouldReceive('run')->with(null)->once()->getMock(); + $task = $this->setupMock(TestPostBuildTask::class, 'run')->with(null)->once()->getMock(); $this->service->registerTask($task); $this->service->runPostBuildTasks(); @@ -256,8 +250,8 @@ public function testRunPostBuildTasksCallsRunMethodsWithNullWhenServiceHasNoOutp public function testRunPreBuildTasksCallsRunMethodsWithOutputWhenServiceHasOutput() { - $output = Mockery::mock(OutputStyle::class)->makePartial(); - $task = Mockery::mock(TestPreBuildTask::class)->makePartial()->shouldReceive('run')->with($output)->once()->getMock(); + $output = $this->mockOutput(); + $task = $this->setupMock(TestPreBuildTask::class, 'run')->with($output)->once()->getMock(); $this->service->setOutput($output); $this->service->registerTask($task); @@ -266,8 +260,8 @@ public function testRunPreBuildTasksCallsRunMethodsWithOutputWhenServiceHasOutpu public function testRunPostBuildTasksCallsRunMethodsWithOutputWhenServiceHasOutput() { - $output = Mockery::mock(OutputStyle::class)->makePartial(); - $task = Mockery::mock(TestPostBuildTask::class)->makePartial()->shouldReceive('run')->with($output)->once()->getMock(); + $output = $this->mockOutput(); + $task = $this->setupMock(TestPostBuildTask::class, 'run')->with($output)->once()->getMock(); $this->service->setOutput($output); $this->service->registerTask($task); @@ -291,6 +285,7 @@ public function testServiceFindsTasksInAppDirectory() 'app/Actions/GenerateBuildManifestBuildTask.php' => GenerateBuildManifest::class, 'app/Actions/GenerateRssFeedBuildTask.php' => GenerateRssFeed::class, ]; + $this->mockKernelFilesystem($files); $this->can($this->createService(...)); @@ -316,17 +311,9 @@ protected function createService(): BuildTaskService return tap(new BuildTaskService(), fn (BuildTaskService $service) => $this->service = $service); } - protected function verifyMockeryExpectations(): void - { - $this->addToAssertionCount(Mockery::getContainer()->mockery_getExpectationCount()); - - Mockery::close(); - } - protected function mockKernelFilesystem(array $files = []): void { - $filesystem = Mockery::mock(Filesystem::class, [HydeKernel::getInstance()]) - ->makePartial()->shouldReceive('smartGlob')->once() + $filesystem = $this->setupMock(Filesystem::class, 'smartGlob') ->with('app/Actions/*BuildTask.php', 0) ->andReturn(collect($files))->getMock(); @@ -338,6 +325,16 @@ protected function resetKernelInstance(): void { HydeKernel::setInstance(new HydeKernel()); } + + protected function setupMock(string $class, string $method): Mockery\ExpectationInterface|Mockery\Expectation|Mockery\HigherOrderMessage + { + return Mockery::mock($class)->makePartial()->shouldReceive($method)->once(); + } + + protected function mockOutput(): Mockery\LegacyMockInterface|Mockery\MockInterface|OutputStyle + { + return Mockery::mock(OutputStyle::class)->makePartial(); + } } class InstantiableTestBuildTask extends BuildTask diff --git a/packages/framework/tests/Unit/BuildTaskUnitTest.php b/packages/framework/tests/Unit/BuildTaskUnitTest.php index 48c49b8bbda..7cf72e874ba 100644 --- a/packages/framework/tests/Unit/BuildTaskUnitTest.php +++ b/packages/framework/tests/Unit/BuildTaskUnitTest.php @@ -153,7 +153,7 @@ public function testCanWriteToOutput() public function testCreatedSiteFile() { - self::needsKernel(); + self::resetKernel(); $task = new BufferedTestBuildTask(); @@ -164,7 +164,7 @@ public function testCreatedSiteFile() public function testCreatedSiteFileWithAbsolutePath() { - self::needsKernel(); + self::resetKernel(); $task = new BufferedTestBuildTask(); diff --git a/packages/framework/tests/Unit/BuildWarningsTest.php b/packages/framework/tests/Unit/BuildWarningsTest.php index 5de6645c419..0d4207112a5 100644 --- a/packages/framework/tests/Unit/BuildWarningsTest.php +++ b/packages/framework/tests/Unit/BuildWarningsTest.php @@ -21,8 +21,6 @@ class BuildWarningsTest extends UnitTestCase protected function tearDown(): void { app()->forgetInstance(BuildWarnings::class); - - parent::tearDown(); } public function testGetInstance() diff --git a/packages/framework/tests/Unit/ConfigurableFeaturesUnitTest.php b/packages/framework/tests/Unit/ConfigurableFeaturesUnitTest.php index c1f578da7be..0ef3caec202 100644 --- a/packages/framework/tests/Unit/ConfigurableFeaturesUnitTest.php +++ b/packages/framework/tests/Unit/ConfigurableFeaturesUnitTest.php @@ -8,7 +8,7 @@ beforeEach(function () { $this->mockConfig(); - $this->needsKernel(); + $this->setupKernel(); }); test('has feature method returns false when feature is disabled', function (Feature $feature) { diff --git a/packages/framework/tests/Unit/CreatesNewMarkdownPostFileTest.php b/packages/framework/tests/Unit/CreatesNewMarkdownPostFileTest.php index 47b81290328..338db38c31a 100644 --- a/packages/framework/tests/Unit/CreatesNewMarkdownPostFileTest.php +++ b/packages/framework/tests/Unit/CreatesNewMarkdownPostFileTest.php @@ -5,7 +5,7 @@ namespace Hyde\Framework\Testing\Unit; use Hyde\Hyde; -use Hyde\Testing\TestCase; +use Hyde\Testing\UnitTestCase; use Illuminate\Support\Carbon; use Hyde\Framework\Actions\CreatesNewMarkdownPostFile; @@ -14,12 +14,13 @@ * * @see \Hyde\Framework\Testing\Feature\Commands\MakePostCommandTest */ -class CreatesNewMarkdownPostFileTest extends TestCase +class CreatesNewMarkdownPostFileTest extends UnitTestCase { + protected static bool $needsKernel = true; + protected static bool $needsConfig = true; + protected function setUp(): void { - parent::setUp(); - Carbon::setTestNow(Carbon::create(2024)); } diff --git a/packages/framework/tests/Unit/DataCollectionUnitTest.php b/packages/framework/tests/Unit/DataCollectionUnitTest.php index cf1c8122ffc..921d7e2c836 100644 --- a/packages/framework/tests/Unit/DataCollectionUnitTest.php +++ b/packages/framework/tests/Unit/DataCollectionUnitTest.php @@ -27,8 +27,6 @@ class DataCollectionUnitTest extends UnitTestCase protected function tearDown(): void { MockableDataCollection::tearDown(); - - parent::tearDown(); } public function testClassHasStaticSourceDirectoryProperty() @@ -58,46 +56,29 @@ public function testCanConvertCollectionToJson() public function testFindMarkdownFilesCallsProperGlobPattern() { - $filesystem = Mockery::mock(Filesystem::class, ['exists' => true]); - $filesystem->shouldReceive('glob') - ->with(Hyde::path('resources/collections/foo/*.{md}'), GLOB_BRACE) - ->once(); - - app()->instance(Filesystem::class, $filesystem); + $this->mockFilesystemFacade(['shouldReceiveGlob' => true]); DataCollection::markdown('foo')->keys()->toArray(); - $this->addToAssertionCount(Mockery::getContainer()->mockery_getExpectationCount()); - Mockery::close(); + $this->verifyMockeryExpectations(); } public function testFindMarkdownFilesWithNoFiles() { - $filesystem = Mockery::mock(Filesystem::class, [ - 'exists' => true, - 'glob' => [], - ]); - - app()->instance(Filesystem::class, $filesystem); + $this->mockFilesystemFacade(); $this->assertSame([], DataCollection::markdown('foo')->keys()->toArray()); - Mockery::close(); + $this->verifyMockeryExpectations(); } public function testFindMarkdownFilesWithFiles() { - $filesystem = Mockery::mock(Filesystem::class, [ - 'exists' => true, - 'glob' => ['bar.md'], - 'get' => 'foo', - ]); - - app()->instance(Filesystem::class, $filesystem); + $this->mockFilesystemFacade(['glob' => ['bar.md']]); $this->assertSame(['bar.md'], DataCollection::markdown('foo')->keys()->toArray()); - Mockery::close(); + $this->verifyMockeryExpectations(); } public function testStaticMarkdownHelperReturnsNewDataCollectionInstance() @@ -505,6 +486,28 @@ public function testJsonMethodThrowsExceptionForOtherReasonsThanSyntaxErrorWithC MockableDataCollection::json('foo'); } + protected function mockFilesystemFacade(array $config = []): void + { + $defaults = [ + 'exists' => true, + 'glob' => [], + 'get' => 'foo', + ]; + + $config = array_merge($defaults, $config); + + $filesystem = Mockery::mock(Filesystem::class, $config); + + if (isset($config['shouldReceiveGlob'])) { + $filesystem->shouldReceive('glob') + ->with(Hyde::path('resources/collections/foo/*.{md}'), GLOB_BRACE) + ->once() + ->andReturn($config['glob']); + } + + app()->instance(Filesystem::class, $filesystem); + } + protected function assertMarkdownCollectionStructure(array $expected, DataCollection $collection): void { $this->assertContainsOnlyInstancesOf(MarkdownDocument::class, $collection); diff --git a/packages/framework/tests/Unit/DocumentationSidebarGetActiveGroupUnitTest.php b/packages/framework/tests/Unit/DocumentationSidebarGetActiveGroupUnitTest.php index 85cfca99569..06d8f27d8cb 100644 --- a/packages/framework/tests/Unit/DocumentationSidebarGetActiveGroupUnitTest.php +++ b/packages/framework/tests/Unit/DocumentationSidebarGetActiveGroupUnitTest.php @@ -29,8 +29,6 @@ class DocumentationSidebarGetActiveGroupUnitTest extends UnitTestCase protected function setUp(): void { - parent::setUp(); - View::swap(Mockery::mock(Factory::class)->makePartial()); $this->renderData = new RenderData(); Render::swap($this->renderData); @@ -38,6 +36,11 @@ protected function setUp(): void self::mockConfig(); } + protected function tearDown(): void + { + $this->verifyMockeryExpectations(); + } + protected function createSidebar(): DocumentationSidebar { // The sidebar structure diff --git a/packages/framework/tests/Unit/Facades/AssetFacadeTest.php b/packages/framework/tests/Unit/Facades/AssetFacadeTest.php index df8344a3771..a3e504c2c19 100644 --- a/packages/framework/tests/Unit/Facades/AssetFacadeTest.php +++ b/packages/framework/tests/Unit/Facades/AssetFacadeTest.php @@ -5,14 +5,22 @@ namespace Hyde\Framework\Testing\Unit\Facades; use Hyde\Facades\Asset; +use Hyde\Testing\UnitTestCase; +use Hyde\Testing\CreatesApplication; use Hyde\Framework\Services\AssetService; -use Hyde\Testing\TestCase; /** * @covers \Hyde\Facades\Asset */ -class AssetFacadeTest extends TestCase +class AssetFacadeTest extends UnitTestCase { + use CreatesApplication; + + protected function setUp(): void + { + $this->createApplication(); + } + public function testAssetFacadeReturnsTheAssetService() { $this->assertInstanceOf(AssetService::class, Asset::getFacadeRoot()); diff --git a/packages/framework/tests/Unit/Facades/AuthorFacadeTest.php b/packages/framework/tests/Unit/Facades/AuthorFacadeTest.php index 43bc49291e2..f4e4a273561 100644 --- a/packages/framework/tests/Unit/Facades/AuthorFacadeTest.php +++ b/packages/framework/tests/Unit/Facades/AuthorFacadeTest.php @@ -18,8 +18,6 @@ class AuthorFacadeTest extends UnitTestCase protected function setUp(): void { - parent::setUp(); - static $config = null; if ($config === null) { diff --git a/packages/framework/tests/Unit/Facades/HydeFacadesAreAliasedInAppConfigTest.php b/packages/framework/tests/Unit/Facades/HydeFacadesAreAliasedInAppConfigTest.php index 132e7bda662..07efeb0a5c3 100644 --- a/packages/framework/tests/Unit/Facades/HydeFacadesAreAliasedInAppConfigTest.php +++ b/packages/framework/tests/Unit/Facades/HydeFacadesAreAliasedInAppConfigTest.php @@ -5,10 +5,17 @@ namespace Hyde\Framework\Testing\Unit\Facades; use Hyde\Hyde; -use Hyde\Testing\TestCase; +use Hyde\Testing\UnitTestCase; -class HydeFacadesAreAliasedInAppConfigTest extends TestCase +class HydeFacadesAreAliasedInAppConfigTest extends UnitTestCase { + protected static bool $needsKernel = true; + + protected function setUp(): void + { + self::mockConfig(['app' => require Hyde::path('app/config.php')]); + } + public function testAllFacadesAreAliasedInAppConfig() { $this->assertArrayHasKey('Hyde', config('app.aliases')); diff --git a/packages/framework/tests/Unit/FilesystemFacadeUnitTest.php b/packages/framework/tests/Unit/FilesystemFacadeUnitTest.php new file mode 100644 index 00000000000..8aa29c7bc7f --- /dev/null +++ b/packages/framework/tests/Unit/FilesystemFacadeUnitTest.php @@ -0,0 +1,398 @@ +verifyMockeryExpectations(); + } + + public function testGetContents() + { + $this->createExpectation('get', 'string', Hyde::path('path')); + + Filesystem::getContents('path'); + } + + public function testGetContentsWithLock() + { + $this->createExpectation('get', 'string', Hyde::path('path'), true); + + Filesystem::getContents('path', true); + } + + public function testPutContents() + { + $this->createExpectation('put', true, Hyde::path('path'), 'string'); + + Filesystem::putContents('path', 'string'); + } + + public function testPutContentsWithLock() + { + $this->createExpectation('put', true, Hyde::path('path'), 'string', true); + + Filesystem::putContents('path', 'string', true); + } + + public function testExists() + { + $this->createExpectation('exists', true, Hyde::path('path')); + + Filesystem::exists('path'); + } + + public function testMissing() + { + $this->createExpectation('missing', true, Hyde::path('path')); + + Filesystem::missing('path'); + } + + public function testGet() + { + $this->createExpectation('get', 'string', Hyde::path('path')); + + Filesystem::get('path'); + } + + public function testSharedGet() + { + $this->createExpectation('sharedGet', 'string', Hyde::path('path')); + + Filesystem::sharedGet('path'); + } + + public function testGetRequire() + { + $this->createExpectation('getRequire', 'string', Hyde::path('path')); + + Filesystem::getRequire('path'); + } + + public function testRequireOnce() + { + $this->createExpectation('requireOnce', 'string', Hyde::path('path')); + + Filesystem::requireOnce('path'); + } + + public function testLines() + { + $this->createExpectation('lines', new LazyCollection(), Hyde::path('path')); + + Filesystem::lines('path'); + } + + public function testHash() + { + $this->createExpectation('hash', 'string', Hyde::path('path')); + + Filesystem::hash('path'); + } + + public function testPut() + { + $this->createExpectation('put', 10, Hyde::path('path'), 'contents'); + + Filesystem::put('path', 'contents'); + } + + public function testReplace() + { + $this->createExpectation('replace', null, Hyde::path('path'), 'content'); + + Filesystem::replace('path', 'content'); + } + + public function testReplaceInFile() + { + $this->createExpectation('replaceInFile', null, 'search', 'replace', Hyde::path('path')); + + Filesystem::replaceInFile('search', 'replace', 'path'); + } + + public function testPrepend() + { + $this->createExpectation('prepend', 10, Hyde::path('path'), 'data'); + + Filesystem::prepend('path', 'data'); + } + + public function testAppend() + { + $this->createExpectation('append', 10, Hyde::path('path'), 'data'); + + Filesystem::append('path', 'data'); + } + + public function testChmod() + { + $this->createExpectation('chmod', null, Hyde::path('path'), 0755); + + Filesystem::chmod('path', 0755); + } + + public function testDelete() + { + $this->createExpectation('delete', true, Hyde::path('path')); + + Filesystem::delete('path'); + } + + public function testDeleteWithArray() + { + $this->createExpectation('delete', true, [Hyde::path('path'), Hyde::path('another')]); + + Filesystem::delete(['path', 'another']); + } + + public function testMove() + { + $this->createExpectation('move', true, Hyde::path('path'), Hyde::path('target')); + + Filesystem::move('path', 'target'); + } + + public function testCopy() + { + $this->createExpectation('copy', true, Hyde::path('path'), Hyde::path('target')); + + Filesystem::copy('path', 'target'); + } + + public function testLink() + { + $this->createExpectation('link', true, Hyde::path('target'), Hyde::path('link')); + + Filesystem::link('target', 'link'); + } + + public function testRelativeLink() + { + $this->createExpectation('relativeLink', true, Hyde::path('target'), Hyde::path('link')); + + Filesystem::relativeLink('target', 'link'); + } + + public function testName() + { + $this->createExpectation('name', 'string', Hyde::path('path')); + + Filesystem::name('path'); + } + + public function testBasename() + { + $this->createExpectation('basename', 'string', Hyde::path('path')); + + Filesystem::basename('path'); + } + + public function testDirname() + { + $this->createExpectation('dirname', 'string', Hyde::path('path')); + + Filesystem::dirname('path'); + } + + public function testExtension() + { + $this->createExpectation('extension', 'string', Hyde::path('path')); + + Filesystem::extension('path'); + } + + public function testGuessExtension() + { + $this->createExpectation('guessExtension', 'string', Hyde::path('path')); + + Filesystem::guessExtension('path'); + } + + public function testType() + { + $this->createExpectation('type', 'string', Hyde::path('path')); + + Filesystem::type('path'); + } + + public function testMimeType() + { + $this->createExpectation('mimeType', 'string', Hyde::path('path')); + + Filesystem::mimeType('path'); + } + + public function testSize() + { + $this->createExpectation('size', 10, Hyde::path('path')); + + Filesystem::size('path'); + } + + public function testLastModified() + { + $this->createExpectation('lastModified', 10, Hyde::path('path')); + + Filesystem::lastModified('path'); + } + + public function testIsDirectory() + { + $this->createExpectation('isDirectory', true, Hyde::path('directory')); + + Filesystem::isDirectory('directory'); + } + + public function testIsEmptyDirectory() + { + $this->createExpectation('isEmptyDirectory', true, Hyde::path('directory')); + + Filesystem::isEmptyDirectory('directory'); + } + + public function testIsReadable() + { + $this->createExpectation('isReadable', true, Hyde::path('path')); + + Filesystem::isReadable('path'); + } + + public function testIsWritable() + { + $this->createExpectation('isWritable', true, Hyde::path('path')); + + Filesystem::isWritable('path'); + } + + public function testHasSameHash() + { + $this->createExpectation('hasSameHash', true, Hyde::path('firstFile'), Hyde::path('secondFile')); + + Filesystem::hasSameHash('firstFile', 'secondFile'); + } + + public function testIsFile() + { + $this->createExpectation('isFile', true, Hyde::path('file')); + + Filesystem::isFile('file'); + } + + public function testGlob() + { + $this->createExpectation('glob', [], Hyde::path('pattern')); + + Filesystem::glob('pattern'); + } + + public function testFiles() + { + $this->createExpectation('files', [], Hyde::path('directory')); + + Filesystem::files('directory'); + } + + public function testAllFiles() + { + $this->createExpectation('allFiles', [], Hyde::path('directory')); + + Filesystem::allFiles('directory'); + } + + public function testDirectories() + { + $this->createExpectation('directories', [], Hyde::path('directory')); + + Filesystem::directories('directory'); + } + + public function testEnsureDirectoryExists() + { + $this->createExpectation('ensureDirectoryExists', null, Hyde::path('path')); + + Filesystem::ensureDirectoryExists('path'); + } + + public function testMakeDirectory() + { + $this->createExpectation('makeDirectory', true, Hyde::path('path')); + + Filesystem::makeDirectory('path'); + } + + public function testMoveDirectory() + { + $this->createExpectation('moveDirectory', true, Hyde::path('from'), Hyde::path('to')); + + Filesystem::moveDirectory('from', 'to'); + } + + public function testCopyDirectory() + { + $this->createExpectation('copyDirectory', true, Hyde::path('directory'), Hyde::path('destination')); + + Filesystem::copyDirectory('directory', 'destination'); + } + + public function testDeleteDirectory() + { + $this->createExpectation('deleteDirectory', true, Hyde::path('directory')); + + Filesystem::deleteDirectory('directory'); + } + + public function testDeleteDirectories() + { + $this->createExpectation('deleteDirectories', true, Hyde::path('directory')); + + Filesystem::deleteDirectories('directory'); + } + + public function testCleanDirectory() + { + $this->createExpectation('cleanDirectory', true, Hyde::path('directory')); + + Filesystem::cleanDirectory('directory'); + } + + public function testSmartGlob() + { + $this->createExpectation('glob', [ + Hyde::path('foo'), + Hyde::path('bar'), + Hyde::path('baz'), + ], Hyde::path('pattern/*.md'), 0); + + $expected = Collection::make(['foo', 'bar', 'baz']); + $actual = Filesystem::smartGlob('pattern/*.md'); + + $this->assertEquals($expected, $actual); + $this->assertSame($expected->all(), $actual->all()); + } + + protected function createExpectation(string $method, mixed $returns, ...$args): void + { + $this->mockFilesystem()->shouldReceive($method)->withArgs($args)->once()->andReturn($returns); + } +} diff --git a/packages/framework/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php b/packages/framework/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php index bc3a1f0061f..fa7ed72ff3a 100644 --- a/packages/framework/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php +++ b/packages/framework/tests/Unit/Foundation/HyperlinksUrlPathHelpersTest.php @@ -7,19 +7,23 @@ use BadMethodCallException; use Hyde\Foundation\HydeKernel; use Hyde\Foundation\Kernel\Hyperlinks; -use Hyde\Testing\TestCase; +use Hyde\Testing\FluentTestingHelpers; +use Hyde\Testing\UnitTestCase; /** * @covers \Hyde\Foundation\Kernel\Hyperlinks */ -class HyperlinksUrlPathHelpersTest extends TestCase +class HyperlinksUrlPathHelpersTest extends UnitTestCase { + use FluentTestingHelpers; + + protected static bool $needsKernel = true; + protected static bool $needsConfig = true; + protected Hyperlinks $class; protected function setUp(): void { - parent::setUp(); - $this->class = new Hyperlinks(HydeKernel::getInstance()); } @@ -117,7 +121,7 @@ public function testQualifiedUrlHelperWithAlreadyQualifiedUrl() public function testQualifiedUrlHelperWithAlreadyQualifiedUrlWhenSiteUrlIsSet() { - $this->app['config']->set(['hyde.url' => 'https://example.com']); + self::mockConfig(['hyde.url' => 'https://example.com']); $this->assertSame('https://example.com/foo', $this->class->url('https://example.com/foo')); $this->assertSame('http://localhost/foo', $this->class->url('http://localhost/foo')); @@ -125,7 +129,7 @@ public function testQualifiedUrlHelperWithAlreadyQualifiedUrlWhenSiteUrlIsSet() public function testQualifiedUrlHelperWithAlreadyQualifiedUrlWhenSiteUrlIsSetToSomethingElse() { - $this->app['config']->set(['hyde.url' => 'my-site.com']); + self::mockConfig(['hyde.url' => 'my-site.com']); $this->assertSame('https://example.com/foo', $this->class->url('https://example.com/foo')); $this->assertSame('http://localhost/foo', $this->class->url('http://localhost/foo')); @@ -140,7 +144,7 @@ public function testQualifiedUrlHelperWithAlreadyQualifiedUrlStillFormatsPath() public function testQualifiedUrlHelperWithAlreadyQualifiedUrlStillFormatsPathWhenSiteUrlIsSet() { - $this->app['config']->set(['hyde.url' => 'https://example.com']); + self::mockConfig(['hyde.url' => 'https://example.com']); $this->assertSame('https://example.com/foo/bar.html', $this->class->url('https://example.com/foo/bar.html')); $this->assertSame('http://localhost/foo/bar.html', $this->class->url('http://localhost/foo/bar.html')); $this->assertSame('http://localhost/foo/bar', $this->class->url('http://localhost/foo/bar/')); @@ -148,7 +152,7 @@ public function testQualifiedUrlHelperWithAlreadyQualifiedUrlStillFormatsPathWhe public function testQualifiedUrlHelperWithAlreadyQualifiedUrlStillFormatsPathWithPrettyUrls() { - $this->app['config']->set(['hyde.url' => 'https://example.com', 'hyde.pretty_urls' => true]); + self::mockConfig(['hyde.url' => 'https://example.com', 'hyde.pretty_urls' => true]); $this->assertSame('https://example.com/foo/bar', $this->class->url('https://example.com/foo/bar.html')); $this->assertSame('http://localhost/foo/bar', $this->class->url('http://localhost/foo/bar.html')); $this->assertSame('http://localhost/foo/bar', $this->class->url('http://localhost/foo/bar/')); @@ -176,7 +180,7 @@ public function testHelperFallsBackToRelativeLinksWhenNoSiteUrlIsSet() public function testHelperFallsBackToPrettyRelativeLinksWhenNoSiteUrlIsSetAndPrettyUrlsAreEnabled() { - config(['hyde.url' => '', 'hyde.pretty_urls' => true]); + self::mockConfig(['hyde.url' => '', 'hyde.pretty_urls' => true]); $this->assertSame('/', $this->class->url('index.html')); $this->assertSame('foo', $this->class->url('foo.html')); @@ -196,7 +200,7 @@ public function testHelperFallsBackToRelativeLinksWhenSiteUrlIsSetToLocalhost() public function testHelperFallsBackToPrettyRelativeLinksWhenSiteUrlIsSetToLocalhostAndPrettyUrlsAreEnabled() { - config(['hyde.url' => 'http://localhost', 'hyde.pretty_urls' => true]); + self::mockConfig(['hyde.url' => 'http://localhost', 'hyde.pretty_urls' => true]); $this->assertSame('/', $this->class->url('index.html')); $this->assertSame('foo', $this->class->url('foo.html')); @@ -213,7 +217,7 @@ public function testHelperReturnsExpectedStringWhenSiteUrlIsSet() public function testHelperReturnsExpectedStringWhenPrettyUrlsAreEnabled() { - config(['hyde.url' => 'https://example.com', 'hyde.pretty_urls' => true]); + self::mockConfig(['hyde.url' => 'https://example.com', 'hyde.pretty_urls' => true]); $this->assertSame('https://example.com', $this->class->url('index.html')); $this->assertSame('https://example.com/foo', $this->class->url('foo.html')); diff --git a/packages/framework/tests/Unit/HtmlTestingSupportMetaTest.php b/packages/framework/tests/Unit/HtmlTestingSupportMetaTest.php index 5b6ec6f42da..3c109d7473b 100644 --- a/packages/framework/tests/Unit/HtmlTestingSupportMetaTest.php +++ b/packages/framework/tests/Unit/HtmlTestingSupportMetaTest.php @@ -31,9 +31,7 @@ class HtmlTestingSupportMetaTest extends UnitTestCase protected function setUp(): void { - parent::setUp(); - - self::needsKernel(); + self::resetKernel(); $this->html ??= file_get_contents(Hyde::vendorPath('resources/views/homepages/welcome.blade.php')); } diff --git a/packages/framework/tests/Unit/HydeFileHelpersTest.php b/packages/framework/tests/Unit/HydeFileHelpersTest.php index 7bb1974bf1d..d373c9b2e3f 100644 --- a/packages/framework/tests/Unit/HydeFileHelpersTest.php +++ b/packages/framework/tests/Unit/HydeFileHelpersTest.php @@ -4,16 +4,29 @@ namespace Hyde\Framework\Testing\Unit; +use Mockery; +use Illuminate\View\Factory; +use Hyde\Testing\UnitTestCase; use Hyde\Foundation\Facades\Routes; use Hyde\Hyde; use Hyde\Support\Facades\Render; -use Hyde\Testing\TestCase; +use Illuminate\Support\Facades\View; /** * @covers \Hyde\Foundation\HydeKernel */ -class HydeFileHelpersTest extends TestCase +class HydeFileHelpersTest extends UnitTestCase { + protected static bool $needsKernel = true; + protected static bool $needsConfig = true; + + protected function setUp(): void + { + self::mockRender(); + + View::swap(Mockery::mock(Factory::class)->makePartial()); + } + public function testCurrentPageReturnsCurrentPageViewProperty() { Render::share('routeKey', 'foo'); diff --git a/packages/framework/tests/Unit/HydeHelperFacadeTest.php b/packages/framework/tests/Unit/HydeHelperFacadeTest.php index d6a3aef3a23..f8b5d2df5c8 100644 --- a/packages/framework/tests/Unit/HydeHelperFacadeTest.php +++ b/packages/framework/tests/Unit/HydeHelperFacadeTest.php @@ -7,32 +7,28 @@ use Hyde\Enums\Feature; use Hyde\Facades\Features; use Hyde\Hyde; -use Hyde\Testing\TestCase; +use Hyde\Testing\UnitTestCase; /** * @covers \Hyde\Foundation\HydeKernel */ -class HydeHelperFacadeTest extends TestCase +class HydeHelperFacadeTest extends UnitTestCase { + protected static bool $needsKernel = true; + protected static bool $needsConfig = true; + public function testFeaturesFacadeReturnsInstanceOfFeaturesClass() { - $this->assertInstanceOf( - Features::class, - Hyde::features() - ); + $this->assertInstanceOf(Features::class, Hyde::features()); } public function testFeaturesFacadeCanBeUsedToCallStaticMethodsOnFeaturesClass() { - $this->assertTrue( - Hyde::features()->hasMarkdownPosts() - ); + $this->assertTrue(Hyde::features()->hasMarkdownPosts()); } public function testHydeHasFeatureShorthandCallsStaticMethodOnFeaturesClass() { - $this->assertTrue( - Hyde::hasFeature(Feature::MarkdownPosts) - ); + $this->assertTrue(Hyde::hasFeature(Feature::MarkdownPosts)); } } diff --git a/packages/framework/tests/Unit/HydePageDataFactoryTest.php b/packages/framework/tests/Unit/HydePageDataFactoryTest.php index 8c8f2a8676a..4590a54a64d 100644 --- a/packages/framework/tests/Unit/HydePageDataFactoryTest.php +++ b/packages/framework/tests/Unit/HydePageDataFactoryTest.php @@ -22,8 +22,6 @@ class HydePageDataFactoryTest extends UnitTestCase protected function tearDown(): void { self::mockConfig(); - - parent::tearDown(); } public function testCanConstruct() diff --git a/packages/framework/tests/Unit/IncludesFacadeUnitTest.php b/packages/framework/tests/Unit/IncludesFacadeUnitTest.php index 6dac17db2f5..a47609e4c21 100644 --- a/packages/framework/tests/Unit/IncludesFacadeUnitTest.php +++ b/packages/framework/tests/Unit/IncludesFacadeUnitTest.php @@ -8,6 +8,7 @@ use Closure; use Hyde\Hyde; use Hyde\Support\Includes; +use AllowDynamicProperties; use Hyde\Testing\UnitTestCase; use Hyde\Support\Facades\Render; use Illuminate\Support\HtmlString; @@ -21,6 +22,7 @@ * * @see \Hyde\Framework\Testing\Feature\IncludesFacadeTest */ +#[AllowDynamicProperties] class IncludesFacadeUnitTest extends UnitTestCase { use MocksKernelFeatures; @@ -30,8 +32,6 @@ class IncludesFacadeUnitTest extends UnitTestCase protected function setUp(): void { - parent::setUp(); - Blade::swap(Mockery::mock()); $this->setupTestKernel(); @@ -42,8 +42,6 @@ protected function setUp(): void protected function tearDown(): void { Mockery::close(); - - parent::tearDown(); } public function testPathReturnsTheIncludesDirectory() @@ -66,7 +64,7 @@ public function testGetReturnsPartial() $filename = 'foo.txt'; $expected = 'foo bar'; - $this->mockFilesystem(function ($filesystem) use ($expected, $filename) { + $this->mockFilesystemFromClosure(function ($filesystem) use ($expected, $filename) { $filesystem->shouldReceive('exists')->with($this->includesPath($filename))->andReturn(true); $filesystem->shouldReceive('get')->with($this->includesPath($filename))->andReturn($expected); }); @@ -79,7 +77,7 @@ public function testGetReturnsDefaultValueWhenNotFound() $filename = 'foo.txt'; $default = 'default'; - $this->mockFilesystem(function ($filesystem) use ($filename) { + $this->mockFilesystemFromClosure(function ($filesystem) use ($filename) { $filesystem->shouldReceive('exists')->with($this->includesPath($filename))->andReturn(false); }); @@ -93,7 +91,7 @@ public function testGetNormalizesNestedIdentifiers() $normalized = 'bar.txt'; $expected = 'foo bar'; - $this->mockFilesystem(function ($filesystem) use ($expected, $normalized) { + $this->mockFilesystemFromClosure(function ($filesystem) use ($expected, $normalized) { $filesystem->shouldReceive('exists')->with($this->includesPath($normalized))->andReturn(true); $filesystem->shouldReceive('get')->with($this->includesPath($normalized))->andReturn($expected); }); @@ -106,7 +104,7 @@ public function testHtmlReturnsRenderedPartial() $filename = 'foo.html'; $expected = '

foo bar

'; - $this->mockFilesystem(function ($filesystem) use ($expected, $filename) { + $this->mockFilesystemFromClosure(function ($filesystem) use ($expected, $filename) { $filesystem->shouldReceive('exists')->with($this->includesPath($filename))->andReturn(true); $filesystem->shouldReceive('get')->with($this->includesPath($filename))->andReturn($expected); }); @@ -119,7 +117,7 @@ public function testHtmlReturnsDefaultValueWhenNotFound() $filename = 'foo.html'; $default = '

default

'; - $this->mockFilesystem(function ($filesystem) use ($filename) { + $this->mockFilesystemFromClosure(function ($filesystem) use ($filename) { $filesystem->shouldReceive('exists')->with($this->includesPath($filename))->andReturn(false); }); @@ -129,7 +127,7 @@ public function testHtmlReturnsDefaultValueWhenNotFound() public function testHtmlWithAndWithoutExtension() { - $this->mockFilesystem(function ($filesystem) { + $this->mockFilesystemFromClosure(function ($filesystem) { $filename = 'foo.html'; $content = '

foo bar

'; @@ -145,7 +143,7 @@ public function testMarkdownReturnsRenderedPartial() $filename = 'foo.md'; $expected = '

foo bar

'; - $this->mockFilesystem(function ($filesystem) use ($filename) { + $this->mockFilesystemFromClosure(function ($filesystem) use ($filename) { $content = '# foo bar'; $filesystem->shouldReceive('exists')->with($this->includesPath($filename))->andReturn(true); @@ -161,7 +159,7 @@ public function testMarkdownReturnsRenderedDefaultValueWhenNotFound() $default = '# default'; $expected = '

default

'; - $this->mockFilesystem(function ($filesystem) use ($filename) { + $this->mockFilesystemFromClosure(function ($filesystem) use ($filename) { $filesystem->shouldReceive('exists')->with($this->includesPath($filename))->andReturn(false); }); @@ -173,7 +171,7 @@ public function testMarkdownWithAndWithoutExtension() { $expected = '

foo bar

'; - $this->mockFilesystem(function ($filesystem) { + $this->mockFilesystemFromClosure(function ($filesystem) { $content = '# foo bar'; $filename = 'foo.md'; @@ -191,7 +189,7 @@ public function testBladeReturnsRenderedPartial() $filename = 'foo.blade.php'; $expected = 'foo bar'; - $this->mockFilesystem(function ($filesystem) use ($expected, $filename) { + $this->mockFilesystemFromClosure(function ($filesystem) use ($expected, $filename) { $content = '{{ "foo bar" }}'; $filesystem->shouldReceive('exists')->with($this->includesPath($filename))->andReturn(true); @@ -205,7 +203,7 @@ public function testBladeReturnsRenderedPartial() public function testBladeWithAndWithoutExtension() { - $this->mockFilesystem(function ($filesystem) { + $this->mockFilesystemFromClosure(function ($filesystem) { $expected = 'foo bar'; $content = '{{ "foo bar" }}'; $filename = 'foo.blade.php'; @@ -225,7 +223,7 @@ public function testBladeReturnsDefaultValueWhenNotFound() $default = '{{ "default" }}'; $expected = 'default'; - $this->mockFilesystem(function ($filesystem) use ($default, $expected, $filename) { + $this->mockFilesystemFromClosure(function ($filesystem) use ($default, $expected, $filename) { $filesystem->shouldReceive('exists')->with($this->includesPath($filename))->andReturn(false); Blade::shouldReceive('render')->with($default)->andReturn($expected); @@ -235,7 +233,7 @@ public function testBladeReturnsDefaultValueWhenNotFound() $this->assertHtmlStringIsSame($expected, Includes::blade($filename, $default)); } - protected function mockFilesystem(Closure $config): void + protected function mockFilesystemFromClosure(Closure $config): void { $filesystem = Mockery::mock(Filesystem::class); diff --git a/packages/framework/tests/Unit/InteractsWithDirectoriesConcernTest.php b/packages/framework/tests/Unit/InteractsWithDirectoriesConcernTest.php index d788f101506..9d23ff0bd50 100644 --- a/packages/framework/tests/Unit/InteractsWithDirectoriesConcernTest.php +++ b/packages/framework/tests/Unit/InteractsWithDirectoriesConcernTest.php @@ -4,80 +4,89 @@ namespace Hyde\Framework\Testing\Unit; +use Hyde\Testing\UnitTestCase; use Hyde\Framework\Concerns\InteractsWithDirectories; use Hyde\Hyde; -use Hyde\Testing\TestCase; -use Illuminate\Support\Facades\File; /** * @covers \Hyde\Framework\Concerns\InteractsWithDirectories */ -class InteractsWithDirectoriesConcernTest extends TestCase +class InteractsWithDirectoriesConcernTest extends UnitTestCase { use InteractsWithDirectories; - protected function setUp(): void - { - parent::setUp(); + protected static bool $needsKernel = true; - File::deleteDirectory(Hyde::path('foo')); - } + /** @var \Illuminate\Filesystem\Filesystem&\Mockery\MockInterface */ + protected $filesystem; - protected function tearDown(): void + protected function setUp(): void { - File::deleteDirectory(Hyde::path('foo')); - - parent::tearDown(); + $this->filesystem = $this->mockFilesystemStrict(); } - public function testMethodsCanBeCalledStatically() + protected function tearDown(): void { - static::needsDirectory('foo'); - $this->assertDirectoryExists(Hyde::path('foo')); - - static::needsDirectories(['foo']); - $this->assertDirectoryExists(Hyde::path('foo')); + $this->verifyMockeryExpectations(); } public function testNeedsDirectoryCreatesTheDirectory() { + $this->filesystem->expects('exists')->with(Hyde::path('foo'))->andReturnFalse(); + $this->filesystem->expects('makeDirectory')->with(Hyde::path('foo'), 0755, true); + $this->needsDirectory('foo'); - $this->assertDirectoryExists(Hyde::path('foo')); } public function testNeedsDirectoryCreatesTheDirectoryRecursively() { + $this->filesystem->expects('exists')->with(Hyde::path('foo/bar/baz'))->andReturnFalse(); + $this->filesystem->expects('makeDirectory')->with(Hyde::path('foo/bar/baz'), 0755, true); + $this->needsDirectory('foo/bar/baz'); - $this->assertDirectoryExists(Hyde::path('foo/bar/baz')); } public function testNeedsDirectoryHandlesExistingDirectory() { + $this->filesystem->expects('exists')->with(Hyde::path('foo'))->andReturnTrue()->twice(); + $this->filesystem->expects('makeDirectory')->never(); + $this->needsDirectory('foo'); $this->needsDirectory('foo'); - - $this->assertDirectoryExists(Hyde::path('foo')); } public function testNeedsDirectoriesCreatesSingleDirectory() { + $this->filesystem->expects('exists')->with(Hyde::path('foo'))->andReturnFalse(); + $this->filesystem->expects('makeDirectory')->with(Hyde::path('foo'), 0755, true); + $this->needsDirectories(['foo']); - $this->assertDirectoryExists(Hyde::path('foo')); } public function testNeedsDirectoriesCreatesMultipleDirectories() { - $this->needsDirectories(['foo', 'bar']); - - $this->assertDirectoryExists(Hyde::path('foo')); - $this->assertDirectoryExists(Hyde::path('bar')); + $this->filesystem->expects('exists')->with(Hyde::path('foo'))->andReturnFalse(); + $this->filesystem->expects('exists')->with(Hyde::path('bar'))->andReturnFalse(); + $this->filesystem->expects('makeDirectory')->with(Hyde::path('foo'), 0755, true); + $this->filesystem->expects('makeDirectory')->with(Hyde::path('bar'), 0755, true); - File::deleteDirectory(Hyde::path('bar')); + $this->needsDirectories(['foo', 'bar']); } public function testNeedsParentDirectoryCreatesDirectoryForTheParentFile() { + $this->filesystem->expects('exists')->with(Hyde::path('foo/bar'))->andReturnFalse(); + $this->filesystem->expects('makeDirectory')->with(Hyde::path('foo/bar'), 0755, true); + $this->needsParentDirectory(Hyde::path('foo/bar/baz.txt')); - $this->assertDirectoryExists(Hyde::path('foo/bar')); + } + + public function testMethodsCanBeCalledStatically() + { + $this->filesystem->expects('exists')->with(Hyde::path('foo'))->andReturnFalse()->twice(); + $this->filesystem->expects('makeDirectory')->with(Hyde::path('foo'), 0755, true)->twice(); + + static::needsDirectory('foo'); + static::needsDirectories(['foo']); } } diff --git a/packages/framework/tests/Unit/NavigationDataFactoryUnitTest.php b/packages/framework/tests/Unit/NavigationDataFactoryUnitTest.php index bdbca3f172e..f60404da717 100644 --- a/packages/framework/tests/Unit/NavigationDataFactoryUnitTest.php +++ b/packages/framework/tests/Unit/NavigationDataFactoryUnitTest.php @@ -19,7 +19,7 @@ class NavigationDataFactoryUnitTest extends UnitTestCase { protected function setUp(): void { - self::needsKernel(); + self::resetKernel(); self::mockConfig(); } diff --git a/packages/framework/tests/Unit/NavigationGroupTest.php b/packages/framework/tests/Unit/NavigationGroupTest.php index a9ad9646633..2b9483c2f72 100644 --- a/packages/framework/tests/Unit/NavigationGroupTest.php +++ b/packages/framework/tests/Unit/NavigationGroupTest.php @@ -20,7 +20,7 @@ class NavigationGroupTest extends UnitTestCase { public static function setUpBeforeClass(): void { - self::needsKernel(); + self::setupKernel(); self::mockConfig(); } diff --git a/packages/framework/tests/Unit/NavigationItemTest.php b/packages/framework/tests/Unit/NavigationItemTest.php index 22742802644..235cc81abe1 100644 --- a/packages/framework/tests/Unit/NavigationItemTest.php +++ b/packages/framework/tests/Unit/NavigationItemTest.php @@ -25,18 +25,9 @@ */ class NavigationItemTest extends UnitTestCase { - public static function setUpBeforeClass(): void - { - self::$hasSetUpKernel = false; - - self::needsKernel(); - self::mockConfig(); - } - - protected function setUp(): void - { - Render::swap(new RenderData()); - } + protected static bool $needsKernel = true; + protected static bool $needsConfig = true; + protected static bool $needsRender = true; public function testConstruct() { diff --git a/packages/framework/tests/Unit/NavigationMenuConfigurationBuilderTest.php b/packages/framework/tests/Unit/NavigationMenuConfigurationBuilderTest.php index cde1e6c4100..2a7fb3a1f24 100644 --- a/packages/framework/tests/Unit/NavigationMenuConfigurationBuilderTest.php +++ b/packages/framework/tests/Unit/NavigationMenuConfigurationBuilderTest.php @@ -16,8 +16,6 @@ class NavigationMenuConfigurationBuilderTest extends UnitTestCase protected function setUp(): void { - parent::setUp(); - $this->builder = new NavigationMenuConfigurationBuilder(); } diff --git a/packages/framework/tests/Unit/NumericalPageOrderingHelperUnitTest.php b/packages/framework/tests/Unit/NumericalPageOrderingHelperUnitTest.php index 08c4416bd0d..e9aedb62394 100644 --- a/packages/framework/tests/Unit/NumericalPageOrderingHelperUnitTest.php +++ b/packages/framework/tests/Unit/NumericalPageOrderingHelperUnitTest.php @@ -278,7 +278,7 @@ public function testHasNumericalPrefixOnlyReturnsTrueIfLastIdentifierPartIsNumer public static function pageTypeProvider(): array { - self::needsKernel(); + self::setupKernel(); self::mockConfig(); return array_combine( diff --git a/packages/framework/tests/Unit/Pages/PageModelGetAllFilesHelperTest.php b/packages/framework/tests/Unit/Pages/PageModelGetAllFilesHelperTest.php index 8ccd211d324..6ca5e43d91f 100644 --- a/packages/framework/tests/Unit/Pages/PageModelGetAllFilesHelperTest.php +++ b/packages/framework/tests/Unit/Pages/PageModelGetAllFilesHelperTest.php @@ -4,59 +4,85 @@ namespace Hyde\Framework\Testing\Unit\Pages; -use Hyde\Facades\Filesystem; +use Hyde\Hyde; use Hyde\Pages\BladePage; +use Hyde\Testing\UnitTestCase; use Hyde\Pages\DocumentationPage; use Hyde\Pages\MarkdownPage; use Hyde\Pages\MarkdownPost; -use Hyde\Testing\TestCase; +use Mockery\ExpectationInterface; /** * @see \Hyde\Pages\Concerns\HydePage::files() */ -class PageModelGetAllFilesHelperTest extends TestCase +class PageModelGetAllFilesHelperTest extends UnitTestCase { + protected static bool $needsConfig = true; + + /** @var \Illuminate\Filesystem\Filesystem&\Mockery\MockInterface */ + protected $filesystem; + + protected function setUp(): void + { + self::setupKernel(); + + $this->filesystem = $this->mockFilesystemStrict() + ->shouldReceive('missing')->withAnyArgs()->andReturn(false)->byDefault() + ->shouldReceive('get')->withAnyArgs()->andReturn('foo')->byDefault() + ->shouldReceive('glob')->once()->with(Hyde::path('_pages/{*,**/*}.html'), GLOB_BRACE)->andReturn([])->byDefault() + ->shouldReceive('glob')->once()->with(Hyde::path('_pages/{*,**/*}.blade.php'), GLOB_BRACE)->andReturn([])->byDefault() + ->shouldReceive('glob')->once()->with(Hyde::path('_pages/{*,**/*}.md'), GLOB_BRACE)->andReturn([])->byDefault() + ->shouldReceive('glob')->once()->with(Hyde::path('_posts/{*,**/*}.md'), GLOB_BRACE)->andReturn([])->byDefault() + ->shouldReceive('glob')->once()->with(Hyde::path('_docs/{*,**/*}.md'), GLOB_BRACE)->andReturn([])->byDefault(); + } + + protected function tearDown(): void + { + $this->verifyMockeryExpectations(); + } + public function testBladePageGetHelperReturnsBladePageArray() { + $this->shouldReceiveGlob('_pages/{*,**/*}.blade.php')->andReturn(['_pages/test-page.blade.php']); + $array = BladePage::files(); - $this->assertCount(2, $array); + $this->assertCount(1, $array); $this->assertIsArray($array); - $this->assertEquals(['404', 'index'], $array); + $this->assertEquals(['test-page'], $array); } public function testMarkdownPageGetHelperReturnsMarkdownPageArray() { - Filesystem::touch('_pages/test-page.md'); + $this->shouldReceiveGlob('_pages/{*,**/*}.md')->andReturn(['_pages/test-page.md']); $array = MarkdownPage::files(); $this->assertCount(1, $array); $this->assertIsArray($array); $this->assertEquals(['test-page'], $array); - - Filesystem::unlink('_pages/test-page.md'); } public function testMarkdownPostGetHelperReturnsMarkdownPostArray() { - Filesystem::touch('_posts/test-post.md'); + $this->shouldReceiveGlob('_posts/{*,**/*}.md')->andReturn(['_posts/test-post.md']); $array = MarkdownPost::files(); $this->assertCount(1, $array); $this->assertIsArray($array); $this->assertEquals(['test-post'], $array); - - Filesystem::unlink('_posts/test-post.md'); } public function testDocumentationPageGetHelperReturnsDocumentationPageArray() { - Filesystem::touch('_docs/test-page.md'); + $this->shouldReceiveGlob('_docs/{*,**/*}.md')->andReturn(['_docs/test-page.md']); $array = DocumentationPage::files(); $this->assertCount(1, $array); $this->assertIsArray($array); $this->assertEquals(['test-page'], $array); + } - Filesystem::unlink('_docs/test-page.md'); + protected function shouldReceiveGlob(string $withPath): ExpectationInterface + { + return $this->filesystem->shouldReceive('glob')->once()->with(Hyde::path($withPath), GLOB_BRACE); } } diff --git a/packages/framework/tests/Unit/Pages/PageModelGetHelperTest.php b/packages/framework/tests/Unit/Pages/PageModelGetHelperTest.php index e04c4838a17..de9e3acb239 100644 --- a/packages/framework/tests/Unit/Pages/PageModelGetHelperTest.php +++ b/packages/framework/tests/Unit/Pages/PageModelGetHelperTest.php @@ -4,64 +4,93 @@ namespace Hyde\Framework\Testing\Unit\Pages; -use Hyde\Facades\Filesystem; +use Hyde\Hyde; use Hyde\Pages\BladePage; use Hyde\Pages\DocumentationPage; use Hyde\Pages\MarkdownPage; use Hyde\Pages\MarkdownPost; -use Hyde\Testing\TestCase; +use Hyde\Testing\UnitTestCase; +use Mockery\ExpectationInterface; use Illuminate\Support\Collection; /** * @see \Hyde\Pages\Concerns\HydePage::all() */ -class PageModelGetHelperTest extends TestCase +class PageModelGetHelperTest extends UnitTestCase { + protected static bool $needsConfig = true; + + /** @var \Illuminate\Filesystem\Filesystem&\Mockery\MockInterface */ + protected $filesystem; + + protected function setUp(): void + { + self::setupKernel(); + + $this->filesystem = $this->mockFilesystemStrict() + ->shouldReceive('glob')->once()->with(Hyde::path('_pages/{*,**/*}.html'), GLOB_BRACE)->andReturn([])->byDefault() + ->shouldReceive('glob')->once()->with(Hyde::path('_pages/{*,**/*}.blade.php'), GLOB_BRACE)->andReturn([])->byDefault() + ->shouldReceive('glob')->once()->with(Hyde::path('_pages/{*,**/*}.md'), GLOB_BRACE)->andReturn([])->byDefault() + ->shouldReceive('glob')->once()->with(Hyde::path('_posts/{*,**/*}.md'), GLOB_BRACE)->andReturn([])->byDefault() + ->shouldReceive('glob')->once()->with(Hyde::path('_docs/{*,**/*}.md'), GLOB_BRACE)->andReturn([])->byDefault(); + } + + protected function tearDown(): void + { + $this->verifyMockeryExpectations(); + } + public function testBladePageGetHelperReturnsBladePageCollection() { + $this->shouldReceiveGlob('_pages/{*,**/*}.blade.php')->andReturn(['_pages/test-page.blade.php']); + $this->shouldFindFile('_pages/test-page.blade.php'); + $collection = BladePage::all(); - $this->assertCount(2, $collection); + $this->assertCount(1, $collection); $this->assertInstanceOf(Collection::class, $collection); $this->assertContainsOnlyInstancesOf(BladePage::class, $collection); } public function testMarkdownPageGetHelperReturnsMarkdownPageCollection() { - Filesystem::touch('_pages/test-page.md'); + $this->shouldReceiveGlob('_pages/{*,**/*}.md')->andReturn(['_pages/test-page.md']); + $this->shouldFindFile('_pages/test-page.md'); $collection = MarkdownPage::all(); $this->assertCount(1, $collection); $this->assertInstanceOf(Collection::class, $collection); $this->assertContainsOnlyInstancesOf(MarkdownPage::class, $collection); - - Filesystem::unlink('_pages/test-page.md'); } public function testMarkdownPostGetHelperReturnsMarkdownPostCollection() { - Filesystem::touch('_posts/test-post.md'); + $this->shouldReceiveGlob('_posts/{*,**/*}.md')->andReturn(['_posts/test-post.md']); + $this->shouldFindFile('_posts/test-post.md'); $collection = MarkdownPost::all(); $this->assertCount(1, $collection); $this->assertInstanceOf(Collection::class, $collection); $this->assertContainsOnlyInstancesOf(MarkdownPost::class, $collection); - - Filesystem::unlink('_posts/test-post.md'); } public function testDocumentationPageGetHelperReturnsDocumentationPageCollection() { - $this->withoutDocumentationSearch(); - - Filesystem::touch('_docs/test-page.md'); - + $this->shouldReceiveGlob('_docs/{*,**/*}.md')->andReturn(['_docs/test-page.md']); + $this->shouldFindFile('_docs/test-page.md'); $collection = DocumentationPage::all(); $this->assertCount(1, $collection); $this->assertInstanceOf(Collection::class, $collection); $this->assertContainsOnlyInstancesOf(DocumentationPage::class, $collection); + } - Filesystem::unlink('_docs/test-page.md'); + protected function shouldReceiveGlob(string $withPath): ExpectationInterface + { + return $this->filesystem->shouldReceive('glob')->once()->with(Hyde::path($withPath), GLOB_BRACE); + } - $this->restoreDocumentationSearch(); + protected function shouldFindFile(string $file): void + { + $this->filesystem->shouldReceive('missing')->once()->with(Hyde::path($file))->andReturnFalse(); + $this->filesystem->shouldReceive('get')->once()->with(Hyde::path($file))->andReturn('content'); } } diff --git a/packages/framework/tests/Unit/Pages/PageModelParseHelperTest.php b/packages/framework/tests/Unit/Pages/PageModelParseHelperTest.php index 8e4c55fedd7..885a35a817f 100644 --- a/packages/framework/tests/Unit/Pages/PageModelParseHelperTest.php +++ b/packages/framework/tests/Unit/Pages/PageModelParseHelperTest.php @@ -4,55 +4,58 @@ namespace Hyde\Framework\Testing\Unit\Pages; -use Hyde\Facades\Filesystem; +use Hyde\Hyde; use Hyde\Pages\BladePage; use Hyde\Pages\DocumentationPage; use Hyde\Pages\MarkdownPage; use Hyde\Pages\MarkdownPost; -use Hyde\Testing\TestCase; +use Hyde\Testing\UnitTestCase; /** * @covers \Hyde\Pages\Concerns\HydePage::parse */ -class PageModelParseHelperTest extends TestCase +class PageModelParseHelperTest extends UnitTestCase { - public function testBladePageGetHelperReturnsBladePageObject() + protected static bool $needsKernel = true; + protected static bool $needsConfig = true; + + protected function tearDown(): void { - Filesystem::touch('_pages/foo.blade.php'); + $this->verifyMockeryExpectations(); + } - $object = BladePage::parse('foo'); - $this->assertInstanceOf(BladePage::class, $object); + public function testBladePageGetHelperReturnsBladePageObject() + { + $this->mockFilesystemCalls('_pages/foo.blade.php'); - Filesystem::unlink('_pages/foo.blade.php'); + $this->assertInstanceOf(BladePage::class, BladePage::parse('foo')); } public function testMarkdownPageGetHelperReturnsMarkdownPageObject() { - Filesystem::touch('_pages/foo.md'); + $this->mockFilesystemCalls('_pages/foo.md'); - $object = MarkdownPage::parse('foo'); - $this->assertInstanceOf(MarkdownPage::class, $object); - - Filesystem::unlink('_pages/foo.md'); + $this->assertInstanceOf(MarkdownPage::class, MarkdownPage::parse('foo')); } public function testMarkdownPostGetHelperReturnsMarkdownPostObject() { - Filesystem::touch('_posts/foo.md'); - - $object = MarkdownPost::parse('foo'); - $this->assertInstanceOf(MarkdownPost::class, $object); + $this->mockFilesystemCalls('_posts/foo.md'); - Filesystem::unlink('_posts/foo.md'); + $this->assertInstanceOf(MarkdownPost::class, MarkdownPost::parse('foo')); } public function testDocumentationPageGetHelperReturnsDocumentationPageObject() { - Filesystem::touch('_docs/foo.md'); + $this->mockFilesystemCalls('_docs/foo.md'); - $object = DocumentationPage::parse('foo'); - $this->assertInstanceOf(DocumentationPage::class, $object); + $this->assertInstanceOf(DocumentationPage::class, DocumentationPage::parse('foo')); + } - Filesystem::unlink('_docs/foo.md'); + protected function mockFilesystemCalls(string $path): void + { + $this->mockFilesystemStrict() + ->shouldReceive('missing')->once()->with(Hyde::path($path))->andReturn(false) + ->shouldReceive('get')->once()->with(Hyde::path($path))->andReturn('foo'); } } diff --git a/packages/framework/tests/Unit/PostAuthorTest.php b/packages/framework/tests/Unit/PostAuthorTest.php index 3eeb7bd0d27..f7ad7902170 100644 --- a/packages/framework/tests/Unit/PostAuthorTest.php +++ b/packages/framework/tests/Unit/PostAuthorTest.php @@ -26,8 +26,6 @@ class PostAuthorTest extends UnitTestCase protected function setUp(): void { - parent::setUp(); - self::resetKernel(); } diff --git a/packages/framework/tests/Unit/RenderHelperTest.php b/packages/framework/tests/Unit/RenderHelperTest.php index ee0cc280ecb..e99195248f1 100644 --- a/packages/framework/tests/Unit/RenderHelperTest.php +++ b/packages/framework/tests/Unit/RenderHelperTest.php @@ -26,8 +26,6 @@ class RenderHelperTest extends UnitTestCase protected function setUp(): void { - parent::setUp(); - Render::swap(new RenderData()); View::swap(Mockery::mock(Factory::class)->makePartial()); } diff --git a/packages/framework/tests/Unit/ServeCommandOptionsUnitTest.php b/packages/framework/tests/Unit/ServeCommandOptionsUnitTest.php index ea003f8feaf..f76d70e35ee 100644 --- a/packages/framework/tests/Unit/ServeCommandOptionsUnitTest.php +++ b/packages/framework/tests/Unit/ServeCommandOptionsUnitTest.php @@ -34,11 +34,7 @@ protected function setUp(): void protected function tearDown(): void { - $this->addToAssertionCount(Mockery::getContainer()->mockery_getExpectationCount()); - - Mockery::close(); - - parent::tearDown(); + $this->verifyMockeryExpectations(); } public function testGetHostSelection() diff --git a/packages/framework/tests/Unit/TestingSupportHelpersMetaTest.php b/packages/framework/tests/Unit/TestingSupportHelpersMetaTest.php index 83c694546b3..55abd8b70e2 100644 --- a/packages/framework/tests/Unit/TestingSupportHelpersMetaTest.php +++ b/packages/framework/tests/Unit/TestingSupportHelpersMetaTest.php @@ -4,6 +4,7 @@ namespace Hyde\Framework\Testing\Unit; +use AllowDynamicProperties; use Hyde\Pages\InMemoryPage; use Hyde\Testing\UnitTestCase; use Hyde\Testing\MocksKernelFeatures; @@ -17,6 +18,7 @@ * * @coversNothing */ +#[AllowDynamicProperties] class TestingSupportHelpersMetaTest extends UnitTestCase { use MocksKernelFeatures; diff --git a/packages/framework/tests/Unit/UnixsumTest.php b/packages/framework/tests/Unit/UnixsumTest.php index 968c1d0d5f1..81b800eda6c 100644 --- a/packages/framework/tests/Unit/UnixsumTest.php +++ b/packages/framework/tests/Unit/UnixsumTest.php @@ -63,7 +63,7 @@ public function testMethodReturnsSameValueForStringWithMixedEndOfLineSequences() public function testMethodReturnsSameValueWhenLoadedFromFileUsingShorthand() { - self::needsKernel(); + self::resetKernel(); $string = "foo\nbar\r\nbaz\r\n"; diff --git a/packages/framework/tests/Unit/ValidatesExistenceTest.php b/packages/framework/tests/Unit/ValidatesExistenceTest.php index 51414ea4507..efcc3b88e06 100644 --- a/packages/framework/tests/Unit/ValidatesExistenceTest.php +++ b/packages/framework/tests/Unit/ValidatesExistenceTest.php @@ -7,14 +7,16 @@ use Hyde\Framework\Concerns\ValidatesExistence; use Hyde\Framework\Exceptions\FileNotFoundException; use Hyde\Pages\BladePage; -use Hyde\Testing\TestCase; +use Hyde\Testing\UnitTestCase; /** * @covers \Hyde\Framework\Concerns\ValidatesExistence * @covers \Hyde\Framework\Exceptions\FileNotFoundException */ -class ValidatesExistenceTest extends TestCase +class ValidatesExistenceTest extends UnitTestCase { + protected static bool $needsKernel = true; + public function testValidateExistenceDoesNothingIfFileExists() { $class = new ValidatesExistenceTestClass(); diff --git a/packages/framework/tests/Unit/Views/LinkComponentTest.php b/packages/framework/tests/Unit/Views/LinkComponentViewTest.php similarity index 96% rename from packages/framework/tests/Unit/Views/LinkComponentTest.php rename to packages/framework/tests/Unit/Views/LinkComponentViewTest.php index 30b2b016dee..7d8839ac082 100644 --- a/packages/framework/tests/Unit/Views/LinkComponentTest.php +++ b/packages/framework/tests/Unit/Views/LinkComponentViewTest.php @@ -12,7 +12,7 @@ /** * @covers \Hyde\Framework\Views\Components\LinkComponent */ -class LinkComponentTest extends TestCase +class LinkComponentViewTest extends TestCase { public function testLinkComponentCanBeRendered() { diff --git a/packages/hyde/tests/DefaultContentTest.php b/packages/hyde/tests/DefaultContentTest.php index f632c9c433a..77c8d349d18 100644 --- a/packages/hyde/tests/DefaultContentTest.php +++ b/packages/hyde/tests/DefaultContentTest.php @@ -10,7 +10,7 @@ class DefaultContentTest extends UnitTestCase { public static function setUpBeforeClass(): void { - self::needsKernel(); + self::resetKernel(); } public function testDefaultPagesArePresent() diff --git a/packages/testing/src/FluentTestingHelpers.php b/packages/testing/src/FluentTestingHelpers.php index 77bc23b3fdc..117a339467b 100644 --- a/packages/testing/src/FluentTestingHelpers.php +++ b/packages/testing/src/FluentTestingHelpers.php @@ -37,7 +37,11 @@ protected function throwOnConsoleException(bool $throw = true): void */ protected function withSiteUrl(?string $url = 'https://example.com'): void { - config(['hyde.url' => $url]); + if ($this instanceof UnitTestCase) { + self::mockConfig(['hyde.url' => $url]); + } else { + config(['hyde.url' => $url]); + } } /** @@ -45,7 +49,7 @@ protected function withSiteUrl(?string $url = 'https://example.com'): void */ protected function withoutSiteUrl(): void { - config(['hyde.url' => null]); + $this->withSiteUrl(null); } /** Assert that all the given variables are the same. */ diff --git a/packages/testing/src/UnitTestCase.php b/packages/testing/src/UnitTestCase.php index 764334bec74..3314280c698 100644 --- a/packages/testing/src/UnitTestCase.php +++ b/packages/testing/src/UnitTestCase.php @@ -4,32 +4,25 @@ namespace Hyde\Testing; +use Mockery; use Hyde\Foundation\HydeKernel; use Hyde\Support\Facades\Render; use Illuminate\Config\Repository; use Hyde\Support\Models\RenderData; +use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Facades\Config; use PHPUnit\Framework\TestCase as BaseTestCase; abstract class UnitTestCase extends BaseTestCase { - protected static bool $hasSetUpKernel = false; - protected static bool $needsKernel = false; protected static bool $needsConfig = false; protected static bool $needsRender = false; - protected static function needsKernel(): void - { - if (! self::$hasSetUpKernel) { - self::setupKernel(); - } - } - public static function setUpBeforeClass(): void { if (static::$needsKernel) { - self::needsKernel(); + self::resetKernel(); } if (static::$needsConfig) { @@ -41,10 +34,23 @@ public static function setUpBeforeClass(): void } } + public static function tearDownAfterClass(): void + { + // Todo: Ensure all tests properly clean up after themselves + Mockery::close(); + + if (Mockery::getContainer()->getMocks()) { + self::markTestIncomplete('Mockery expectations were not verified and state was not reset.'); + } + + if (app()->bound(Filesystem::class) && app()->make(Filesystem::class) instanceof Mockery\MockInterface) { + app()->forgetInstance(Filesystem::class); + } + } + protected static function setupKernel(): void { HydeKernel::setInstance(new HydeKernel()); - self::$hasSetUpKernel = true; } protected static function resetKernel(): void @@ -54,9 +60,9 @@ protected static function resetKernel(): void protected static function mockRender(): Render { - Render::swap(new RenderData()); - - return new Render(); + return tap(new Render(), function () { + Render::swap(new RenderData()); + }); } protected static function mockCurrentRouteKey(?string $routeKey = null): void @@ -66,8 +72,31 @@ protected static function mockCurrentRouteKey(?string $routeKey = null): void protected static function mockConfig(array $items = []): void { - app()->bind('config', fn (): Repository => new Repository($items)); + Config::swap(tap(new Repository($items), function ($config) { + app()->instance('config', $config); + })); + } + + /** @return \Illuminate\Filesystem\Filesystem&\Mockery\MockInterface */ + protected function mockFilesystem(array $methods = []): Filesystem + { + return tap(Mockery::mock(Filesystem::class, $methods)->makePartial(), function ($filesystem) { + app()->instance(Filesystem::class, $filesystem); + }); + } + + /** @return \Illuminate\Filesystem\Filesystem&\Mockery\MockInterface */ + protected function mockFilesystemStrict(array $methods = []): Filesystem + { + return tap(Mockery::mock(Filesystem::class, $methods), function ($filesystem) { + app()->instance(Filesystem::class, $filesystem); + }); + } + + protected function verifyMockeryExpectations(): void + { + $this->addToAssertionCount(Mockery::getContainer()->mockery_getExpectationCount()); - Config::swap(app('config')); + Mockery::close(); } }