ArgumentTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. <?php
  2. namespace League\CLImate\Tests\Argument;
  3. use League\CLImate\Argument\Argument;
  4. use League\CLImate\Exceptions\InvalidArgumentException;
  5. use League\CLImate\Exceptions\UnexpectedValueException;
  6. use League\CLImate\Tests\TestBase;
  7. class ArgumentTest extends TestBase
  8. {
  9. /** @test */
  10. public function it_throws_an_exception_when_setting_an_unknown_cast_type()
  11. {
  12. $this->expectException(UnexpectedValueException::class);
  13. $this->expectExceptionMessage("An argument may only be cast to the data type 'string', 'int', 'float', or 'bool'.");
  14. Argument::createFromArray('invalid-cast-type', [
  15. 'castTo' => 'invalid',
  16. ]);
  17. }
  18. /** @test */
  19. public function it_throws_an_exception_when_building_arguments_from_an_unknown_type()
  20. {
  21. $this->expectException(InvalidArgumentException::class);
  22. $this->expectExceptionMessage("Please provide an argument name or object.");
  23. $this->cli->arguments->add(new \stdClass());
  24. }
  25. protected function getFullArguments()
  26. {
  27. return [
  28. 'only-short-prefix' => [
  29. 'prefix' => 's',
  30. 'description' => 'Only short prefix',
  31. ],
  32. 'only-long-prefix' => [
  33. 'longPrefix' => 'long',
  34. 'description' => 'Only long prefix',
  35. ],
  36. 'both-prefixes' => [
  37. 'prefix' => 'b',
  38. 'longPrefix' => 'both',
  39. 'description' => 'Both short and long prefixes',
  40. ],
  41. 'no-prefix' => [
  42. 'description' => 'Not defined by a prefix',
  43. ],
  44. 'defined-only' => [
  45. 'prefix' => 'd',
  46. 'longPrefix' => 'defined',
  47. 'description' => 'True when defined',
  48. 'noValue' => true,
  49. ],
  50. 'required' => [
  51. 'prefix' => 'r',
  52. 'description' => 'Required',
  53. 'required' => true,
  54. ],
  55. 'default-value' => [
  56. 'prefix' => 'v',
  57. 'description' => 'Has a default value',
  58. 'defaultValue' => 'test',
  59. ],
  60. 'default-value2' => [
  61. 'prefix' => 'x',
  62. 'description' => 'Has also a default value',
  63. 'defaultValue' => ['test2', 'test3'],
  64. ],
  65. ];
  66. }
  67. public function testCanCastToString(): void
  68. {
  69. $argument = Argument::createFromArray('test', [
  70. 'castTo' => 'string',
  71. ]);
  72. $argument->setValue('a string');
  73. self::assertSame('a string', $argument->value());
  74. }
  75. public function testCanCastToInteger(): void
  76. {
  77. $argument = Argument::createFromArray('test', [
  78. 'castTo' => 'int',
  79. ]);
  80. $argument->setValue('1234');
  81. self::assertSame(1234, $argument->value());
  82. }
  83. public function testCanCastToFloat(): void
  84. {
  85. $argument = Argument::createFromArray('test', [
  86. 'castTo' => 'float',
  87. ]);
  88. $argument->setValue('12.34');
  89. self::assertSame(12.34, $argument->value());
  90. }
  91. public function testCanCastToBool(): void
  92. {
  93. $argument = Argument::createFromArray('test', [
  94. 'castTo' => 'bool',
  95. ]);
  96. $argument->setValue('1');
  97. self::assertSame(true, $argument->value());
  98. }
  99. /** @test */
  100. public function it_casts_to_bool_when_defined_only()
  101. {
  102. $argument = Argument::createFromArray('invalid-cast-type', [
  103. 'noValue' => true,
  104. ]);
  105. $this->assertEquals('bool', $argument->castTo());
  106. }
  107. /**
  108. * @test
  109. */
  110. public function it_casts_to_bool_when_defined_only_true()
  111. {
  112. $argument = Argument::createFromArray('invalid-cast-type', [
  113. 'noValue' => false,
  114. ]);
  115. $this->assertNotEquals('bool', $argument->castTo());
  116. }
  117. /**
  118. * @test
  119. * @doesNotPerformAssertions
  120. */
  121. public function it_builds_arguments_from_a_single_array()
  122. {
  123. // Test Description
  124. //
  125. // Usage: test-script [-b both-prefixes, --both both-prefixes] [-d, --defined] [--long only-long-prefix] [-r required] [-s only-short-prefix] [-v default-value (default: test)] [-x default-value2 (defaults: test2, test3)] [no-prefix]
  126. //
  127. // Required Arguments:
  128. // -r required
  129. // Required
  130. //
  131. // Optional Arguments:
  132. // -b both-prefixes, --both both-prefixes
  133. // Both short and long prefixes
  134. // -d, --defined
  135. // True when defined
  136. // -s only-short-prefix
  137. // Only short prefix
  138. // --long only-long-prefix
  139. // Only long prefix
  140. // -v default-value (default: test)
  141. // Has a default value
  142. // -x default-value2 (defaults: test2, test3)
  143. // Has also a default value
  144. // no-prefix
  145. // Not defined by a prefix
  146. $this->output->shouldReceive("sameLine");
  147. $this->shouldWrite("\e[mTest Description\e[0m");
  148. $this->shouldWrite("\e[m\e[0m");
  149. $this->shouldWrite("\e[mUsage: test-script "
  150. . "[-b both-prefixes, --both both-prefixes] [-d, --defined] "
  151. . "[--long only-long-prefix] [-r required] [-s only-short-prefix] "
  152. . "[-v default-value (default: test)] [-x default-value2 (defaults: test2, test3)] [no-prefix]\e[0m");
  153. $this->shouldWrite("\e[m\e[0m");
  154. $this->shouldWrite("\e[mRequired Arguments:\e[0m");
  155. $this->shouldWrite("\e[m\t\e[0m");
  156. $this->shouldWrite("\e[m-r required\e[0m");
  157. $this->shouldWrite("\e[m\t\t\e[0m");
  158. $this->shouldWrite("\e[mRequired\e[0m");
  159. $this->shouldWrite("\e[m\e[0m");
  160. $this->shouldWrite("\e[mOptional Arguments:\e[0m");
  161. $this->shouldWrite("\e[m\t\e[0m");
  162. $this->shouldWrite("\e[m-b both-prefixes, --both both-prefixes\e[0m");
  163. $this->shouldWrite("\e[m\t\t\e[0m");
  164. $this->shouldWrite("\e[mBoth short and long prefixes\e[0m");
  165. $this->shouldWrite("\e[m\t\e[0m");
  166. $this->shouldWrite("\e[m-d, --defined\e[0m");
  167. $this->shouldWrite("\e[m\t\t\e[0m");
  168. $this->shouldWrite("\e[mTrue when defined\e[0m");
  169. $this->shouldWrite("\e[m\t\e[0m");
  170. $this->shouldWrite("\e[m--long only-long-prefix\e[0m");
  171. $this->shouldWrite("\e[m\t\t\e[0m");
  172. $this->shouldWrite("\e[mOnly long prefix\e[0m");
  173. $this->shouldWrite("\e[m\t\e[0m");
  174. $this->shouldWrite("\e[m-s only-short-prefix\e[0m");
  175. $this->shouldWrite("\e[m\t\t\e[0m");
  176. $this->shouldWrite("\e[mOnly short prefix\e[0m");
  177. $this->shouldWrite("\e[m\t\e[0m");
  178. $this->shouldWrite("\e[m-v default-value (default: test)\e[0m");
  179. $this->shouldWrite("\e[m\t\t\e[0m");
  180. $this->shouldWrite("\e[mHas a default value\e[0m");
  181. $this->shouldWrite("\e[m\t\e[0m");
  182. $this->shouldWrite("\e[m-x default-value2 (defaults: test2, test3)\e[0m");
  183. $this->shouldWrite("\e[m\t\t\e[0m");
  184. $this->shouldWrite("\e[mHas also a default value\e[0m");
  185. $this->shouldWrite("\e[m\t\e[0m");
  186. $this->shouldWrite("\e[mno-prefix\e[0m");
  187. $this->shouldWrite("\e[m\t\t\e[0m");
  188. $this->shouldWrite("\e[mNot defined by a prefix\e[0m");
  189. $this->shouldHavePersisted(39);
  190. $this->cli->description('Test Description');
  191. $this->cli->arguments->add($this->getFullArguments());
  192. $command = 'test-script';
  193. $this->cli->usage([$command]);
  194. }
  195. /** @test */
  196. public function it_can_parse_arguments()
  197. {
  198. $this->cli->arguments->add([
  199. 'only-short-prefix' => [
  200. 'prefix' => 's',
  201. ],
  202. 'only-long-prefix' => [
  203. 'longPrefix' => 'long',
  204. ],
  205. 'both-prefixes' => [
  206. 'prefix' => 'b',
  207. 'longPrefix' => 'both',
  208. ],
  209. 'both-equals' => [
  210. 'longPrefix' => 'both-equals',
  211. ],
  212. 'no-prefix' => [],
  213. 'defined-only' => [
  214. 'prefix' => 'd',
  215. 'longPrefix' => 'defined',
  216. 'noValue' => true,
  217. ],
  218. ]);
  219. $argv = [
  220. 'test-script',
  221. '-s=baz',
  222. '-s',
  223. 'foo',
  224. '--long',
  225. 'bar',
  226. '-b=both',
  227. '-d',
  228. '--both-equals=both_equals',
  229. 'no_prefix_value',
  230. '-unknown',
  231. 'after_non_prefixed'
  232. ];
  233. $this->cli->arguments->parse($argv);
  234. $processed = $this->cli->arguments->toArray();
  235. $this->assertCount(6, $processed);
  236. $this->assertEquals('foo', $processed['only-short-prefix']);
  237. $this->assertEquals('bar', $processed['only-long-prefix']);
  238. $this->assertEquals('both', $processed['both-prefixes']);
  239. $this->assertEquals('both_equals', $processed['both-equals']);
  240. $this->assertEquals('no_prefix_value', $processed['no-prefix']);
  241. $this->assertTrue($processed['defined-only']);
  242. $this->assertEquals('foo', $this->cli->arguments->get('only-short-prefix'));
  243. $this->assertEquals(['baz', 'foo'], $this->cli->arguments->getArray('only-short-prefix'));
  244. }
  245. /** @test */
  246. public function it_will_get_a_default_value_for_a_long_prefix_with_no_value()
  247. {
  248. $this->cli->arguments->add([
  249. 'only-long-prefix' => [
  250. 'longPrefix' => 'long',
  251. 'defaultValue' => 'HEY',
  252. ],
  253. ]);
  254. $argv = [
  255. 'test-script',
  256. '--long',
  257. ];
  258. $this->cli->arguments->parse($argv);
  259. $processed = $this->cli->arguments->toArray();
  260. $this->assertEquals('HEY', $this->cli->arguments->get('only-long-prefix'));
  261. }
  262. /** @test */
  263. public function it_throws_an_exception_when_required_arguments_are_not_defined()
  264. {
  265. $this->expectException(InvalidArgumentException::class);
  266. $this->expectExceptionMessage("The following arguments are required: [-r required-value] [-r1 required-value-1].");
  267. $this->cli->arguments->add([
  268. 'required-value' => [
  269. 'prefix' => 'r',
  270. 'required' => true,
  271. ],
  272. 'required-value-1' => [
  273. 'prefix' => 'r1',
  274. 'required' => true,
  275. ],
  276. 'optional-value' => [
  277. 'prefix' => 'o',
  278. ],
  279. ]);
  280. $argv = ['test-script', '-o', 'foo'];
  281. $this->cli->arguments->parse($argv);
  282. }
  283. /** @test */
  284. public function it_can_detect_when_arguments_are_defined()
  285. {
  286. $this->cli->arguments->add([
  287. 'argument' => [
  288. 'prefix' => 'a',
  289. ],
  290. 'another-argument' => [
  291. 'prefix' => 'b',
  292. ],
  293. 'long-argument' => [
  294. 'longPrefix' => 'c',
  295. ],
  296. ]);
  297. $argv = ['test-script', '-a', 'foo', '--c=bar'];
  298. $this->assertTrue($this->cli->arguments->defined('argument', $argv));
  299. $this->assertTrue($this->cli->arguments->defined('long-argument', $argv));
  300. $this->assertFalse($this->cli->arguments->defined('another-argument', $argv));
  301. $this->assertFalse($this->cli->arguments->defined('nonexistent', $argv));
  302. }
  303. /** @test */
  304. public function it_can_grab_the_trailing_arguments()
  305. {
  306. $this->cli->arguments->add([
  307. 'argument' => [
  308. 'prefix' => 'a',
  309. ],
  310. 'another-argument' => [
  311. 'prefix' => 'b',
  312. ],
  313. 'long-argument' => [
  314. 'longPrefix' => 'c',
  315. ],
  316. ]);
  317. $argv = ['test-script', '-a', 'foo', '--c=bar', '--', '-the', 'trailing', '--arguments=here'];
  318. $this->cli->arguments->parse($argv);
  319. $this->assertTrue($this->cli->arguments->defined('argument', $argv));
  320. $this->assertTrue($this->cli->arguments->defined('long-argument', $argv));
  321. $this->assertFalse($this->cli->arguments->defined('another-argument', $argv));
  322. $this->assertFalse($this->cli->arguments->defined('nonexistent', $argv));
  323. $this->assertSame($this->cli->arguments->trailing(), '-the trailing --arguments=here');
  324. }
  325. }