diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index ee37e38..cb83e60 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -45,7 +45,7 @@ composer install composer test # Run specific test suite -vendor/bin/phpunit tests/EnvironmentTest.php +vendor/bin/phpunit tests/FooTest.php # Run with coverage vendor/bin/phpunit --coverage-html coverage/ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7ff5eb0..0c29f6b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -62,7 +62,7 @@ jobs: - name: Run tests with coverage if: matrix.php == '8.4' - run: vendor/bin/phpunit --coverage-clover=coverage.xml + run: composer test-coverage - name: Upload coverage to Codecov if: matrix.php == '8.4' diff --git a/.gitignore b/.gitignore index 3875a89..3c10f33 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .psalm/ vendor/ composer.lock +composer.develop.* diff --git a/README.md b/README.md index feb0145..3550707 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ +![PHP Version](https://img.shields.io/packagist/php-v/wp-spaghetti/wp-env) ![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/wp-spaghetti/wp-env/total) ![GitHub Actions Workflow Status](https://github.com/wp-spaghetti/wp-env/actions/workflows/main.yml/badge.svg) +![Coverage Status](https://img.shields.io/codecov/c/github/wp-spaghetti/wp-env) ![GitHub Issues](https://img.shields.io/github/issues/wp-spaghetti/wp-env) ![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen) ![GitHub Release](https://img.shields.io/github/v/release/wp-spaghetti/wp-env) ![License](https://img.shields.io/github/license/wp-spaghetti/wp-env) @@ -586,7 +586,7 @@ echo "Debug Mode: " . (Environment::isDebug() ? 'enabled' : 'disabled') . "\n"; ## Changelog -Please see [CHANGELOG.md](CHANGELOG.md) for a detailed list of changes for each release. +Please see [CHANGELOG](CHANGELOG.md) for a detailed list of changes for each release. We follow [Semantic Versioning](https://semver.org/) and use [Conventional Commits](https://www.conventionalcommits.org/) to automatically generate our changelog. @@ -606,6 +606,8 @@ For your contributions please use: - [git-flow workflow](https://danielkummer.github.io/git-flow-cheatsheet/) - [Pull request workflow](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project) +See [CONTRIBUTING](CONTRIBUTING.md) for detailed guidelines. + ## Sponsor [Buy Me A Coffee](https://buymeacoff.ee/frugan) @@ -614,4 +616,3 @@ For your contributions please use: (ɔ) Copyleft 2025 [Frugan](https://frugan.it). [GNU GPLv3](https://choosealicense.com/licenses/gpl-3.0/), see [LICENSE](LICENSE) file. - diff --git a/composer.json b/composer.json index 8dc6ee4..78ba55e 100644 --- a/composer.json +++ b/composer.json @@ -16,10 +16,16 @@ { "name": "Frugan", "email": "dev@frugan.it", - "homepage": "https://github.com/wp-spaghetti" + "homepage": "https://github.com/frugan-dev", + "role": "Developer" } ], "homepage": "https://github.com/wp-spaghetti/wp-env", + "support": { + "issues": "https://github.com/wp-spaghetti/wp-env/issues", + "source": "https://github.com/wp-spaghetti/wp-env", + "docs": "https://github.com/wp-spaghetti/wp-env#readme" + }, "require": { "php": ">=8.0" }, @@ -60,10 +66,16 @@ "analysis": "grumphp run --tasks=phpstan", "check": "grumphp run", "ci": "grumphp run --no-interaction", - "coverage": "vendor/bin/phpunit --coverage-clover=coverage.xml", "lint": "grumphp run --tasks=phpcsfixer,phplint,phpstan,rector", "quality": "grumphp run --tasks=phpmnd,phpparser", "security": "grumphp run --tasks=securitychecker_roave", - "test": "grumphp run --tasks=phpunit" - } + "test": "grumphp run --tasks=phpunit", + "test-coverage": "vendor/bin/phpunit --coverage-clover=coverage.xml" + }, + "funding": [ + { + "type": "custom", + "url": "https://buymeacoff.ee/frugan" + } + ] } diff --git a/phpunit-10.xml.dist b/phpunit-10.xml.dist index 581f936..8de15e9 100644 --- a/phpunit-10.xml.dist +++ b/phpunit-10.xml.dist @@ -22,4 +22,4 @@ - \ No newline at end of file + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index aa4e15e..742fbad 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -23,4 +23,4 @@ - \ No newline at end of file + diff --git a/src/Environment.php b/src/Environment.php index 3b07f5e..d93da4a 100644 --- a/src/Environment.php +++ b/src/Environment.php @@ -14,6 +14,7 @@ namespace WpSpaghetti\WpEnv; use Env\Env; +use PHPUnit\Framework\TestCase; if (!\defined('ABSPATH')) { exit; @@ -42,6 +43,8 @@ class Environment public const ENV_PRODUCTION = 'production'; + public const ENV_TESTING = 'testing'; + /** * Cache for environment values to improve performance. * @@ -368,7 +371,8 @@ public static function getEnvironment(): string // Map common variations $environment = match ($env) { 'dev', 'develop', 'development', 'local' => self::ENV_DEVELOPMENT, - 'stage', 'staging', 'test', 'testing' => self::ENV_STAGING, + 'stage', 'staging', => self::ENV_STAGING, + 'test', 'testing' => self::ENV_TESTING, 'prod', 'production', 'live' => self::ENV_PRODUCTION, default => self::detectEnvironmentByIndicators() }; @@ -409,6 +413,34 @@ public static function isProduction(): bool return self::ENV_PRODUCTION === self::getEnvironment(); } + /** + * Check if we're in testing environment. + * This includes both environment variables and PHPUnit runtime detection. + */ + public static function isTesting(): bool + { + // First check PHPUnit runtime (not affected by mocks) + if (\defined('PHPUNIT_COMPOSER_INSTALL') || class_exists(TestCase::class)) { + return true; + } + + $testingValue = self::ENV_TESTING; + + // Then check WordPress constants (not affected by mocks) + // @phpstan-ignore-next-line identical.alwaysTrue (constants may vary in different environments) + if (\defined('WP_ENV') && $testingValue === \constant('WP_ENV')) { + return true; + } + + // @phpstan-ignore-next-line identical.alwaysTrue (constants may vary in different environments) + if (\defined('WP_ENVIRONMENT_TYPE') && $testingValue === \constant('WP_ENVIRONMENT_TYPE')) { + return true; + } + + // Finally check environment variables (affected by mocks) + return self::ENV_TESTING === self::getEnvironment(); + } + /** * Check if WordPress debug mode is enabled. */ @@ -579,12 +611,12 @@ private static function getRaw(string $key, mixed $default = null): mixed } // Normal priority outside of testing: - // Then try WordPress constants (more WordPress-native) + // WordPress constants have priority in production (defined in wp-config.php) if (\defined($key)) { return \constant($key); } - // Then try oscarotero/env (for Bedrock and modern setups) + // Then try oscarotero/env (for Bedrock and modern setups) - only in non-testing mode if (\function_exists('Env\env')) { /** @phpstan-ignore-next-line */ $originalDefault = Env::$default ?? null; @@ -626,9 +658,9 @@ private static function getMockAwareEnvVar(string $key): false|string } // In testing mode, don't fall back to regular getenv to maintain mock isolation - if (self::hasMockVariables()) { - return false; - } + // if (self::hasMockVariables()) { + // return false; + // } // Fall back to regular getenv only in non-testing mode $getEnv = \function_exists('mock_getenv') ? 'mock_getenv' : 'getenv'; diff --git a/tests/bootstrap.php b/tests/bootstrap.php index fd25cde..1b0e140 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -24,6 +24,10 @@ define('WP_ENV', 'testing'); } +if (!defined('WP_ENVIRONMENT_TYPE')) { + define('WP_ENVIRONMENT_TYPE', 'testing'); +} + // Autoload Composer dependencies require_once __DIR__.'/../vendor/autoload.php';