diff --git a/docs/en/usage.md b/docs/en/usage.md index 76b226d9f..212251174 100644 --- a/docs/en/usage.md +++ b/docs/en/usage.md @@ -61,6 +61,21 @@ For non-conventional relations, you can use references in constraints or foreign ->addForeignKey('shipping_country_id', 'countries', 'cid') ``` +### Fixture Factories + +When a Fixture Factories plugin such as +[vierge-noire/cakephp-fixture-factories](https://github.com/vierge-noire/cakephp-fixture-factories) +or [dereuromark/cakephp-fixture-factories](https://github.com/dereuromark/cakephp-fixture-factories) +is installed, `bake model` does not generate a fixture class, and baked test +cases have no `$fixtures` property. Bake the factory with that plugin's own command: + +```bash +bin/cake bake fixture_factory Articles +``` + +`bake fixture` still generates a fixture class when you ask for one, and +`bake test` honors an explicit `--fixtures` list. + ## Bake Enums You can use Bake to generate [backed enums](https://www.php.net/manual/en/language.enumerations.backed.php) for use in your models. diff --git a/src/Command/BakeCommand.php b/src/Command/BakeCommand.php index 1c783b2e6..b8032dea1 100644 --- a/src/Command/BakeCommand.php +++ b/src/Command/BakeCommand.php @@ -185,6 +185,17 @@ public function createTemplateRenderer(): TemplateRenderer return $renderer; } + /** + * Check if a Fixture Factories plugin is installed. + * + * @return bool + */ + protected function hasFixtureFactories(): bool + { + return class_exists('CakephpFixtureFactories\Plugin') + || class_exists('CakephpFixtureFactories\CakephpFixtureFactoriesPlugin'); + } + /** * Delete empty file in a given path * diff --git a/src/Command/ModelCommand.php b/src/Command/ModelCommand.php index a8d87cdef..6bfaa435b 100644 --- a/src/Command/ModelCommand.php +++ b/src/Command/ModelCommand.php @@ -1435,6 +1435,12 @@ public function bakeFixture( if ($args->getOption('no-fixture')) { return; } + if ($this->hasFixtureFactories()) { + $io->info('Fixture Factories plugin detected - skipping fixture generation.'); + $io->info(sprintf('Bake a factory instead: `bin/cake bake fixture_factory %s`', $className)); + + return; + } $fixture = new FixtureCommand(); $fixtureArgs = new Arguments( [$className], diff --git a/src/Command/TestCommand.php b/src/Command/TestCommand.php index b6e78ea03..70f8f5a5a 100644 --- a/src/Command/TestCommand.php +++ b/src/Command/TestCommand.php @@ -300,11 +300,11 @@ public function bake(string $type, string $className, Arguments $args, ConsoleIo $hasFixtureFactories = $this->hasFixtureFactories(); if (!$args->getOption('no-fixture')) { - if ($hasFixtureFactories) { - $io->info('Fixture Factories plugin detected - skipping fixture property generation.'); - } elseif ($args->getOption('fixtures')) { + if ($args->getOption('fixtures')) { $fixtures = array_map('trim', explode(',', (string)$args->getOption('fixtures'))); $this->_fixtures = array_filter($fixtures); + } elseif ($hasFixtureFactories) { + $io->info('Fixture Factories plugin detected - skipping fixture property generation.'); } elseif ($this->typeCanDetectFixtures($type) && class_exists($fullClassName)) { $io->out('Bake is detecting possible fixtures...'); $testSubject = $this->buildTestSubject($type, $fullClassName); @@ -373,17 +373,6 @@ public function bake(string $type, string $className, Arguments $args, ConsoleIo return false; } - /** - * Check if the CakePHP Fixture Factories plugin is available - * - * @return bool - */ - protected function hasFixtureFactories(): bool - { - return class_exists('CakephpFixtureFactories\Plugin') - || class_exists('CakephpFixtureFactories\CakephpFixtureFactoriesPlugin'); - } - /** * Checks whether the chosen type can find its own fixtures. * Currently only model, and controller are supported diff --git a/templates/bake/tests/test_case.twig b/templates/bake/tests/test_case.twig index 2fcb90ff5..351cf85bf 100644 --- a/templates/bake/tests/test_case.twig +++ b/templates/bake/tests/test_case.twig @@ -63,7 +63,7 @@ class {{ className }}Test extends TestCase {%~ endfor %} {% endif %} -{%- if fixtures and not (hasFixtureFactories|default(false)) %} +{%- if fixtures %} /** * Fixtures * diff --git a/tests/TestCase/Command/ModelCommandTest.php b/tests/TestCase/Command/ModelCommandTest.php index 0cc9cc1fe..3074e89fd 100644 --- a/tests/TestCase/Command/ModelCommandTest.php +++ b/tests/TestCase/Command/ModelCommandTest.php @@ -1835,6 +1835,32 @@ public function testBakeFixtureDisabled(): void $this->assertFileDoesNotExist(ROOT . 'tests/TestCase/Model/Table/TodoItemsTableTest.php'); } + /** + * No fixture is baked when a Fixture Factories plugin is installed. + * + * @return void + */ + public function testBakeFixtureWithFixtureFactories(): void + { + $this->generatedFiles = [ + ROOT . 'tests/Fixture/TodoItemsFixture.php', + ]; + $command = new class extends ModelCommand { + protected function hasFixtureFactories(): bool + { + return true; + } + }; + $out = new StubConsoleOutput(); + $io = new ConsoleIo($out, new StubConsoleOutput(), new StubConsoleInput([])); + + $command->bakeFixture('TodoItems', 'todo_items', new Arguments([], [], []), $io); + + $this->assertFileDoesNotExist($this->generatedFiles[0]); + $this->assertStringContainsString('skipping fixture generation', $out->output()); + $this->assertStringContainsString('bin/cake bake fixture_factory TodoItems', $out->output()); + } + /** * Ensure that the test object is correctly called. * diff --git a/tests/TestCase/Command/TestCommandTest.php b/tests/TestCase/Command/TestCommandTest.php index edfa9783c..3ba0a037b 100644 --- a/tests/TestCase/Command/TestCommandTest.php +++ b/tests/TestCase/Command/TestCommandTest.php @@ -22,6 +22,9 @@ use Bake\Test\App\Model\Table\CategoryThreadsTable; use Bake\Test\TestCase\TestCase; use Cake\Console\CommandInterface; +use Cake\Console\ConsoleIo; +use Cake\Console\TestSuite\StubConsoleInput; +use Cake\Console\TestSuite\StubConsoleOutput; use Cake\Core\Plugin; use Cake\Http\ServerRequest as Request; use PHPUnit\Framework\Attributes\DataProvider; @@ -386,6 +389,62 @@ public function testBakeNoFixtureParam(): void $this->assertSameAsFile(__FUNCTION__ . '.php', file_get_contents($this->generatedFiles[0])); } + /** + * Fixtures are left out when a Fixture Factories plugin is installed. + * + * @return void + */ + public function testBakeWithFixtureFactories(): void + { + $this->generatedFiles = [ + ROOT . 'tests/TestCase/Model/Table/AuthorsTableTest.php', + ]; + $out = new StubConsoleOutput(); + $io = new ConsoleIo($out, new StubConsoleOutput(), new StubConsoleInput([])); + + $result = $this->fixtureFactoriesCommand()->run(['table', 'Authors'], $io); + + $this->assertSame(CommandInterface::CODE_SUCCESS, $result); + $this->assertStringContainsString('Fixture Factories plugin detected', $out->output()); + $this->assertStringNotContainsString('$fixtures', (string)file_get_contents($this->generatedFiles[0])); + } + + /** + * An explicit fixture list is used even if a Fixture Factories plugin is installed. + * + * @return void + */ + public function testBakeFixturesParamWithFixtureFactories(): void + { + $this->generatedFiles = [ + ROOT . 'tests/TestCase/Model/Table/AuthorsTableTest.php', + ]; + $out = new StubConsoleOutput(); + $io = new ConsoleIo($out, new StubConsoleOutput(), new StubConsoleInput([])); + + $result = $this->fixtureFactoriesCommand()->run( + ['table', 'Authors', '--fixtures', 'app.Posts,app.Comments,app.Users'], + $io, + ); + + $this->assertSame(CommandInterface::CODE_SUCCESS, $result); + $this->assertStringNotContainsString('Fixture Factories plugin detected', $out->output()); + $this->assertSameAsFile('testBakeFixturesParam.php', file_get_contents($this->generatedFiles[0])); + } + + /** + * @return \Bake\Command\TestCommand + */ + protected function fixtureFactoriesCommand(): TestCommand + { + return new class extends TestCommand { + protected function hasFixtureFactories(): bool + { + return true; + } + }; + } + /** * Test baking a test for a cell. *