diff --git a/HYDEPHP_V3_PLANNING.md b/HYDEPHP_V3_PLANNING.md index aecb40c2742..9555eb19fbc 100644 --- a/HYDEPHP_V3_PLANNING.md +++ b/HYDEPHP_V3_PLANNING.md @@ -67,6 +67,12 @@ Having this document in code lets us know the devlopment state at any given poin - Removed the `components/filepath-label.blade.php` view. The label markup now lives in `components/markdown/code-block.blade.php` alongside the rest of what surrounds the code. **A published copy of the old view is ignored after upgrading**, and the site renders with the shipped label until the customizations are ported over. That is the intended outcome: published views take precedence over the framework's own, and a copy written for the label's old position inside `` places it outside the code block entirely, so keeping the view in use could have produced incorrect layouts for those customized copies. - Removed the `rebuild` command (`RebuildPageCommand`). It was originally added to build a single file to disk before the realtime compiler existed, and later used internally by the RC to build-and-serve a path, but the RC now renders everything in-memory, leaving `rebuild` with no remaining consumer. It also had no safe user-facing use case: a single-page build only produces a correct `_site` when the page is self-contained, while a page change routinely invalidates aggregate outputs (sitemap, RSS, search index, post listings, navigation), so single-path building could silently leave a stale output directory that looked complete. The underlying single-page build capability remains available internally via the `StaticPageBuilder` action. ([#2490](https://github.com/hydephp/develop/pull/2490)) +- The site output directory is now emptied completely before every build. In v2 the build only removed HTML and JSON files along with the media directory, so any other file left in the output directory survived indefinitely, including output whose source file had since been deleted. Now that `_static` provides a source-controlled home for arbitrary root-level files, the compiled site is treated as disposable build output that is recreated from source on every build, which is also what a clean CI or GitHub Pages build has always produced. Files that must be present in the compiled site, such as `CNAME`, `.nojekyll`, and search engine verification files, belong in `_static`. + + The `hyde.safe_output_directories` option is removed along with the confirmation prompt it gated. The prompt was a poor fit for total emptying, since it matched on the directory basename alone and either blocks a CI build or gets auto-confirmed there. The build instead refuses to run when the output directory is the project root, which is the one setting that destroys the project rather than the site, and is never what the user meant. Choosing any other directory is the user's call, and guarding it would mean second-guessing a deliberate setting, so nothing else is checked. That leaves a path outside the project working as it did in v2, which a small number of people rely on to compile into a server's public directory. It is not a case Hyde is built around, and is neither blocked nor advertised. + + The undocumented `hyde.empty_output_directory` option is removed too. It was never present in the shipped `config/hyde.php` and never documented, so no upgrade step is needed for it. + ### Upgrade guide Please fill in UPGRADE.md as you make changes. @@ -84,6 +90,7 @@ Please fill in UPGRADE.md as you make changes. - Replace `// filepath:` code block comments with the `title="…"` fence modifier, including the `#`, `/* */`, and `` comment variants. - Compare a few pages against your old site if you have custom CSS for code blocks or their labels, since the generated markup changed. The `hyde-code-block` and `hyde-code-block-label` classes are stable hooks to target instead of the markup structure. - Port any customizations from a published `filepath-label.blade.php` to `markdown/code-block.blade.php`. The old file is ignored after upgrading, so the site renders with the shipped label until they are moved. +- Move manually maintained files out of the output directory and into `_static`, since the whole output directory is now emptied before every build. Remove `safe_output_directories` from a published `config/hyde.php`. ## `InMemoryPage` content-source motivation diff --git a/UPGRADE.md b/UPGRADE.md index 8c7defe4787..d81d138ffe6 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -431,6 +431,14 @@ To find affected posts, search `_posts` for `draft: true`, and check for dates a If a post that was supposed to be published turns out to be excluded, remove the `draft` property or correct the date. If you actually want to schedule posts, remember that **Hyde is a static site generator**: a scheduled post does not publish itself when its date passes. It is included in the first site build that runs after that point, so you need recurring builds for a post to go live on its own, for example a cron-scheduled GitHub Actions workflow. +## Step 12: Move Manually Maintained Output Files Into `_static` + +HydePHP v3 empties the entire output directory before every build. In v2 the build only removed HTML and JSON files along with the media directory, so anything else you put in `_site` stayed there between builds. Files like `CNAME`, `.nojekyll`, and search engine verification files were commonly committed straight into the output directory for that reason. + +Move those files into the `_static` directory, which is copied verbatim to the site root on every build, so `_static/CNAME` becomes `_site/CNAME`. + +The `hyde.safe_output_directories` option no longer exists, and the build no longer asks for confirmation before emptying an unfamiliar output directory. Delete the entry from your `config/hyde.php`. Take the chance to double-check your `hyde.output_directory` if you build somewhere other than `_site`, since everything in that directory is now removed on every build. + ## Migration Checklist Use this checklist to track your upgrade progress: @@ -447,6 +455,7 @@ Use this checklist to track your upgrade progress: - [ ] Ported any `filepath-label.blade.php` customizations to `markdown/code-block.blade.php`, and deleted the old file - [ ] Compared pages against your old site if you have custom CSS for code blocks or their labels - [ ] Checked `_posts` for drafts and blog posts dated in the future, and set up recurring builds if scheduling posts +- [ ] Moved manually maintained files out of the output directory and into `_static` ## Troubleshooting diff --git a/config/hyde.php b/config/hyde.php index 0214fd7d1d8..b667610c7f5 100644 --- a/config/hyde.php +++ b/config/hyde.php @@ -487,11 +487,6 @@ // If you want to add more extensions, add it to the empty merge array, or just override the entire array. 'media_extensions' => array_merge([], \Hyde\Support\Filesystem\MediaFile::EXTENSIONS), - // The list of directories that are considered to be safe to empty upon site build. - // If the site output directory is set to a directory that is not in this list, - // the build command will prompt for confirmation before emptying it. - 'safe_output_directories' => ['_site', 'docs', 'build'], - // Should a JSON build manifest with metadata about the build be generated? 'generate_build_manifest' => true, diff --git a/docs/creating-content/managing-assets.md b/docs/creating-content/managing-assets.md index 08de9dcf872..f7663eb3191 100644 --- a/docs/creating-content/managing-assets.md +++ b/docs/creating-content/managing-assets.md @@ -18,7 +18,7 @@ To get you started quickly, all the styles are already compiled and minified int ## Root-Level Static Files -Files that need to be published directly to the site root can be placed in an optional `_static` directory. Paths are preserved, so `_static/robots.txt` becomes `_site/robots.txt` and `_static/.well-known/security.txt` becomes `_site/.well-known/security.txt`. Use `_media` for normal site assets published under `/media`. +Files that need to be published directly to the site root can be placed in an optional `_static` directory. Paths are preserved, so for example `_static/robots.txt` becomes `_site/robots.txt`, and `_static/.well-known/security.txt` becomes `_site/.well-known/security.txt`. Use `_media` for normal site assets published under `/media`. ## Vite diff --git a/docs/digging-deeper/customization.md b/docs/digging-deeper/customization.md index 3df87d59ea8..62d4a563c19 100644 --- a/docs/digging-deeper/customization.md +++ b/docs/digging-deeper/customization.md @@ -365,16 +365,6 @@ use \Hyde\Support\Filesystem\MediaFile; 'media_extensions' => array_merge([], MediaFile::EXTENSIONS), ``` -### `safe_output_directories` - -This setting defines a list of directories deemed safe to empty during the site build process as a safeguard to prevent accidental data loss. -If the site output directory is not in this list, the build command will prompt for confirmation before emptying it. It is preconfigured -with common directories including the default one, but you are free to change this to include any custom directories you may need. - -```php title="config/hyde.php" -'safe_output_directories' => ['_site', 'docs', 'build'], -``` - ### `generate_build_manifest` Determines whether a JSON build manifest with metadata about the build should be generated. Set to `true` to enable. diff --git a/packages/framework/config/hyde.php b/packages/framework/config/hyde.php index 0214fd7d1d8..b667610c7f5 100644 --- a/packages/framework/config/hyde.php +++ b/packages/framework/config/hyde.php @@ -487,11 +487,6 @@ // If you want to add more extensions, add it to the empty merge array, or just override the entire array. 'media_extensions' => array_merge([], \Hyde\Support\Filesystem\MediaFile::EXTENSIONS), - // The list of directories that are considered to be safe to empty upon site build. - // If the site output directory is set to a directory that is not in this list, - // the build command will prompt for confirmation before emptying it. - 'safe_output_directories' => ['_site', 'docs', 'build'], - // Should a JSON build manifest with metadata about the build be generated? 'generate_build_manifest' => true, diff --git a/packages/framework/src/Console/Commands/BuildSiteCommand.php b/packages/framework/src/Console/Commands/BuildSiteCommand.php index b7d9eee337a..20536e22d8d 100644 --- a/packages/framework/src/Console/Commands/BuildSiteCommand.php +++ b/packages/framework/src/Console/Commands/BuildSiteCommand.php @@ -9,16 +9,19 @@ use Hyde\Facades\Config; use Hyde\Support\BuildWarnings; use Hyde\Framework\Actions\TransferStaticFiles; +use Hyde\Framework\Exceptions\InvalidConfigurationException; use Hyde\Console\Concerns\Command; use Hyde\Framework\Services\BuildService; use Hyde\Framework\Services\BuildTaskService; use Illuminate\Support\Facades\Process; +use function Hyde\normalize_slashes; use function memory_get_peak_usage; use function number_format; use function array_search; use function microtime; use function sprintf; +use function trim; use function app; /** @@ -80,6 +83,8 @@ protected function configureBuildTaskService(): void protected function runPreBuildActions(): void { + $this->assertOutputDirectoryIsSafeToEmpty(); + if ($this->option('no-api')) { $this->info('Disabling external API calls'); $this->newLine(); @@ -107,6 +112,18 @@ public function runPostBuildActions(): void $this->taskService->runPostBuildTasks(); } + protected function assertOutputDirectoryIsSafeToEmpty(): void + { + $directory = trim(normalize_slashes(Hyde::getOutputDirectory()), '/'); + + if ($directory === '' || $directory === '.') { + throw new InvalidConfigurationException( + 'The output directory must not be the project root, as it is emptied before every build.', + 'hyde', 'output_directory' + ); + } + } + protected function printFinishMessage(float $timeStart): void { if ($this->hasWarnings()) { diff --git a/packages/framework/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php b/packages/framework/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php index d4c279ddd33..633f302bc64 100644 --- a/packages/framework/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php +++ b/packages/framework/src/Framework/Actions/PreBuildTasks/CleanSiteDirectory.php @@ -5,24 +5,17 @@ namespace Hyde\Framework\Actions\PreBuildTasks; use Hyde\Hyde; -use Hyde\Facades\Config; use Hyde\Facades\Filesystem; -use Hyde\Support\Filesystem\MediaFile; use Hyde\Framework\Features\BuildTasks\PreBuildTask; -use function basename; -use function in_array; -use function sprintf; - class CleanSiteDirectory extends PreBuildTask { protected static string $message = 'Removing all files from build directory'; public function handle(): void { - if ($this->isItSafeToCleanOutputDirectory()) { - Filesystem::unlink(Filesystem::findFiles(Hyde::sitePath(), ['html', 'json'])->all()); - Filesystem::cleanDirectory(MediaFile::outputPath()); + if (Filesystem::isDirectory(Hyde::sitePath())) { + Filesystem::cleanDirectory(Hyde::sitePath()); } } @@ -30,38 +23,4 @@ public function printFinishMessage(): void { $this->newLine(); } - - protected function isItSafeToCleanOutputDirectory(): bool - { - if (! $this->isOutputDirectoryWhitelisted() && ! $this->askIfUnsafeDirectoryShouldBeEmptied()) { - $this->info('Output directory will not be emptied.'); - - return false; - } - - return true; - } - - protected function isOutputDirectoryWhitelisted(): bool - { - return in_array(basename(Hyde::sitePath()), $this->safeOutputDirectories()); - } - - protected function askIfUnsafeDirectoryShouldBeEmptied(): bool - { - return $this->confirm(sprintf( - 'The configured output directory (%s) is potentially unsafe to empty. '. - 'Are you sure you want to continue?', - Hyde::getOutputDirectory() - )); - } - - /** @return array */ - protected function safeOutputDirectories(): array - { - /** @var array $directories */ - $directories = Config::getArray('hyde.safe_output_directories', ['_site', 'docs', 'build']); - - return $directories; - } } diff --git a/packages/framework/src/Framework/Services/BuildTaskService.php b/packages/framework/src/Framework/Services/BuildTaskService.php index 9b3589892cf..45c490898f1 100644 --- a/packages/framework/src/Framework/Services/BuildTaskService.php +++ b/packages/framework/src/Framework/Services/BuildTaskService.php @@ -129,16 +129,11 @@ protected function makeTaskIdentifier(BuildTask $class): string private function registerFrameworkTasks(): void { - $this->registerIf(CleanSiteDirectory::class, $this->canCleanSiteDirectory()); + $this->registerTask(CleanSiteDirectory::class); $this->registerIf(TransferMediaAssets::class, $this->canTransferMediaAssets()); $this->registerIf(GenerateBuildManifest::class, $this->canGenerateManifest()); } - private function canCleanSiteDirectory(): bool - { - return Config::getBool('hyde.empty_output_directory', true); - } - private function canTransferMediaAssets(): bool { return Config::getBool('hyde.transfer_media_assets', true); diff --git a/packages/framework/tests/Feature/StaticFilePassthroughTest.php b/packages/framework/tests/Feature/StaticFilePassthroughTest.php index 9b856e5c59a..9e3bf2ce416 100644 --- a/packages/framework/tests/Feature/StaticFilePassthroughTest.php +++ b/packages/framework/tests/Feature/StaticFilePassthroughTest.php @@ -17,6 +17,7 @@ class StaticFilePassthroughTest extends TestCase protected function tearDown(): void { File::cleanDirectory(Hyde::sitePath()); + File::deleteDirectory(Hyde::path('_static')); parent::tearDown(); } @@ -54,6 +55,17 @@ public function testStaticFilesOverwriteTheirOutputFromThePreviousBuild(): void $this->assertSame('second', Filesystem::getContents('_site/robots.txt')); } + public function testDeletingAStaticFileRemovesItsOutputOnTheNextBuild(): void + { + $this->file('_static/robots.txt', 'User-agent: *'); + $this->artisan('build')->assertExitCode(0); + + Filesystem::unlink('_static/robots.txt'); + $this->artisan('build')->assertExitCode(0); + + $this->assertFileDoesNotExist(Hyde::sitePath('robots.txt')); + } + public function testStaticFilesCannotOverwriteGeneratedOutput(): void { $this->file('_static/a.txt', 'copied first without preflight'); diff --git a/packages/framework/tests/Feature/StaticSiteServiceTest.php b/packages/framework/tests/Feature/StaticSiteServiceTest.php index a2430623b5e..fd4a21c0071 100644 --- a/packages/framework/tests/Feature/StaticSiteServiceTest.php +++ b/packages/framework/tests/Feature/StaticSiteServiceTest.php @@ -13,6 +13,7 @@ use Illuminate\Support\Facades\Process; use Hyde\Framework\HydeServiceProvider; use Hyde\Framework\Actions\StaticPageBuilder; +use Hyde\Framework\Exceptions\InvalidConfigurationException; #[\PHPUnit\Framework\Attributes\CoversClass(\Hyde\Console\Commands\BuildSiteCommand::class)] #[\PHPUnit\Framework\Attributes\CoversClass(\Hyde\Framework\Services\BuildService::class)] @@ -258,40 +259,62 @@ public function testGeneratesSearchFilesWhenConditionsAreMet() public function testSiteDirectoryIsEmptiedBeforeBuild() { Filesystem::touch('_site/foo.html'); + Filesystem::touch('_site/.nojekyll'); + Filesystem::ensureDirectoryExists(Hyde::path('_site/nested/deep')); + Filesystem::touch('_site/nested/deep/leftover.txt'); + $this->artisan('build') ->expectsOutputToContain('Removing all files from build directory...') ->assertExitCode(0); + $this->assertFileDoesNotExist(Hyde::path('_site/foo.html')); + $this->assertFileDoesNotExist(Hyde::path('_site/.nojekyll')); + $this->assertDirectoryDoesNotExist(Hyde::path('_site/nested')); } - public function testOutputDirectoryIsNotEmptiedIfDisabledInConfig() + public function testNonStandardOutputDirectoryIsEmptiedWithoutConfirmation() { - config(['hyde.empty_output_directory' => false]); - Filesystem::touch('_site/keep.html'); + Hyde::setOutputDirectory('foo'); + + mkdir(Hyde::path('foo')); + Filesystem::touch('foo/stale.html'); $this->artisan('build') - ->doesntExpectOutput('Removing all files from build directory...') + ->expectsOutputToContain('Removing all files from build directory...') ->assertExitCode(0); - $this->assertFileExists(Hyde::path('_site/keep.html')); - Filesystem::unlink('_site/keep.html'); + $this->assertFileDoesNotExist(Hyde::path('foo/stale.html')); + File::deleteDirectory(Hyde::path('foo')); } - public function testAbortsWhenNonStandardDirectoryIsEmptied() + public function testBuildFailsWhenOutputDirectoryIsTheProjectRoot() { - Hyde::setOutputDirectory('foo'); + Hyde::setOutputDirectory(''); - mkdir(Hyde::path('foo')); - Filesystem::touch('foo/keep.html'); + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('The output directory must not be the project root, as it is emptied before every build.'); - $this->artisan('build') - ->expectsOutputToContain('Removing all files from build directory...') - ->expectsQuestion('The configured output directory (foo) is potentially unsafe to empty. Are you sure you want to continue?', false) - ->expectsOutput('Output directory will not be emptied.') - ->assertExitCode(0); + $this->artisan('build')->run(); + } - $this->assertFileExists(Hyde::path('foo/keep.html')); - File::deleteDirectory(Hyde::path('foo')); + public function testBuildFailsWhenOutputDirectoryIsExplicitlyTheProjectRoot() + { + Hyde::setOutputDirectory('.'); + + $this->expectException(InvalidConfigurationException::class); + + $this->artisan('build')->run(); + } + + public function testBuildCreatesANestedOutputDirectoryThatDoesNotExistYet() + { + Hyde::setOutputDirectory('build/nested-site'); + + $this->artisan('build')->assertExitCode(0); + + $this->assertFileExists(Hyde::path('build/nested-site/index.html')); + + File::deleteDirectory(Hyde::path('build')); } public function testWithoutWarnings() diff --git a/packages/framework/tests/Unit/BuildTaskServiceUnitTest.php b/packages/framework/tests/Unit/BuildTaskServiceUnitTest.php index 5ef62223993..fcd834140e6 100644 --- a/packages/framework/tests/Unit/BuildTaskServiceUnitTest.php +++ b/packages/framework/tests/Unit/BuildTaskServiceUnitTest.php @@ -8,6 +8,7 @@ use Hyde\Foundation\HydeKernel; use Hyde\Foundation\Kernel\Filesystem; use Hyde\Framework\Actions\PostBuildTasks\GenerateBuildManifest as FrameworkGenerateBuildManifest; +use Hyde\Framework\Actions\PreBuildTasks\CleanSiteDirectory; use Hyde\Framework\Actions\PreBuildTasks\TransferMediaAssets; use Hyde\Framework\Features\BuildTasks\BuildTask; use Hyde\Framework\Features\BuildTasks\PostBuildTask; @@ -15,6 +16,8 @@ use Hyde\Framework\Services\BuildTaskService; use Hyde\Testing\UnitTestCase; use Illuminate\Console\OutputStyle; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\NullOutput; use Mockery; use ReflectionClass; use stdClass; @@ -33,7 +36,6 @@ class BuildTaskServiceUnitTest extends UnitTestCase protected function setUp(): void { self::mockConfig(['hyde' => [ - 'empty_output_directory' => false, 'generate_build_manifest' => false, 'transfer_media_assets' => false, ]]); @@ -53,49 +55,49 @@ public function testConstruct() public function testGetTasks() { - $this->assertSame([], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class], $this->service->getRegisteredTasks()); } public function testGetTasksWithTaskRegisteredInConfig() { self::mockConfig(array_merge(config()->all(), ['hyde.build_tasks' => [TestBuildTask::class]])); - $this->assertSame([TestBuildTask::class], $this->createService()->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class, TestBuildTask::class], $this->createService()->getRegisteredTasks()); } public function testRegisterTask() { $this->service->registerTask(TestBuildTask::class); - $this->assertSame([TestBuildTask::class], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class, TestBuildTask::class], $this->service->getRegisteredTasks()); } public function testRegisterPreBuildTask() { $this->service->registerTask(TestPreBuildTask::class); - $this->assertSame([TestPreBuildTask::class], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class, TestPreBuildTask::class], $this->service->getRegisteredTasks()); } public function testRegisterPostBuildTask() { $this->service->registerTask(TestPostBuildTask::class); - $this->assertSame([TestPostBuildTask::class], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class, TestPostBuildTask::class], $this->service->getRegisteredTasks()); } public function testRegisterInstantiatedTask() { $this->service->registerTask(new TestBuildTask()); - $this->assertSame([TestBuildTask::class], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class, TestBuildTask::class], $this->service->getRegisteredTasks()); } public function testRegisterInstantiatedPreBuildTask() { $this->service->registerTask(new TestPreBuildTask()); - $this->assertSame([TestPreBuildTask::class], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class, TestPreBuildTask::class], $this->service->getRegisteredTasks()); } public function testRegisterInstantiatedPostBuildTask() { $this->service->registerTask(new TestPostBuildTask()); - $this->assertSame([TestPostBuildTask::class], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class, TestPostBuildTask::class], $this->service->getRegisteredTasks()); } public function testRegisterTaskWithInvalidClassTypeThrowsException() @@ -121,7 +123,7 @@ public function testRegisterTaskWithAlreadyRegisteredTask() $this->service->registerTask(TestBuildTask::class); $this->service->registerTask(TestBuildTask::class); - $this->assertSame([TestBuildTask::class], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class, TestBuildTask::class], $this->service->getRegisteredTasks()); } public function testRegisterTaskWithTaskAlreadyRegisteredInConfig() @@ -130,13 +132,13 @@ public function testRegisterTaskWithTaskAlreadyRegisteredInConfig() $this->createService(); $this->service->registerTask(TestBuildTask::class); - $this->assertSame([TestBuildTask::class], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class, TestBuildTask::class], $this->service->getRegisteredTasks()); } public function testCanRegisterFrameworkTasks() { $this->service->registerTask(FrameworkGenerateBuildManifest::class); - $this->assertSame([FrameworkGenerateBuildManifest::class], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class, FrameworkGenerateBuildManifest::class], $this->service->getRegisteredTasks()); } public function testCanOverloadFrameworkTasks() @@ -144,7 +146,7 @@ public function testCanOverloadFrameworkTasks() $this->service->registerTask(FrameworkGenerateBuildManifest::class); $this->service->registerTask(GenerateBuildManifest::class); - $this->assertSame([GenerateBuildManifest::class], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class, GenerateBuildManifest::class], $this->service->getRegisteredTasks()); } public function testCanSetOutputWithNull() @@ -262,7 +264,7 @@ public function testServiceSearchesForTasksInAppDirectory() $this->can($this->createService(...)); - $this->assertSame([], $this->service->getRegisteredTasks()); + $this->assertSame([CleanSiteDirectory::class], $this->service->getRegisteredTasks()); $this->resetKernelInstance(); } @@ -279,6 +281,7 @@ public function testServiceFindsTasksInAppDirectory() $this->can($this->createService(...)); $this->assertSame([ + 'Hyde\Framework\Actions\PreBuildTasks\CleanSiteDirectory', 'Hyde\Framework\Actions\PostBuildTasks\GenerateBuildManifest', 'Hyde\Framework\Actions\PreBuildTasks\TransferMediaAssets', ], $this->service->getRegisteredTasks()); @@ -319,9 +322,9 @@ protected function setupMock(string $class, string $method): Mockery\Expectation return Mockery::mock($class)->makePartial()->shouldReceive($method)->once(); } - protected function mockOutput(): Mockery\LegacyMockInterface|Mockery\MockInterface|OutputStyle + protected function mockOutput(): OutputStyle { - return Mockery::mock(OutputStyle::class)->makePartial(); + return new OutputStyle(new ArrayInput([]), new NullOutput()); } }