diff --git a/common/Gruntfile.plugin.ts b/common/Gruntfile.plugin.ts index cf7ed7c..9f7d9bf 100755 --- a/common/Gruntfile.plugin.ts +++ b/common/Gruntfile.plugin.ts @@ -35,6 +35,14 @@ function applyPluginRunnerConfiguration(grunt: IGrunt) { cwd: "<%= BUILD_PLUGIN_DIR %>", src: ["public/ts", "public/dev/*.map", `vendor/${mainPkg.name}/*/dev/*.map`] }, + /** + * Remove all `dev` folders. This is an optional task and must be added via grunt.registerTask("post:clean:productionSource", ["clean:webpackDevBundles"]). + */ + webpackDevBundles: { + expand: true, + cwd: "<%= BUILD_PLUGIN_DIR %>", + src: ["public/dev/", `vendor/${mainPkg.name}/*/dev/`] + }, packageManageFiles: ["<%= BUILD_PLUGIN_DIR %>/?(composer|package).*"] }, strip_code: /* eslint-disable-line @typescript-eslint/camelcase */ { diff --git a/devops/.gitlab/stage-build.yml b/devops/.gitlab/stage-build.yml index 86ed1d9..6f9c704 100755 --- a/devops/.gitlab/stage-build.yml +++ b/devops/.gitlab/stage-build.yml @@ -60,6 +60,8 @@ common lint phpcs: - yarn tsc -p . # Build the plugin - yarn build + # Output artifact size of plugin zip + - du -sh build/* artifacts: name: $CI_JOB_NAME paths: [plugins/$JOB_PACKAGE_NAME/build/] diff --git a/packages/utils/src/Assets.php b/packages/utils/src/Assets.php index f650296..98f1630 100755 --- a/packages/utils/src/Assets.php +++ b/packages/utils/src/Assets.php @@ -342,7 +342,8 @@ protected function enqueueComposer( $useHandle = $vendorHandle !== null ? $vendorHandle : $rootSlug . '-' . $handle . $scriptSuffix; $useNonMinifiedSources = $this->useNonMinifiedSources(); $packageDir = 'vendor/' . $rootSlug . '/' . $handle . '/'; - $packageSrc = $packageDir . ($useNonMinifiedSources ? 'dev' : 'dist') . '/' . $src; + $devBundlesExists = is_dir($packageDir . 'dev'); + $packageSrc = $packageDir . ($useNonMinifiedSources && $devBundlesExists ? 'dev' : 'dist') . '/' . $src; $pluginPath = $this->getPluginConstant(PluginReceiver::$PLUGIN_CONST_PATH); $composerPath = path_join($pluginPath, $packageSrc); $isInLernaRepo = file_exists(path_join(WP_CONTENT_DIR, 'packages/' . $handle . '/tsconfig.json')); @@ -523,7 +524,16 @@ public function getPluginsUrl($asset, $isLib = false) { * @return string */ public function getPublicFolder($isLib = false) { - return 'public/' . ($isLib ? 'lib' : ($this->useNonMinifiedSources() ? 'dev' : 'dist')) . '/'; + if ($isLib) { + return 'public/lib/'; + } elseif ($this->useNonMinifiedSources()) { + // Check if dev folder exists because it can be removed in some builds + $path = $this->getPluginConstant(PluginReceiver::$PLUGIN_CONST_PATH); + if (is_dir($path . '/public/dev') || is_dir($path . '/src/public/dev') /* monorepo development */) { + return 'public/dev/'; + } + } + return 'public/dist/'; } /** diff --git a/packages/utils/test/patchwork.json b/packages/utils/test/patchwork.json index 46060b7..4742ae5 100755 --- a/packages/utils/test/patchwork.json +++ b/packages/utils/test/patchwork.json @@ -12,6 +12,7 @@ "glob", "basename", "filemtime", - "file_get_contents" + "file_get_contents", + "is_dir" ] } diff --git a/packages/utils/test/phpunit/AssetsTest.php b/packages/utils/test/phpunit/AssetsTest.php index e8fd861..f82cf97 100755 --- a/packages/utils/test/phpunit/AssetsTest.php +++ b/packages/utils/test/phpunit/AssetsTest.php @@ -884,7 +884,78 @@ public function testEnqueueComposer() { $this->assets->shouldAllowMockingProtectedMethods(); $this->assets->shouldReceive('enqueueComposer')->passthru(); $this->assets->shouldReceive('useNonMinifiedSources')->andReturnTrue(); - $this->expectCallbacksReached(['isLernaRepo']); + $self = $this->expectCallbacksReached(['devDirExists', 'isLernaRepo']); + + redefine('is_dir', function($dir) use ($self, $packageDir) { + $self->addCallbackReached('devDirExists', $dir === $packageDir . 'dev'); + return true; + }); + + WP_Mock::userFunction('path_join', ['times' => 1, 'args' => [PHPUNIT_PATH, $packageSrc]]); + WP_Mock::userFunction('path_join', [ + 'times' => 1, + 'args' => [WP_CONTENT_DIR, 'packages/' . $handle . '/tsconfig.json'] + ]); + + redefine('file_exists', function () { + if (!$this->hasCallbackReached('isLernaRepo')) { + $this->addCallbackReached('isLernaRepo'); + return false; + } + return true; + }); + + WP_Mock::userFunction('plugins_url', ['args' => [$packageSrc, PHPUNIT_FILE], 'return' => $plugins_url]); + WP_Mock::userFunction('path_join', ['times' => 1, 'args' => [PHPUNIT_PATH, $packageDir . 'package.json']]); + + redefine('filemtime', always($ts)); + redefine('file_get_contents', always('{"version": "' . $packageJsonVersion . '"}')); + + $this->assets + ->shouldReceive('probablyEnqueueComposerChunk') + ->once() + ->with($handle, 'index.js', [], true, 'all'); + + WP_Mock::userFunction('wp_enqueue_script', [ + 'times' => 1, + 'args' => [$should, $plugins_url, [], $packageJsonVersion, true] + ]); + WP_Mock::userFunction('path_join', [ + 'times' => 1, + 'args' => [PHPUNIT_PATH, $packageDir . 'languages/frontend/json'] + ]); + + $this->assets + ->shouldReceive('setLazyScriptTranslations') + ->once() + ->with($should, $should, null); + + $method = new ReflectionMethod(AssetsImpl::class, 'enqueueComposer'); + $method->setAccessible(true); + $actual = $method->invoke($this->assets, $handle); + + $this->assertEquals($should, $actual); + $this->assertCallbacksReached(); + } + + public function testEnqueueComposerDevFolderNotExists() { + $handle = 'utils'; + $should = PHPUNIT_ROOT_SLUG . '-' . $handle; + $packageDir = 'vendor/' . PHPUNIT_ROOT_SLUG . '/' . $handle . '/'; + $packageSrc = 'vendor/phpunit-root/utils/dist/index.js'; + $plugins_url = 'http://localhost/wp-content/plugins/phpunit/' . $packageSrc; + $ts = time(); + $packageJsonVersion = '1.0.0'; + + $this->assets->shouldAllowMockingProtectedMethods(); + $this->assets->shouldReceive('enqueueComposer')->passthru(); + $this->assets->shouldReceive('useNonMinifiedSources')->andReturnTrue(); + $self = $this->expectCallbacksReached(['devDirExists', 'isLernaRepo']); + + redefine('is_dir', function($dir) use ($self, $packageDir) { + $self->addCallbackReached('devDirExists', $dir === $packageDir . 'dev'); + return false; + }); WP_Mock::userFunction('path_join', ['times' => 1, 'args' => [PHPUNIT_PATH, $packageSrc]]); WP_Mock::userFunction('path_join', [ @@ -945,6 +1016,8 @@ public function testEnqueueComposerInLernaRepo() { $this->assets->shouldReceive('enqueueComposer')->passthru(); $this->assets->shouldReceive('useNonMinifiedSources')->andReturnTrue(); + redefine('is_dir', always(true)); + WP_Mock::userFunction('path_join'); redefine('file_exists', always(true)); @@ -981,6 +1054,8 @@ public function testEnqueueComposerWithNonExistingFile() { $this->assets->shouldReceive('enqueueComposer')->passthru(); $this->assets->shouldReceive('useNonMinifiedSources')->andReturnTrue(); + redefine('is_dir', always(true)); + WP_Mock::userFunction('path_join'); redefine('file_exists', always(false)); @@ -1008,6 +1083,8 @@ public function testEnqueueComposerWithStyle() { $this->assets->shouldReceive('useNonMinifiedSources')->andReturnTrue(); $this->expectCallbacksReached(['isLernaRepo']); + redefine('is_dir', always(true)); + WP_Mock::userFunction('path_join', ['times' => 1, 'args' => [PHPUNIT_PATH, $packageSrc]]); WP_Mock::userFunction('path_join', [ 'times' => 1, @@ -1060,6 +1137,8 @@ public function testEnqueueComposerWithStyleParameters() { $this->assets->shouldReceive('useNonMinifiedSources')->andReturnTrue(); $this->expectCallbacksReached(['isLernaRepo']); + redefine('is_dir', always(true)); + WP_Mock::userFunction('path_join'); redefine('file_exists', function () { @@ -1104,6 +1183,8 @@ public function testEnqueueComposerWithScriptParameters() { $this->assets->shouldReceive('useNonMinifiedSources')->andReturnTrue(); $this->expectCallbacksReached(['isLernaRepo']); + redefine('is_dir', always(true)); + WP_Mock::userFunction('path_join'); redefine('file_exists', function () { @@ -1334,6 +1415,21 @@ public function testGetPublicFolderDev() { $this->assets->shouldReceive('getPublicFolder')->passthru(); $this->assets->shouldReceive('useNonMinifiedSources')->andReturnTrue(); + redefine('is_dir', always(true)); + + $actual = $this->assets->getPublicFolder(); + + $this->assertEquals($should, $actual); + } + + public function testGetPublicFolderDevButDoesNotExist() { + $should = 'public/dist/'; + + $this->assets->shouldReceive('getPublicFolder')->passthru(); + $this->assets->shouldReceive('useNonMinifiedSources')->andReturnTrue(); + + redefine('is_dir', always(false)); + $actual = $this->assets->getPublicFolder(); $this->assertEquals($should, $actual);