DotenvTest.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <?php
  2. namespace Test\Michel\Env;
  3. use Michel\Env\DotEnv;
  4. use Michel\Env\Processor\BooleanProcessor;
  5. use Michel\Env\Processor\NullProcessor;
  6. use Michel\Env\Processor\NumberProcessor;
  7. use Michel\Env\Processor\QuotedProcessor;
  8. use Michel\UniTester\TestCase;
  9. class DotenvTest extends TestCase
  10. {
  11. protected function setUp(): void
  12. {
  13. // TODO: Implement setUp() method.
  14. }
  15. protected function tearDown(): void
  16. {
  17. $this->clearAllEnv();
  18. }
  19. private function clearAllEnv(): void
  20. {
  21. foreach ($_ENV as $key => $value) {
  22. unset($_ENV[$key]);
  23. }
  24. foreach ($_SERVER as $key => $value) {
  25. unset($_SERVER[$key]);
  26. }
  27. }
  28. protected function execute(): void
  29. {
  30. $this->clearAllEnv();
  31. $this->testLoad();
  32. $this->clearAllEnv();
  33. $this->testFileNotExist();
  34. $this->clearAllEnv();
  35. $this->testIncompatibleProcessors();
  36. $this->clearAllEnv();
  37. $this->testProcessBoolean();
  38. $this->clearAllEnv();
  39. $this->testDontProcessBoolean();
  40. $this->clearAllEnv();
  41. $this->testProcessQuotes();
  42. $this->clearAllEnv();
  43. $this->testDontProcessQuotes();
  44. $this->clearAllEnv();
  45. $this->testProcessNumbers();
  46. }
  47. private function env(string $file)
  48. {
  49. return __DIR__ . DIRECTORY_SEPARATOR . 'env' . DIRECTORY_SEPARATOR . $file;
  50. }
  51. /**
  52. * @runInSeparateProcess
  53. */
  54. public function testLoad() {
  55. (new DotEnv($this->env('.env.default')))->load();
  56. $this->assertEquals('dev', getenv('APP_ENV'));
  57. $this->assertEquals('mysql:host=localhost;dbname=test;', getenv('DATABASE_DNS'));
  58. $this->assertEquals('root', getenv('DATABASE_USER'));
  59. $this->assertEquals('password', getenv('DATABASE_PASSWORD'));
  60. $this->assertFalse(getenv('GOOGLE_API'));
  61. $this->assertFalse(getenv('GOOGLE_MANAGER_KEY'));
  62. $this->assertEquals(true, getenv('BOOLEAN_LITERAL'));
  63. $this->assertEquals('true', getenv('BOOLEAN_QUOTED'));
  64. $this->assertEquals('dev', $_ENV['APP_ENV']);
  65. $this->assertEquals('password', $_ENV['DATABASE_PASSWORD']);
  66. $this->assertFalse(array_key_exists('GOOGLE_API', $_ENV));
  67. $this->assertFalse(array_key_exists('GOOGLE_MANAGER_KEY', $_ENV));
  68. $this->assertEquals(true, $_ENV['BOOLEAN_LITERAL']);
  69. $this->assertEquals('true', $_ENV['BOOLEAN_QUOTED']);
  70. $this->assertEquals('mysql:host=localhost;dbname=test;', $_SERVER['DATABASE_DNS']);
  71. $this->assertEquals('root', $_SERVER['DATABASE_USER']);
  72. $this->assertEquals('password', $_SERVER['DATABASE_PASSWORD']);
  73. $this->assertFalse(array_key_exists('GOOGLE_API', $_SERVER));
  74. $this->assertFalse(array_key_exists('GOOGLE_MANAGER_KEY', $_SERVER));
  75. $this->assertEquals(true, $_SERVER['BOOLEAN_LITERAL']);
  76. $this->assertEquals('true', $_SERVER['BOOLEAN_QUOTED']);
  77. $this->assertEquals('🪄', $_SERVER['EMOJI']);
  78. $this->assertTrue(is_int($_SERVER['ZERO_LITERAL']));
  79. $this->assertEquals(0, $_SERVER['ZERO_LITERAL']);
  80. $this->assertTrue(is_string($_SERVER['ZERO_QUOTED']));
  81. $this->assertEquals('0', $_SERVER['ZERO_QUOTED']);
  82. $this->assertTrue(is_int($_SERVER['NUMBER_LITERAL']));
  83. $this->assertEquals(1111, $_SERVER['NUMBER_LITERAL']);
  84. $this->assertTrue(is_string($_SERVER['NUMBER_QUOTED']));
  85. $this->assertEquals('1111', $_SERVER['NUMBER_QUOTED']);
  86. $this->assertNull($_SERVER['NULL_LITERAL']);
  87. $this->assertTrue(array_key_exists('NULL_LITERAL', $_SERVER));
  88. $this->assertEquals('null', $_SERVER['NULL_QUOTED']);
  89. $this->assertEquals('', $_SERVER['EMPTY_LITERAL']);
  90. $this->assertEquals('', $_SERVER['EMPTY_QUOTED']);
  91. }
  92. public function testFileNotExist() {
  93. $this->expectException(\InvalidArgumentException::class, function () {
  94. (new DotEnv($this->env('.env.not-exists')))->load();
  95. });
  96. }
  97. /**
  98. * @runInSeparateProcess
  99. */
  100. public function testIncompatibleProcessors() {
  101. $this->assertProcessors(
  102. [],
  103. []
  104. );
  105. $this->assertProcessors(
  106. null,
  107. [
  108. NullProcessor::class,
  109. BooleanProcessor::class,
  110. NumberProcessor::class,
  111. QuotedProcessor::class
  112. ]
  113. );
  114. $this->assertProcessors(
  115. [null],
  116. []
  117. );
  118. $this->assertProcessors(
  119. [new \stdClass()],
  120. []
  121. );
  122. $this->assertProcessors(
  123. [QuotedProcessor::class, null],
  124. [QuotedProcessor::class]
  125. );
  126. }
  127. /**
  128. * @runInSeparateProcess
  129. */
  130. private function assertProcessors(array $processorsToUse = null, array $expectedProcessors = [])
  131. {
  132. $dotEnv = new DotEnv($this->env('.env.default'), $processorsToUse);
  133. $dotEnv->load();
  134. $this->assertEquals(
  135. $expectedProcessors,
  136. $this->getProtectedProperty($dotEnv)
  137. );
  138. }
  139. private function getProtectedProperty(object $object) {
  140. $reflection = new \ReflectionClass($object);
  141. $reflectionProperty = $reflection->getProperty('processors');
  142. $reflectionProperty->setAccessible(true);
  143. return $reflectionProperty->getValue($object);
  144. }
  145. /**
  146. * @runInSeparateProcess
  147. */
  148. public function testProcessBoolean()
  149. {
  150. (new DotEnv($this->env('.env.boolean'), [
  151. BooleanProcessor::class
  152. ]))->load();
  153. $this->assertEquals(false, $_ENV['FALSE1']);
  154. $this->assertEquals(false, $_ENV['FALSE2']);
  155. $this->assertEquals(false, $_ENV['FALSE3']);
  156. $this->assertEquals("'false'", $_ENV['FALSE4']); // Since we don't have the QuotedProcessor::class this will be the result
  157. $this->assertEquals('0', $_ENV['FALSE5']);
  158. $this->assertEquals(true, $_ENV['TRUE1']);
  159. $this->assertEquals(true, $_ENV['TRUE2']);
  160. $this->assertEquals(true, $_ENV['TRUE3']);
  161. $this->assertEquals("'true'", $_ENV['TRUE4']); // Since we don't have the QuotedProcessor::class this will be the result
  162. $this->assertEquals('1', $_ENV['TRUE5']);
  163. }
  164. /**
  165. * @runInSeparateProcess
  166. */
  167. public function testDontProcessBoolean()
  168. {
  169. (new DotEnv($this->env('.env.boolean'), []))->load();
  170. $this->assertEquals('false', $_ENV['FALSE1']);
  171. $this->assertEquals('true', $_ENV['TRUE1']);
  172. }
  173. /**
  174. * @runInSeparateProcess
  175. */
  176. public function testProcessQuotes()
  177. {
  178. (new DotEnv($this->env('.env.quotes'), [
  179. QuotedProcessor::class
  180. ]))->load();
  181. $this->assertEquals('q1', $_ENV['QUOTED1']);
  182. $this->assertEquals('q2', $_ENV['QUOTED2']);
  183. $this->assertEquals('"q3"', $_ENV['QUOTED3']);
  184. $this->assertEquals('This is a "sample" value', $_ENV['QUOTED4']);
  185. $this->assertEquals('\"This is a "sample" value\"', $_ENV['QUOTED5']);
  186. $this->assertEquals('"q6', $_ENV['QUOTED6']);
  187. $this->assertEquals('q7"', $_ENV['QUOTED7']);
  188. }
  189. /**
  190. * @runInSeparateProcess
  191. */
  192. public function testDontProcessQuotes()
  193. {
  194. (new DotEnv($this->env('.env.quotes'), []))->load();
  195. $this->assertEquals('"q1"', $_ENV['QUOTED1']);
  196. $this->assertEquals('\'q2\'', $_ENV['QUOTED2']);
  197. $this->assertEquals('""q3""', $_ENV['QUOTED3']);
  198. $this->assertEquals('"This is a "sample" value"', $_ENV['QUOTED4']);
  199. $this->assertEquals('\"This is a "sample" value\"', $_ENV['QUOTED5']);
  200. $this->assertEquals('"q6', $_ENV['QUOTED6']);
  201. $this->assertEquals('q7"', $_ENV['QUOTED7']);
  202. $this->assertEquals('0', $_ENV['ZERO_LITERAL']);
  203. $this->assertEquals('"0"', $_ENV['ZERO_QUOTED']);
  204. }
  205. /**
  206. * @runInSeparateProcess
  207. */
  208. public function testProcessNumbers()
  209. {
  210. (new DotEnv($this->env('.env.number'), [
  211. NumberProcessor::class
  212. ]))->load();
  213. $this->assertEquals(0, $_ENV['NUMBER1']);
  214. $this->assertTrue(is_numeric($_ENV['NUMBER1']));
  215. $this->assertEquals(0.0001, $_ENV['NUMBER2']);
  216. $this->assertEquals(123456789, $_ENV['NUMBER3']);
  217. $this->assertEquals(123456789.0, $_ENV['NUMBER4']);
  218. }
  219. }