ValidatorTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. <?php
  2. declare(strict_types=1);
  3. namespace Dotenv\Tests;
  4. use Dotenv\Dotenv;
  5. use Dotenv\Exception\ValidationException;
  6. use Dotenv\Repository\Adapter\ArrayAdapter;
  7. use Dotenv\Repository\RepositoryBuilder;
  8. use PHPUnit\Framework\TestCase;
  9. final class ValidatorTest extends TestCase
  10. {
  11. /**
  12. * @var string
  13. */
  14. private static $folder;
  15. /**
  16. * @beforeClass
  17. *
  18. * @return void
  19. */
  20. public static function setFolder()
  21. {
  22. self::$folder = \dirname(__DIR__).'/fixtures/env';
  23. }
  24. /**
  25. * @param string $name
  26. *
  27. * @return array{\Dotenv\Repository\RepositoryInterface,\Dotenv\Dotenv}
  28. */
  29. public static function createArrayDotenv(string $name = '.env')
  30. {
  31. $repository = RepositoryBuilder::createWithNoAdapters()->addAdapter(ArrayAdapter::class)->make();
  32. return [$repository, Dotenv::create($repository, self::$folder, $name)];
  33. }
  34. /**
  35. * @doesNotPerformAssertions
  36. */
  37. public function testDotenvRequiredStringEnvironmentVars()
  38. {
  39. $dotenv = self::createArrayDotenv()[1];
  40. $dotenv->load();
  41. $dotenv->required('FOO');
  42. }
  43. /**
  44. * @doesNotPerformAssertions
  45. */
  46. public function testDotenvAllowedValues()
  47. {
  48. $dotenv = self::createArrayDotenv()[1];
  49. $dotenv->load();
  50. $dotenv->required('FOO')->allowedValues(['bar', 'baz']);
  51. }
  52. /**
  53. * @doesNotPerformAssertions
  54. */
  55. public function testDotenvAllowedValuesIfPresent()
  56. {
  57. $dotenv = self::createArrayDotenv()[1];
  58. $dotenv->load();
  59. $dotenv->ifPresent('FOO')->allowedValues(['bar', 'baz']);
  60. }
  61. /**
  62. * @doesNotPerformAssertions
  63. */
  64. public function testDotenvAllowedValuesIfNotPresent()
  65. {
  66. $dotenv = self::createArrayDotenv()[1];
  67. $dotenv->load();
  68. $dotenv->ifPresent('FOOQWERTYOOOOOO')->allowedValues(['bar', 'baz']);
  69. }
  70. public function testDotenvProhibitedValues()
  71. {
  72. $dotenv = self::createArrayDotenv()[1];
  73. $dotenv->load();
  74. $this->expectException(ValidationException::class);
  75. $this->expectExceptionMessage('One or more environment variables failed assertions: FOO is not one of [buzz, buz].');
  76. $dotenv->required('FOO')->allowedValues(['buzz', 'buz']);
  77. }
  78. public function testDotenvProhibitedValuesIfPresent()
  79. {
  80. $dotenv = self::createArrayDotenv()[1];
  81. $dotenv->load();
  82. $this->expectException(ValidationException::class);
  83. $this->expectExceptionMessage('One or more environment variables failed assertions: FOO is not one of [buzz, buz].');
  84. $dotenv->ifPresent('FOO')->allowedValues(['buzz', 'buz']);
  85. }
  86. public function testDotenvRequiredThrowsRuntimeException()
  87. {
  88. [$repo, $dotenv] = self::createArrayDotenv();
  89. $dotenv->load();
  90. self::assertFalse($repo->has('FOOX'));
  91. self::assertFalse($repo->has('NOPE'));
  92. $this->expectException(ValidationException::class);
  93. $this->expectExceptionMessage('One or more environment variables failed assertions: FOOX is missing, NOPE is missing.');
  94. $dotenv->required(['FOOX', 'NOPE']);
  95. }
  96. /**
  97. * @doesNotPerformAssertions
  98. */
  99. public function testDotenvRequiredArrayEnvironmentVars()
  100. {
  101. $dotenv = self::createArrayDotenv()[1];
  102. $dotenv->load();
  103. $dotenv->required(['FOO', 'BAR']);
  104. }
  105. public function testDotenvAssertions()
  106. {
  107. [$repo, $dotenv] = self::createArrayDotenv('assertions.env');
  108. $dotenv->load();
  109. self::assertSame('val1', $repo->get('ASSERTVAR1'));
  110. self::assertSame('', $repo->get('ASSERTVAR2'));
  111. self::assertSame('val3 ', $repo->get('ASSERTVAR3'));
  112. self::assertSame('0', $repo->get('ASSERTVAR4'));
  113. self::assertSame('#foo', $repo->get('ASSERTVAR5'));
  114. self::assertSame("val1\nval2", $repo->get('ASSERTVAR6'));
  115. self::assertSame("\nval3", $repo->get('ASSERTVAR7'));
  116. self::assertSame("val3\n", $repo->get('ASSERTVAR8'));
  117. $dotenv->required([
  118. 'ASSERTVAR1',
  119. 'ASSERTVAR2',
  120. 'ASSERTVAR3',
  121. 'ASSERTVAR4',
  122. 'ASSERTVAR5',
  123. 'ASSERTVAR6',
  124. 'ASSERTVAR7',
  125. 'ASSERTVAR8',
  126. 'ASSERTVAR9',
  127. ]);
  128. $dotenv->required([
  129. 'ASSERTVAR1',
  130. 'ASSERTVAR3',
  131. 'ASSERTVAR4',
  132. 'ASSERTVAR5',
  133. 'ASSERTVAR6',
  134. 'ASSERTVAR7',
  135. 'ASSERTVAR8',
  136. ])->notEmpty();
  137. $dotenv->required([
  138. 'ASSERTVAR1',
  139. 'ASSERTVAR4',
  140. 'ASSERTVAR5',
  141. ])->notEmpty()->allowedValues(['0', 'val1', '#foo']);
  142. }
  143. public function testDotenvEmptyThrowsRuntimeException()
  144. {
  145. $dotenv = self::createArrayDotenv('assertions.env')[1];
  146. $dotenv->load();
  147. $this->expectException(ValidationException::class);
  148. $this->expectExceptionMessage('One or more environment variables failed assertions: ASSERTVAR2 is empty.');
  149. $dotenv->required('ASSERTVAR2')->notEmpty();
  150. }
  151. /**
  152. * @doesNotPerformAssertions
  153. */
  154. public function testDotenvEmptyWhenNotPresent()
  155. {
  156. $dotenv = self::createArrayDotenv('assertions.env')[1];
  157. $dotenv->load();
  158. $dotenv->ifPresent('ASSERTVAR2_NO_SUCH_VARIABLE')->notEmpty();
  159. }
  160. public function testDotenvStringOfSpacesConsideredEmpty()
  161. {
  162. $dotenv = self::createArrayDotenv('assertions.env')[1];
  163. $dotenv->load();
  164. $this->expectException(ValidationException::class);
  165. $this->expectExceptionMessage('One or more environment variables failed assertions: ASSERTVAR9 is empty.');
  166. $dotenv->required('ASSERTVAR9')->notEmpty();
  167. }
  168. /**
  169. * List of valid boolean values in fixtures/env/booleans.env.
  170. *
  171. * @return string[][]
  172. */
  173. public static function validBooleanValuesDataProvider()
  174. {
  175. return [
  176. ['VALID_EXPLICIT_LOWERCASE_TRUE'],
  177. ['VALID_EXPLICIT_LOWERCASE_FALSE'],
  178. ['VALID_EXPLICIT_UPPERCASE_TRUE'],
  179. ['VALID_EXPLICIT_UPPERCASE_FALSE'],
  180. ['VALID_EXPLICIT_MIXEDCASE_TRUE'],
  181. ['VALID_EXPLICIT_MIXEDCASE_FALSE'],
  182. ['VALID_NUMBER_TRUE'],
  183. ['VALID_NUMBER_FALSE'],
  184. ['VALID_ONOFF_LOWERCASE_TRUE'],
  185. ['VALID_ONOFF_LOWERCASE_FALSE'],
  186. ['VALID_ONOFF_UPPERCASE_TRUE'],
  187. ['VALID_ONOFF_UPPERCASE_FALSE'],
  188. ['VALID_ONOFF_MIXEDCASE_TRUE'],
  189. ['VALID_ONOFF_MIXEDCASE_FALSE'],
  190. ['VALID_YESNO_LOWERCASE_TRUE'],
  191. ['VALID_YESNO_LOWERCASE_FALSE'],
  192. ['VALID_YESNO_UPPERCASE_TRUE'],
  193. ['VALID_YESNO_UPPERCASE_FALSE'],
  194. ['VALID_YESNO_MIXEDCASE_TRUE'],
  195. ['VALID_YESNO_MIXEDCASE_FALSE'],
  196. ];
  197. }
  198. /**
  199. * @dataProvider validBooleanValuesDataProvider
  200. * @doesNotPerformAssertions
  201. */
  202. public function testCanValidateBooleans(string $boolean)
  203. {
  204. $dotenv = Dotenv::createImmutable(self::$folder, 'booleans.env');
  205. $dotenv->load();
  206. $dotenv->required($boolean)->isBoolean();
  207. }
  208. /**
  209. * @dataProvider validBooleanValuesDataProvider
  210. * @doesNotPerformAssertions
  211. */
  212. public function testCanValidateBooleansIfPresent(string $boolean)
  213. {
  214. $dotenv = Dotenv::createImmutable(self::$folder, 'booleans.env');
  215. $dotenv->load();
  216. $dotenv->ifPresent($boolean)->isBoolean();
  217. }
  218. /**
  219. * List of non-boolean values in fixtures/env/booleans.env.
  220. *
  221. * @return string[][]
  222. */
  223. public static function invalidBooleanValuesDataProvider()
  224. {
  225. return [
  226. ['INVALID_SOMETHING'],
  227. ['INVALID_EMPTY'],
  228. ['INVALID_EMPTY_STRING'],
  229. ['INVALID_NULL'],
  230. ['INVALID_NUMBER_POSITIVE'],
  231. ['INVALID_NUMBER_NEGATIVE'],
  232. ['INVALID_MINUS'],
  233. ['INVALID_TILDA'],
  234. ['INVALID_EXCLAMATION'],
  235. ];
  236. }
  237. /**
  238. * @dataProvider invalidBooleanValuesDataProvider
  239. */
  240. public function testCanInvalidateNonBooleans(string $boolean)
  241. {
  242. $dotenv = Dotenv::createImmutable(self::$folder, 'booleans.env');
  243. $dotenv->load();
  244. $this->expectException(ValidationException::class);
  245. $this->expectExceptionMessage('One or more environment variables failed assertions: INVALID_');
  246. $dotenv->required($boolean)->isBoolean();
  247. }
  248. /**
  249. * @dataProvider invalidBooleanValuesDataProvider
  250. */
  251. public function testCanInvalidateNonBooleansIfPresent(string $boolean)
  252. {
  253. $dotenv = Dotenv::createImmutable(self::$folder, 'booleans.env');
  254. $dotenv->load();
  255. $this->expectException(ValidationException::class);
  256. $this->expectExceptionMessage('One or more environment variables failed assertions: INVALID_');
  257. $dotenv->ifPresent($boolean)->isBoolean();
  258. }
  259. public function testCanInvalidateBooleanNonExist()
  260. {
  261. $dotenv = Dotenv::createImmutable(self::$folder, 'booleans.env');
  262. $dotenv->load();
  263. $this->expectException(ValidationException::class);
  264. $this->expectExceptionMessage('One or more environment variables failed assertions: VAR_DOES_NOT_EXIST_234782462764');
  265. $dotenv->required(['VAR_DOES_NOT_EXIST_234782462764'])->isBoolean();
  266. }
  267. /**
  268. * @doesNotPerformAssertions
  269. */
  270. public function testIfPresentBooleanNonExist()
  271. {
  272. $dotenv = Dotenv::createImmutable(self::$folder, 'booleans.env');
  273. $dotenv->load();
  274. $dotenv->ifPresent(['VAR_DOES_NOT_EXIST_234782462764'])->isBoolean();
  275. }
  276. /**
  277. * List of valid integer values in fixtures/env/integers.env.
  278. *
  279. * @return string[][]
  280. */
  281. public static function validIntegerValuesDataProvider()
  282. {
  283. return [
  284. ['VALID_ZERO'],
  285. ['VALID_ONE'],
  286. ['VALID_TWO'],
  287. ['VALID_LARGE'],
  288. ['VALID_HUGE'],
  289. ];
  290. }
  291. /**
  292. * @dataProvider validIntegerValuesDataProvider
  293. * @doesNotPerformAssertions
  294. */
  295. public function testCanValidateIntegers(string $integer)
  296. {
  297. $dotenv = Dotenv::createImmutable(self::$folder, 'integers.env');
  298. $dotenv->load();
  299. $dotenv->required($integer)->isInteger();
  300. }
  301. /**
  302. * @dataProvider validIntegerValuesDataProvider
  303. * @doesNotPerformAssertions
  304. */
  305. public function testCanValidateIntegersIfPresent(string $integer)
  306. {
  307. $dotenv = Dotenv::createImmutable(self::$folder, 'integers.env');
  308. $dotenv->load();
  309. $dotenv->ifPresent($integer)->isInteger();
  310. }
  311. /**
  312. * List of non-integer values in fixtures/env/integers.env.
  313. *
  314. * @return string[][]
  315. */
  316. public static function invalidIntegerValuesDataProvider()
  317. {
  318. return [
  319. ['INVALID_SOMETHING'],
  320. ['INVALID_EMPTY'],
  321. ['INVALID_EMPTY_STRING'],
  322. ['INVALID_NULL'],
  323. ['INVALID_NEGATIVE'],
  324. ['INVALID_MINUS'],
  325. ['INVALID_TILDA'],
  326. ['INVALID_EXCLAMATION'],
  327. ['INVALID_SPACES'],
  328. ['INVALID_COMMAS'],
  329. ];
  330. }
  331. /**
  332. * @dataProvider invalidIntegerValuesDataProvider
  333. */
  334. public function testCanInvalidateNonIntegers(string $integer)
  335. {
  336. $dotenv = Dotenv::createImmutable(self::$folder, 'integers.env');
  337. $dotenv->load();
  338. $this->expectException(ValidationException::class);
  339. $this->expectExceptionMessage('One or more environment variables failed assertions: INVALID_');
  340. $dotenv->required($integer)->isInteger();
  341. }
  342. /**
  343. * @dataProvider invalidIntegerValuesDataProvider
  344. */
  345. public function testCanInvalidateNonIntegersIfExist(string $integer)
  346. {
  347. $dotenv = Dotenv::createImmutable(self::$folder, 'integers.env');
  348. $dotenv->load();
  349. $this->expectException(ValidationException::class);
  350. $this->expectExceptionMessage('One or more environment variables failed assertions: INVALID_');
  351. $dotenv->ifPresent($integer)->isInteger();
  352. }
  353. public function testCanInvalidateIntegerNonExist()
  354. {
  355. $dotenv = Dotenv::createImmutable(self::$folder, 'integers.env');
  356. $dotenv->load();
  357. $this->expectException(ValidationException::class);
  358. $this->expectExceptionMessage('One or more environment variables failed assertions: VAR_DOES_NOT_EXIST_234782462764');
  359. $dotenv->required(['VAR_DOES_NOT_EXIST_234782462764'])->isInteger();
  360. }
  361. /**
  362. * @doesNotPerformAssertions
  363. */
  364. public function testIfPresentIntegerNonExist()
  365. {
  366. $dotenv = Dotenv::createImmutable(self::$folder, 'integers.env');
  367. $dotenv->load();
  368. $dotenv->ifPresent(['VAR_DOES_NOT_EXIST_234782462764'])->isInteger();
  369. }
  370. /**
  371. * @doesNotPerformAssertions
  372. */
  373. public function testDotenvRegexMatchPass()
  374. {
  375. $dotenv = Dotenv::createImmutable(self::$folder);
  376. $dotenv->load();
  377. $dotenv->required('FOO')->allowedRegexValues('([[:lower:]]{3})');
  378. }
  379. public function testDotenvRegexMatchFail()
  380. {
  381. $dotenv = Dotenv::createImmutable(self::$folder);
  382. $dotenv->load();
  383. $this->expectException(ValidationException::class);
  384. $this->expectExceptionMessage('One or more environment variables failed assertions: FOO does not match "/^([[:lower:]]{1})$/".');
  385. $dotenv->required('FOO')->allowedRegexValues('/^([[:lower:]]{1})$/');
  386. }
  387. public function testDotenvRegexMatchError()
  388. {
  389. $dotenv = Dotenv::createImmutable(self::$folder);
  390. $dotenv->load();
  391. $this->expectException(ValidationException::class);
  392. $this->expectExceptionMessage('One or more environment variables failed assertions: FOO does not match "/([[:lower:]{1{".');
  393. $dotenv->required('FOO')->allowedRegexValues('/([[:lower:]{1{');
  394. }
  395. /**
  396. * @doesNotPerformAssertions
  397. */
  398. public function testDotenvRegexMatchNotPresent()
  399. {
  400. $dotenv = Dotenv::createImmutable(self::$folder);
  401. $dotenv->load();
  402. $dotenv->ifPresent('FOOOOOOOOOOO')->allowedRegexValues('([[:lower:]]{3})');
  403. }
  404. }