Browse Source

Change how plugin collection is used by an application.

Instead of fetching the singleton instance from the Plugin class the
app now creates it's own collection instance and sets it as the singleton.

This provides better app state isolation when running integration tests.
ADmad 2 years ago
parent
commit
bd231aff03

+ 11 - 0
src/Core/Plugin.php

@@ -129,4 +129,15 @@ class Plugin
     {
         return static::$plugins ??= new PluginCollection();
     }
+
+    /**
+     * Set the shared plugin collection.
+     *
+     * @param \Cake\Core\PluginCollection $collection
+     * @return void
+     */
+    public static function setCollection(PluginCollection $collection): void
+    {
+        static::$plugins = $collection;
+    }
 }

+ 21 - 0
src/Core/TestSuite/ContainerStubTrait.php

@@ -56,6 +56,8 @@ trait ContainerStubTrait
      */
     private array $containerServices = [];
 
+    protected array $pluginsToLoad = [];
+
     /**
      * Configure the application class to use in integration tests.
      *
@@ -71,6 +73,17 @@ trait ContainerStubTrait
     }
 
     /**
+     * Plugins to load after the app instance is created.
+     *
+     * @param array $plugins
+     * @return void
+     */
+    public function pluginsToLoad(array $plugins): void
+    {
+        $this->pluginsToLoad = $plugins;
+    }
+
+    /**
      * Create an application instance.
      *
      * Uses the configuration set in `configApplication()`.
@@ -95,6 +108,14 @@ trait ContainerStubTrait
             $app->getEventManager()->on('Application.buildContainer', [$this, 'modifyContainer']);
         }
 
+        foreach ($this->pluginsToLoad as $pluginName => $config) {
+            if (is_array($config)) {
+                $app->addPlugin($pluginName, $config);
+            } else {
+                $app->addPlugin($config);
+            }
+        }
+
         return $app;
     }
 

+ 2 - 1
src/Http/BaseApplication.php

@@ -107,9 +107,10 @@ abstract class BaseApplication implements
         ?ControllerFactoryInterface $controllerFactory = null
     ) {
         $this->configDir = rtrim($configDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
-        $this->plugins = Plugin::getCollection();
+        $this->plugins = new PluginCollection();
         $this->_eventManager = $eventManager ?: EventManager::instance();
         $this->controllerFactory = $controllerFactory;
+        Plugin::setCollection($this->plugins);
     }
 
     /**

+ 1 - 1
tests/TestCase/Command/I18nExtractCommandTest.php

@@ -273,7 +273,7 @@ class I18nExtractCommandTest extends TestCase
      */
     public function testExtractVendorPrefixedPlugin(): void
     {
-        $this->loadPlugins(['Company/TestPluginThree']);
+        $this->pluginsToLoad(['Company/TestPluginThree']);
 
         $this->exec(
             'i18n extract ' .

+ 10 - 10
tests/TestCase/Command/PluginAssetsCommandsTest.php

@@ -76,7 +76,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
     public function testSymlink(): void
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
         $this->exec('plugin assets symlink');
         $this->assertExitCode(CommandInterface::CODE_SUCCESS);
@@ -92,7 +92,7 @@ class PluginAssetsCommandsTest extends TestCase
 
     public function testSymlinkWhenVendorDirectoryExists(): void
     {
-        $this->loadPlugins(['Company/TestPluginThree']);
+        $this->pluginsToLoad(['Company/TestPluginThree']);
 
         mkdir($this->wwwRoot . 'company');
 
@@ -109,7 +109,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
     public function testSymlinkWhenTargetAlreadyExits(): void
     {
-        $this->loadPlugins(['TestTheme']);
+        $this->pluginsToLoad(['TestTheme']);
 
         $output = new StubConsoleOutput();
         $io = Mockery::mock(ConsoleIo::class, [$output, $output, null, null])->makePartial();
@@ -134,7 +134,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
     public function testForPluginWithoutWebroot(): void
     {
-        $this->loadPlugins(['TestPluginTwo']);
+        $this->pluginsToLoad(['TestPluginTwo']);
 
         $this->exec('plugin assets symlink');
         $this->assertFileDoesNotExist($this->wwwRoot . 'test_plugin_two');
@@ -145,7 +145,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
     public function testSymlinkingSpecifiedPlugin(): void
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
         $this->exec('plugin assets symlink TestPlugin');
 
@@ -162,7 +162,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
     public function testCopy(): void
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
         $this->exec('plugin assets copy');
 
@@ -180,7 +180,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
     public function testCopyOverwrite(): void
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false]]);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false]]);
 
         $this->exec('plugin assets copy');
 
@@ -207,7 +207,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
     public function testRemoveSymlink(): void
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
         mkdir($this->wwwRoot . 'company');
 
@@ -230,7 +230,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
     public function testRemoveFolder(): void
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
         $this->exec('plugin assets copy');
 
@@ -250,7 +250,7 @@ class PluginAssetsCommandsTest extends TestCase
      */
     public function testOverwrite(): void
     {
-        $this->loadPlugins(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
+        $this->pluginsToLoad(['TestPlugin' => ['routes' => false], 'Company/TestPluginThree']);
 
         $path = $this->wwwRoot . 'test_plugin';
 

+ 1 - 13
tests/TestCase/Console/Command/HelpCommandTest.php

@@ -18,9 +18,6 @@ namespace Cake\Test\TestCase\Console\Command;
 
 use Cake\Console\CommandInterface;
 use Cake\Console\TestSuite\ConsoleIntegrationTestTrait;
-use Cake\Core\Plugin;
-use Cake\Http\BaseApplication;
-use Cake\Http\MiddlewareQueue;
 use Cake\TestSuite\TestCase;
 
 /**
@@ -37,16 +34,7 @@ class HelpCommandTest extends TestCase
     {
         parent::setUp();
         $this->setAppNamespace();
-        Plugin::getCollection()->clear();
-
-        $app = new class ('') extends BaseApplication
-        {
-            public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
-            {
-                return $middlewareQueue;
-            }
-        };
-        $app->addPlugin('TestPlugin');
+        $this->pluginsToLoad(['TestPlugin']);
     }
 
     /**

+ 1 - 1
tests/TestCase/Routing/AssetTest.php

@@ -229,7 +229,7 @@ class AssetTest extends TestCase
     public function testAssetTimestampPluginsAndThemes(): void
     {
         Configure::write('Asset.timestamp', 'force');
-        $this->loadPlugins(['TestPlugin', 'Company/TestPluginThree']);
+        $this->loadPlugins(['TestTheme', 'TestPlugin', 'Company/TestPluginThree']);
 
         $result = Asset::assetTimestamp('/test_plugin/css/test_plugin_asset.css');
         $this->assertMatchesRegularExpression('#/test_plugin/css/test_plugin_asset.css\?[0-9]+$#', $result, 'Missing timestamp plugin');

+ 1 - 1
tests/TestCase/View/Helper/UrlHelperTest.php

@@ -333,7 +333,7 @@ class UrlHelperTest extends TestCase
     public function testAssetTimestampPluginsAndThemes(): void
     {
         Configure::write('Asset.timestamp', 'force');
-        $this->loadPlugins(['TestPlugin']);
+        $this->loadPlugins(['TestTheme', 'TestPlugin']);
 
         $result = $this->Helper->assetTimestamp('/test_plugin/css/test_plugin_asset.css');
         $this->assertMatchesRegularExpression('#/test_plugin/css/test_plugin_asset.css\?[0-9]+$#', $result, 'Missing timestamp plugin');