|
@@ -0,0 +1,268 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+
|
|
|
|
|
+namespace Test\Michel\Env;
|
|
|
|
|
+
|
|
|
|
|
+use Michel\Env\DotEnv;
|
|
|
|
|
+use Michel\Env\Processor\BooleanProcessor;
|
|
|
|
|
+use Michel\Env\Processor\NullProcessor;
|
|
|
|
|
+use Michel\Env\Processor\NumberProcessor;
|
|
|
|
|
+use Michel\Env\Processor\QuotedProcessor;
|
|
|
|
|
+use Michel\UniTester\TestCase;
|
|
|
|
|
+
|
|
|
|
|
+class DotenvTest extends TestCase
|
|
|
|
|
+{
|
|
|
|
|
+ protected function setUp(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ // TODO: Implement setUp() method.
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ protected function tearDown(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->clearAllEnv();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function clearAllEnv(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ foreach ($_ENV as $key => $value) {
|
|
|
|
|
+ unset($_ENV[$key]);
|
|
|
|
|
+ }
|
|
|
|
|
+ foreach ($_SERVER as $key => $value) {
|
|
|
|
|
+ unset($_SERVER[$key]);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ protected function execute(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->clearAllEnv();
|
|
|
|
|
+ $this->testLoad();
|
|
|
|
|
+ $this->clearAllEnv();
|
|
|
|
|
+
|
|
|
|
|
+ $this->testFileNotExist();
|
|
|
|
|
+ $this->clearAllEnv();
|
|
|
|
|
+
|
|
|
|
|
+ $this->testIncompatibleProcessors();
|
|
|
|
|
+ $this->clearAllEnv();
|
|
|
|
|
+
|
|
|
|
|
+ $this->testProcessBoolean();
|
|
|
|
|
+ $this->clearAllEnv();
|
|
|
|
|
+
|
|
|
|
|
+ $this->testDontProcessBoolean();
|
|
|
|
|
+ $this->clearAllEnv();
|
|
|
|
|
+
|
|
|
|
|
+ $this->testProcessQuotes();
|
|
|
|
|
+ $this->clearAllEnv();
|
|
|
|
|
+
|
|
|
|
|
+ $this->testDontProcessQuotes();
|
|
|
|
|
+ $this->clearAllEnv();
|
|
|
|
|
+
|
|
|
|
|
+ $this->testProcessNumbers();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function env(string $file)
|
|
|
|
|
+ {
|
|
|
|
|
+ return __DIR__ . DIRECTORY_SEPARATOR . 'env' . DIRECTORY_SEPARATOR . $file;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @runInSeparateProcess
|
|
|
|
|
+ */
|
|
|
|
|
+ public function testLoad() {
|
|
|
|
|
+
|
|
|
|
|
+ (new DotEnv($this->env('.env.default')))->load();
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals('dev', getenv('APP_ENV'));
|
|
|
|
|
+ $this->assertEquals('mysql:host=localhost;dbname=test;', getenv('DATABASE_DNS'));
|
|
|
|
|
+ $this->assertEquals('root', getenv('DATABASE_USER'));
|
|
|
|
|
+ $this->assertEquals('password', getenv('DATABASE_PASSWORD'));
|
|
|
|
|
+ $this->assertFalse(getenv('GOOGLE_API'));
|
|
|
|
|
+ $this->assertFalse(getenv('GOOGLE_MANAGER_KEY'));
|
|
|
|
|
+ $this->assertEquals(true, getenv('BOOLEAN_LITERAL'));
|
|
|
|
|
+ $this->assertEquals('true', getenv('BOOLEAN_QUOTED'));
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals('dev', $_ENV['APP_ENV']);
|
|
|
|
|
+ $this->assertEquals('password', $_ENV['DATABASE_PASSWORD']);
|
|
|
|
|
+ $this->assertFalse(array_key_exists('GOOGLE_API', $_ENV));
|
|
|
|
|
+ $this->assertFalse(array_key_exists('GOOGLE_MANAGER_KEY', $_ENV));
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals(true, $_ENV['BOOLEAN_LITERAL']);
|
|
|
|
|
+ $this->assertEquals('true', $_ENV['BOOLEAN_QUOTED']);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals('mysql:host=localhost;dbname=test;', $_SERVER['DATABASE_DNS']);
|
|
|
|
|
+ $this->assertEquals('root', $_SERVER['DATABASE_USER']);
|
|
|
|
|
+ $this->assertEquals('password', $_SERVER['DATABASE_PASSWORD']);
|
|
|
|
|
+ $this->assertFalse(array_key_exists('GOOGLE_API', $_SERVER));
|
|
|
|
|
+ $this->assertFalse(array_key_exists('GOOGLE_MANAGER_KEY', $_SERVER));
|
|
|
|
|
+ $this->assertEquals(true, $_SERVER['BOOLEAN_LITERAL']);
|
|
|
|
|
+ $this->assertEquals('true', $_SERVER['BOOLEAN_QUOTED']);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals('🪄', $_SERVER['EMOJI']);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertTrue(is_int($_SERVER['ZERO_LITERAL']));
|
|
|
|
|
+ $this->assertEquals(0, $_SERVER['ZERO_LITERAL']);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertTrue(is_string($_SERVER['ZERO_QUOTED']));
|
|
|
|
|
+ $this->assertEquals('0', $_SERVER['ZERO_QUOTED']);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertTrue(is_int($_SERVER['NUMBER_LITERAL']));
|
|
|
|
|
+ $this->assertEquals(1111, $_SERVER['NUMBER_LITERAL']);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertTrue(is_string($_SERVER['NUMBER_QUOTED']));
|
|
|
|
|
+ $this->assertEquals('1111', $_SERVER['NUMBER_QUOTED']);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertNull($_SERVER['NULL_LITERAL']);
|
|
|
|
|
+ $this->assertTrue(array_key_exists('NULL_LITERAL', $_SERVER));
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals('null', $_SERVER['NULL_QUOTED']);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals('', $_SERVER['EMPTY_LITERAL']);
|
|
|
|
|
+ $this->assertEquals('', $_SERVER['EMPTY_QUOTED']);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function testFileNotExist() {
|
|
|
|
|
+ $this->expectException(\InvalidArgumentException::class, function () {
|
|
|
|
|
+ (new DotEnv($this->env('.env.not-exists')))->load();
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @runInSeparateProcess
|
|
|
|
|
+ */
|
|
|
|
|
+ public function testIncompatibleProcessors() {
|
|
|
|
|
+ $this->assertProcessors(
|
|
|
|
|
+ [],
|
|
|
|
|
+ []
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertProcessors(
|
|
|
|
|
+ null,
|
|
|
|
|
+ [
|
|
|
|
|
+ NullProcessor::class,
|
|
|
|
|
+ BooleanProcessor::class,
|
|
|
|
|
+ NumberProcessor::class,
|
|
|
|
|
+ QuotedProcessor::class
|
|
|
|
|
+ ]
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertProcessors(
|
|
|
|
|
+ [null],
|
|
|
|
|
+ []
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertProcessors(
|
|
|
|
|
+ [new \stdClass()],
|
|
|
|
|
+ []
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertProcessors(
|
|
|
|
|
+ [QuotedProcessor::class, null],
|
|
|
|
|
+ [QuotedProcessor::class]
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @runInSeparateProcess
|
|
|
|
|
+ */
|
|
|
|
|
+ private function assertProcessors(array $processorsToUse = null, array $expectedProcessors = [])
|
|
|
|
|
+ {
|
|
|
|
|
+ $dotEnv = new DotEnv($this->env('.env.default'), $processorsToUse);
|
|
|
|
|
+ $dotEnv->load();
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals(
|
|
|
|
|
+ $expectedProcessors,
|
|
|
|
|
+ $this->getProtectedProperty($dotEnv)
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function getProtectedProperty(object $object) {
|
|
|
|
|
+ $reflection = new \ReflectionClass($object);
|
|
|
|
|
+ $reflectionProperty = $reflection->getProperty('processors');
|
|
|
|
|
+ $reflectionProperty->setAccessible(true);
|
|
|
|
|
+
|
|
|
|
|
+ return $reflectionProperty->getValue($object);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @runInSeparateProcess
|
|
|
|
|
+ */
|
|
|
|
|
+ public function testProcessBoolean()
|
|
|
|
|
+ {
|
|
|
|
|
+ (new DotEnv($this->env('.env.boolean'), [
|
|
|
|
|
+ BooleanProcessor::class
|
|
|
|
|
+ ]))->load();
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals(false, $_ENV['FALSE1']);
|
|
|
|
|
+ $this->assertEquals(false, $_ENV['FALSE2']);
|
|
|
|
|
+ $this->assertEquals(false, $_ENV['FALSE3']);
|
|
|
|
|
+ $this->assertEquals("'false'", $_ENV['FALSE4']); // Since we don't have the QuotedProcessor::class this will be the result
|
|
|
|
|
+ $this->assertEquals('0', $_ENV['FALSE5']);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals(true, $_ENV['TRUE1']);
|
|
|
|
|
+ $this->assertEquals(true, $_ENV['TRUE2']);
|
|
|
|
|
+ $this->assertEquals(true, $_ENV['TRUE3']);
|
|
|
|
|
+ $this->assertEquals("'true'", $_ENV['TRUE4']); // Since we don't have the QuotedProcessor::class this will be the result
|
|
|
|
|
+ $this->assertEquals('1', $_ENV['TRUE5']);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @runInSeparateProcess
|
|
|
|
|
+ */
|
|
|
|
|
+ public function testDontProcessBoolean()
|
|
|
|
|
+ {
|
|
|
|
|
+ (new DotEnv($this->env('.env.boolean'), []))->load();
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals('false', $_ENV['FALSE1']);
|
|
|
|
|
+ $this->assertEquals('true', $_ENV['TRUE1']);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @runInSeparateProcess
|
|
|
|
|
+ */
|
|
|
|
|
+ public function testProcessQuotes()
|
|
|
|
|
+ {
|
|
|
|
|
+ (new DotEnv($this->env('.env.quotes'), [
|
|
|
|
|
+ QuotedProcessor::class
|
|
|
|
|
+ ]))->load();
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals('q1', $_ENV['QUOTED1']);
|
|
|
|
|
+ $this->assertEquals('q2', $_ENV['QUOTED2']);
|
|
|
|
|
+ $this->assertEquals('"q3"', $_ENV['QUOTED3']);
|
|
|
|
|
+ $this->assertEquals('This is a "sample" value', $_ENV['QUOTED4']);
|
|
|
|
|
+ $this->assertEquals('\"This is a "sample" value\"', $_ENV['QUOTED5']);
|
|
|
|
|
+ $this->assertEquals('"q6', $_ENV['QUOTED6']);
|
|
|
|
|
+ $this->assertEquals('q7"', $_ENV['QUOTED7']);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @runInSeparateProcess
|
|
|
|
|
+ */
|
|
|
|
|
+ public function testDontProcessQuotes()
|
|
|
|
|
+ {
|
|
|
|
|
+ (new DotEnv($this->env('.env.quotes'), []))->load();
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals('"q1"', $_ENV['QUOTED1']);
|
|
|
|
|
+ $this->assertEquals('\'q2\'', $_ENV['QUOTED2']);
|
|
|
|
|
+ $this->assertEquals('""q3""', $_ENV['QUOTED3']);
|
|
|
|
|
+ $this->assertEquals('"This is a "sample" value"', $_ENV['QUOTED4']);
|
|
|
|
|
+ $this->assertEquals('\"This is a "sample" value\"', $_ENV['QUOTED5']);
|
|
|
|
|
+ $this->assertEquals('"q6', $_ENV['QUOTED6']);
|
|
|
|
|
+ $this->assertEquals('q7"', $_ENV['QUOTED7']);
|
|
|
|
|
+ $this->assertEquals('0', $_ENV['ZERO_LITERAL']);
|
|
|
|
|
+ $this->assertEquals('"0"', $_ENV['ZERO_QUOTED']);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @runInSeparateProcess
|
|
|
|
|
+ */
|
|
|
|
|
+ public function testProcessNumbers()
|
|
|
|
|
+ {
|
|
|
|
|
+ (new DotEnv($this->env('.env.number'), [
|
|
|
|
|
+ NumberProcessor::class
|
|
|
|
|
+ ]))->load();
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertEquals(0, $_ENV['NUMBER1']);
|
|
|
|
|
+ $this->assertTrue(is_numeric($_ENV['NUMBER1']));
|
|
|
|
|
+ $this->assertEquals(0.0001, $_ENV['NUMBER2']);
|
|
|
|
|
+ $this->assertEquals(123456789, $_ENV['NUMBER3']);
|
|
|
|
|
+ $this->assertEquals(123456789.0, $_ENV['NUMBER4']);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|