FixerConfigurationResolverTest.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of PHP CS Fixer.
  5. *
  6. * (c) Fabien Potencier <fabien@symfony.com>
  7. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  8. *
  9. * This source file is subject to the MIT license that is bundled
  10. * with this source code in the file LICENSE.
  11. */
  12. namespace PhpCsFixer\Tests\FixerConfiguration;
  13. use PhpCsFixer\FixerConfiguration\AliasedFixerOption;
  14. use PhpCsFixer\FixerConfiguration\AllowedValueSubset;
  15. use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
  16. use PhpCsFixer\FixerConfiguration\FixerOption;
  17. use PhpCsFixer\FixerConfiguration\FixerOptionSorter;
  18. use PhpCsFixer\Tests\TestCase;
  19. use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
  20. use Symfony\Component\OptionsResolver\Exception\MissingOptionsException;
  21. use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
  22. use Symfony\Component\OptionsResolver\Options;
  23. /**
  24. * @internal
  25. *
  26. * @group legacy
  27. *
  28. * @covers \PhpCsFixer\FixerConfiguration\FixerConfigurationResolver
  29. */
  30. final class FixerConfigurationResolverTest extends TestCase
  31. {
  32. public function testWithoutOptions(): void
  33. {
  34. $this->expectException(\LogicException::class);
  35. $this->expectExceptionMessage('Options cannot be empty.');
  36. new FixerConfigurationResolver([]);
  37. }
  38. public function testWithDuplicatesOptions(): void
  39. {
  40. $this->expectException(\LogicException::class);
  41. $this->expectExceptionMessage('The "foo" option is defined multiple times.');
  42. new FixerConfigurationResolver([
  43. new FixerOption('foo', 'Bar-1.'),
  44. new FixerOption('foo', 'Bar-2.'),
  45. ]);
  46. }
  47. public function testWithDuplicateAliasOptions(): void
  48. {
  49. $this->expectException(\LogicException::class);
  50. $this->expectExceptionMessage('The "foo" option is defined multiple times.');
  51. new FixerConfigurationResolver([
  52. new AliasedFixerOption(new FixerOption('foo', 'Bar-1.'), 'baz'),
  53. new FixerOption('foo', 'Bar-2.'),
  54. ]);
  55. }
  56. public function testGetOptions(): void
  57. {
  58. $options = [
  59. new FixerOption('foo', 'Bar.'),
  60. new FixerOption('baz', 'Qux.'),
  61. ];
  62. $configuration = new FixerConfigurationResolver($options);
  63. $fixerOptionSorter = new FixerOptionSorter();
  64. $expected = $fixerOptionSorter->sort($options);
  65. self::assertSame($expected, $configuration->getOptions());
  66. }
  67. public function testResolve(): void
  68. {
  69. $configuration = new FixerConfigurationResolver([
  70. new FixerOption('foo', 'Bar.'),
  71. ]);
  72. self::assertSame(
  73. ['foo' => 'bar'],
  74. $configuration->resolve(['foo' => 'bar'])
  75. );
  76. }
  77. public function testResolveWithMissingRequiredOption(): void
  78. {
  79. $configuration = new FixerConfigurationResolver([
  80. new FixerOption('foo', 'Bar.'),
  81. ]);
  82. $this->expectException(MissingOptionsException::class);
  83. $configuration->resolve([]);
  84. }
  85. public function testResolveWithDefault(): void
  86. {
  87. $configuration = new FixerConfigurationResolver([
  88. new FixerOption('foo', 'Bar.', false, 'baz'),
  89. ]);
  90. self::assertSame(
  91. ['foo' => 'baz'],
  92. $configuration->resolve([])
  93. );
  94. }
  95. public function testResolveWithAllowedTypes(): void
  96. {
  97. $configuration = new FixerConfigurationResolver([
  98. new FixerOption('foo', 'Bar.', true, null, ['int']),
  99. ]);
  100. self::assertSame(
  101. ['foo' => 1],
  102. $configuration->resolve(['foo' => 1])
  103. );
  104. $this->expectException(InvalidOptionsException::class);
  105. $configuration->resolve(['foo' => '1']);
  106. }
  107. public function testResolveWithAllowedValues(): void
  108. {
  109. $configuration = new FixerConfigurationResolver([
  110. new FixerOption('foo', 'Bar.', true, null, null, [true, false]),
  111. ]);
  112. self::assertSame(
  113. ['foo' => true],
  114. $configuration->resolve(['foo' => true])
  115. );
  116. $this->expectException(InvalidOptionsException::class);
  117. $configuration->resolve(['foo' => 1]);
  118. }
  119. public function testResolveWithAllowedValuesSubset(): void
  120. {
  121. $configuration = new FixerConfigurationResolver([
  122. new FixerOption('foo', 'Bar.', true, null, null, [new AllowedValueSubset(['foo', 'bar'])]),
  123. ]);
  124. self::assertSame(
  125. ['foo' => ['bar']],
  126. $configuration->resolve(['foo' => ['bar']])
  127. );
  128. $this->expectException(InvalidOptionsException::class);
  129. $configuration->resolve(['foo' => ['baz']]);
  130. }
  131. public function testResolveWithUndefinedOption(): void
  132. {
  133. $configuration = new FixerConfigurationResolver([
  134. new FixerOption('bar', 'Bar.'),
  135. ]);
  136. $this->expectException(UndefinedOptionsException::class);
  137. $configuration->resolve(['foo' => 'foooo']);
  138. }
  139. public function testResolveWithNormalizers(): void
  140. {
  141. $configuration = new FixerConfigurationResolver([
  142. new FixerOption('foo', 'Bar.', true, null, null, null, static fn (Options $options, string $value): int => (int) $value),
  143. ]);
  144. self::assertSame(
  145. ['foo' => 1],
  146. $configuration->resolve(['foo' => '1'])
  147. );
  148. $exception = new InvalidOptionsException('');
  149. $configuration = new FixerConfigurationResolver([
  150. new FixerOption('foo', 'Bar.', true, null, null, null, static function (Options $options, $value) use ($exception): void {
  151. throw $exception;
  152. }),
  153. ]);
  154. $caught = null;
  155. try {
  156. $configuration->resolve(['foo' => '1']);
  157. } catch (InvalidOptionsException $caught) {
  158. }
  159. self::assertSame($exception, $caught);
  160. }
  161. public function testResolveWithAliasedDuplicateConfig(): void
  162. {
  163. $configuration = new FixerConfigurationResolver([
  164. new AliasedFixerOption(new FixerOption('bar', 'Bar.'), 'baz'),
  165. ]);
  166. $this->expectException(InvalidOptionsException::class);
  167. $this->expectExceptionMessage('Aliased option "bar"/"baz" is passed multiple times');
  168. $configuration->resolve([
  169. 'bar' => '1',
  170. 'baz' => '2',
  171. ]);
  172. }
  173. public function testResolveWithDeprecatedAlias(): void
  174. {
  175. $this->expectDeprecation('Option "baz" is deprecated, use "bar" instead.');
  176. $configuration = new FixerConfigurationResolver([
  177. new AliasedFixerOption(new FixerOption('bar', 'Bar.'), 'baz'),
  178. ]);
  179. $configuration->resolve([
  180. 'baz' => '1',
  181. ]);
  182. }
  183. }