From 403716bd1937502c8be1f32e6fbc03ee59784a26 Mon Sep 17 00:00:00 2001 From: Andron Ocean Date: Tue, 15 Oct 2024 21:08:49 -0400 Subject: [PATCH 1/5] Use fallback for `$_composer_autoload_path` There are cases where this global may be undefined, and Composer recommends having a fallback. Without one, method signature is incorrect and usages like the `vendorDir()` method will fail if they expect a string. The fallback first looks for `vendor` in the same directory as `codeception.yml`, and if that's not found it guesses what the autoload path _ought_ to be. More info: https://getcomposer.org/doc/articles/vendor-binaries.md#finding-the-composer-autoloader-from-a-binary --- src/Utils/Composer.php | 15 ++++- .../lucatume/WPBrowser/Utils/ComposerTest.php | 63 +++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/Utils/Composer.php b/src/Utils/Composer.php index c8dbb8742..3162aecb5 100644 --- a/src/Utils/Composer.php +++ b/src/Utils/Composer.php @@ -30,8 +30,21 @@ public static function vendorDir(?string $path = null): string public static function autoloadPath(): string { + /** + * if $_composer_autoload_path is undefined, fall back to vendor/autoload.php in the parent project's directory. + * + * @link https://getcomposer.org/doc/articles/vendor-binaries.md#finding-the-composer-autoloader-from-a-binary + */ global $_composer_autoload_path; - return realpath($_composer_autoload_path) ?: $_composer_autoload_path; + if (isset($_composer_autoload_path)) { + $autoload_path = $_composer_autoload_path; + } elseif (is_dir(codecept_root_dir('vendor'))) { + $autoload_path = codecept_root_dir('vendor') . DIRECTORY_SEPARATOR . 'autoload.php'; + } else { + // vendor-dir was renamed, try our best to find the right directory based on where wp-browser is installed + $autoload_path = dirname(__FILE__, 5) . DIRECTORY_SEPARATOR . 'autoload.php'; + } + return realpath($autoload_path) ?: $autoload_path; } public static function binDir(?string $path = null): string diff --git a/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php b/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php index f59cf6667..0c3ff51ef 100644 --- a/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php +++ b/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php @@ -216,4 +216,67 @@ public function should_build_on_the_project_composer_file_if_no_composer_file_sp $composer->getDecodedContents() ); } + + /** + * The `autoloadPath` static method should return `$_composer_autoload_path` if it is defined + * + * @test + * @backupGlobals enabled + */ + public function static_autoload_path_should_return_global_composer_autoload_path(): void + { + global $_composer_autoload_path; + // ensure that it's set for this test + $_composer_autoload_path = codecept_root_dir() . 'vendor/autoload.php'; + + $this->assertSame($_composer_autoload_path, Composer::autoloadPath() ); + } + + /** + * The `autoloadPath` static method should return a best-guess fallback if the global `$_composer_autoload_path` is undefined + * + * @test + * @backupGlobals enabled + */ + public function static_autoload_path_should_use_fallback(): void + { + global $_composer_autoload_path; + // clear value to enable fallback + unset($GLOBALS['_composer_autoload_path']); + + $autoloadPath = Composer::autoloadPath(); + + $this->assertSame(codecept_root_dir() . 'vendor/autoload.php', $autoloadPath ); + $this->assertFileExists( $autoloadPath ); + } + + /** + * The `autoloadPath` static method should still return a best-guess fallback for `$_composer_autoload_path` + * if Composer's vendor-dir was renamed. + * + * @test + * @backupGlobals enabled + */ + public function static_autoload_path_should_use_fallback_if_vendor_dir_renamed_or_missing(): void + { + global $_composer_autoload_path; + // clear value to enable fallback + unset($GLOBALS['_composer_autoload_path']); + // pretend that wp-browser's own vendor dir does not exist + $this->setFunctionReturn('is_dir', false ); + + // The method has to find the renamed vendor-dir by directory traversal. + // i.e. if wp-browser is installed in `project/pkgs/lucatume/wp-browser`, find the `project/pkgs` dir. + // Let's figure out how far it has to go: + $mockVendorDir = dirname(codecept_root_dir(), 2); + $pathToClass = (new \ReflectionClass(Composer::class))->getFileName(); + $relPathToVendorDir = substr($pathToClass, strlen($mockVendorDir)); + + $this->assertSame(5, + // counting directory levels + substr_count($relPathToVendorDir, '/'), + "The method is hardcoded to look 5 levels up for the parent project's vendor-dir. If this test fails, the class has moved." + ); + $this->assertSame( dirname( $pathToClass, 5 ) . '/autoload.php', Composer::autoloadPath() ); + } } From 29c5612978842de5ffb37b6c627e5041a748c5e1 Mon Sep 17 00:00:00 2001 From: Andron Ocean Date: Fri, 1 Nov 2024 12:17:06 -0400 Subject: [PATCH 2/5] Simplify `$_composer_autoload_path` fallback cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `Codeception\Codecept` class will always give us the location of the vendor dir, even during wp-browser development or if a consumer project has moved it. (Thank you, @lucatume, for the suggestion.) Unit test simplified as we don't need the tedious dir traversal anymore — the single fallback test will detect any problems if `Codecept` moves. --- src/Utils/Composer.php | 12 +++---- .../lucatume/WPBrowser/Utils/ComposerTest.php | 32 +------------------ 2 files changed, 7 insertions(+), 37 deletions(-) diff --git a/src/Utils/Composer.php b/src/Utils/Composer.php index 3162aecb5..ac8815767 100644 --- a/src/Utils/Composer.php +++ b/src/Utils/Composer.php @@ -4,6 +4,7 @@ namespace lucatume\WPBrowser\Utils; +use Codeception\Codecept; use JsonException; use lucatume\WPBrowser\Adapters\Symfony\Component\Process\Process; use lucatume\WPBrowser\Exceptions\RuntimeException; @@ -37,14 +38,13 @@ public static function autoloadPath(): string */ global $_composer_autoload_path; if (isset($_composer_autoload_path)) { - $autoload_path = $_composer_autoload_path; - } elseif (is_dir(codecept_root_dir('vendor'))) { - $autoload_path = codecept_root_dir('vendor') . DIRECTORY_SEPARATOR . 'autoload.php'; + $autoloadPath = $_composer_autoload_path; } else { - // vendor-dir was renamed, try our best to find the right directory based on where wp-browser is installed - $autoload_path = dirname(__FILE__, 5) . DIRECTORY_SEPARATOR . 'autoload.php'; + // we use the Codecept class to find the location of Composer's vendor-dir, even if a project has renamed it + $vendorDir = dirname((string)(new \ReflectionClass(Codecept::class))->getFilename(), 5); + $autoloadPath = $vendorDir . DIRECTORY_SEPARATOR . 'autoload.php'; } - return realpath($autoload_path) ?: $autoload_path; + return realpath($autoloadPath) ?: $autoloadPath; } public static function binDir(?string $path = null): string diff --git a/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php b/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php index 0c3ff51ef..e2556ac93 100644 --- a/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php +++ b/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php @@ -233,7 +233,7 @@ public function static_autoload_path_should_return_global_composer_autoload_path } /** - * The `autoloadPath` static method should return a best-guess fallback if the global `$_composer_autoload_path` is undefined + * The `autoloadPath` static method should find the autoload.php file itself if the global `$_composer_autoload_path` is undefined * * @test * @backupGlobals enabled @@ -249,34 +249,4 @@ public function static_autoload_path_should_use_fallback(): void $this->assertSame(codecept_root_dir() . 'vendor/autoload.php', $autoloadPath ); $this->assertFileExists( $autoloadPath ); } - - /** - * The `autoloadPath` static method should still return a best-guess fallback for `$_composer_autoload_path` - * if Composer's vendor-dir was renamed. - * - * @test - * @backupGlobals enabled - */ - public function static_autoload_path_should_use_fallback_if_vendor_dir_renamed_or_missing(): void - { - global $_composer_autoload_path; - // clear value to enable fallback - unset($GLOBALS['_composer_autoload_path']); - // pretend that wp-browser's own vendor dir does not exist - $this->setFunctionReturn('is_dir', false ); - - // The method has to find the renamed vendor-dir by directory traversal. - // i.e. if wp-browser is installed in `project/pkgs/lucatume/wp-browser`, find the `project/pkgs` dir. - // Let's figure out how far it has to go: - $mockVendorDir = dirname(codecept_root_dir(), 2); - $pathToClass = (new \ReflectionClass(Composer::class))->getFileName(); - $relPathToVendorDir = substr($pathToClass, strlen($mockVendorDir)); - - $this->assertSame(5, - // counting directory levels - substr_count($relPathToVendorDir, '/'), - "The method is hardcoded to look 5 levels up for the parent project's vendor-dir. If this test fails, the class has moved." - ); - $this->assertSame( dirname( $pathToClass, 5 ) . '/autoload.php', Composer::autoloadPath() ); - } } From 07d796cabf8e8444298b79c1e7b656199e683e0c Mon Sep 17 00:00:00 2001 From: Luca Tumedei Date: Sat, 2 Nov 2024 10:13:36 +0100 Subject: [PATCH 3/5] build(typos) add rule to config file --- config/typos.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/typos.toml b/config/typos.toml index bc23dd4a9..6e1fc9967 100644 --- a/config/typos.toml +++ b/config/typos.toml @@ -13,3 +13,4 @@ ignore-hidden = false # To handle the hipster default blog content about bike messengers gettin' caught in the rain. "gettin" = "gettin" "Automattic" = "Automattic" +"Symplify" = "Symplify" From 2dce0a2914bc2f607a8db3559342d99d35a40ae8 Mon Sep 17 00:00:00 2001 From: Luca Tumedei Date: Sat, 2 Nov 2024 10:16:33 +0100 Subject: [PATCH 4/5] style(src,tests) update doc lines --- src/Utils/Composer.php | 4 ++-- tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Utils/Composer.php b/src/Utils/Composer.php index ac8815767..cfe86e535 100644 --- a/src/Utils/Composer.php +++ b/src/Utils/Composer.php @@ -32,7 +32,7 @@ public static function vendorDir(?string $path = null): string public static function autoloadPath(): string { /** - * if $_composer_autoload_path is undefined, fall back to vendor/autoload.php in the parent project's directory. + * If `$_composer_autoload_path` is undefined, fall back to `vendor/autoload.php` in the parent project's directory. * * @link https://getcomposer.org/doc/articles/vendor-binaries.md#finding-the-composer-autoloader-from-a-binary */ @@ -40,7 +40,7 @@ public static function autoloadPath(): string if (isset($_composer_autoload_path)) { $autoloadPath = $_composer_autoload_path; } else { - // we use the Codecept class to find the location of Composer's vendor-dir, even if a project has renamed it + // We use the Codecept class to find the location of Composer's vendor-dir, even if a project has renamed it. $vendorDir = dirname((string)(new \ReflectionClass(Codecept::class))->getFilename(), 5); $autoloadPath = $vendorDir . DIRECTORY_SEPARATOR . 'autoload.php'; } diff --git a/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php b/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php index e2556ac93..adc0781d4 100644 --- a/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php +++ b/tests/unit/lucatume/WPBrowser/Utils/ComposerTest.php @@ -225,8 +225,8 @@ public function should_build_on_the_project_composer_file_if_no_composer_file_sp */ public function static_autoload_path_should_return_global_composer_autoload_path(): void { + // Ensure that it's set for this test. global $_composer_autoload_path; - // ensure that it's set for this test $_composer_autoload_path = codecept_root_dir() . 'vendor/autoload.php'; $this->assertSame($_composer_autoload_path, Composer::autoloadPath() ); @@ -240,7 +240,6 @@ public function static_autoload_path_should_return_global_composer_autoload_path */ public function static_autoload_path_should_use_fallback(): void { - global $_composer_autoload_path; // clear value to enable fallback unset($GLOBALS['_composer_autoload_path']); From ea697c67451235500a8e080d6ce4211f62895128 Mon Sep 17 00:00:00 2001 From: Luca Tumedei Date: Sat, 2 Nov 2024 10:22:58 +0100 Subject: [PATCH 5/5] style(src) fix cs issues --- src/Utils/Composer.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Utils/Composer.php b/src/Utils/Composer.php index cfe86e535..9ea22fc0c 100644 --- a/src/Utils/Composer.php +++ b/src/Utils/Composer.php @@ -32,7 +32,8 @@ public static function vendorDir(?string $path = null): string public static function autoloadPath(): string { /** - * If `$_composer_autoload_path` is undefined, fall back to `vendor/autoload.php` in the parent project's directory. + * If `$_composer_autoload_path` is undefined, fall back to `vendor/autoload.php` + * in the parent project's directory. * * @link https://getcomposer.org/doc/articles/vendor-binaries.md#finding-the-composer-autoloader-from-a-binary */ @@ -40,7 +41,7 @@ public static function autoloadPath(): string if (isset($_composer_autoload_path)) { $autoloadPath = $_composer_autoload_path; } else { - // We use the Codecept class to find the location of Composer's vendor-dir, even if a project has renamed it. + // We use the Codecept class to find the location of Composer's vendor-dir. $vendorDir = dirname((string)(new \ReflectionClass(Codecept::class))->getFilename(), 5); $autoloadPath = $vendorDir . DIRECTORY_SEPARATOR . 'autoload.php'; }