|
6 | 6 |
|
7 | 7 | use Nette\DI; |
8 | 8 | use Nette\DI\Definitions\Statement; |
| 9 | +use Nette\DI\Expressions\ArgumentPlaceholder; |
9 | 10 | use Nette\DI\Expressions\PartialCall; |
10 | 11 | use Nette\DI\Expressions\Reference; |
11 | 12 | use Tester\Assert; |
@@ -52,15 +53,44 @@ test('generateCode(): all target forms', function () { |
52 | 53 | }); |
53 | 54 |
|
54 | 55 |
|
55 | | -test('complete(): valid callables pass and return the same instance', function () { |
| 56 | +test('generateCode(): partial application with bound arguments and placeholders (PHP 8.6+)', function () { |
| 57 | + [, $generator] = harness(); |
| 58 | + // single ? placeholders and a bound value |
| 59 | + Assert::same("str_replace(?, ?, 'x')", (new PartialCall(null, 'str_replace', [ArgumentPlaceholder::Single, ArgumentPlaceholder::Single, 'x']))->generateCode($generator)); |
| 60 | + // bound value then placeholder |
| 61 | + Assert::same('trim(1, ?)', (new PartialCall(null, 'trim', [1, ArgumentPlaceholder::Single]))->generateCode($generator)); |
| 62 | + // placeholder then variadic rest |
| 63 | + Assert::same('Subject::pub(?, ...)', (new PartialCall('Subject', 'pub', [ArgumentPlaceholder::Single, ArgumentPlaceholder::Variadic]))->generateCode($generator)); |
| 64 | + // named arguments |
| 65 | + Assert::same('trim(string: ?, characters: 1)', (new PartialCall(null, 'trim', ['string' => ArgumentPlaceholder::Single, 'characters' => 1]))->generateCode($generator)); |
| 66 | + // placeholder on a method call |
| 67 | + Assert::same("\$this->getService('a')->pub(?)", (new PartialCall(new Reference('a'), 'pub', [ArgumentPlaceholder::Single]))->generateCode($generator)); |
| 68 | +}); |
| 69 | + |
| 70 | + |
| 71 | +test('complete(): bound @service arguments are resolved, placeholders pass through untouched', function () { |
| 72 | + [$resolver, $generator] = harness(); |
| 73 | + $partial = new PartialCall(null, 'str_replace', ['@a', ArgumentPlaceholder::Single, ArgumentPlaceholder::Variadic]); |
| 74 | + $completed = $partial->complete($resolver); |
| 75 | + |
| 76 | + Assert::notSame($partial, $completed); |
| 77 | + Assert::same('@a', $partial->arguments[0]); // original untouched |
| 78 | + Assert::type(Reference::class, $completed->arguments[0]); // @a resolved |
| 79 | + Assert::same(ArgumentPlaceholder::Single, $completed->arguments[1]); // placeholder kept |
| 80 | + Assert::same(ArgumentPlaceholder::Variadic, $completed->arguments[2]); // placeholder kept |
| 81 | + Assert::same("str_replace(\$this->getService('a'), ?, ...)", $completed->generateCode($generator)); |
| 82 | +}); |
| 83 | + |
| 84 | + |
| 85 | +test('complete(): valid callables pass and stay unchanged', function () { |
56 | 86 | [$resolver] = harness(); |
57 | 87 | foreach ([ |
58 | 88 | new PartialCall(null, 'trim'), |
59 | 89 | new PartialCall(null, 'Foo\undefinedFunc'), // function existence is not verified (not autoloadable) |
60 | 90 | new PartialCall(Subject::class, 'pub'), |
61 | 91 | new PartialCall(Subject::class, 'magic'), // missing method tolerated because of __callStatic |
62 | 92 | ] as $callable) { |
63 | | - Assert::same($callable, $callable->complete($resolver)); |
| 93 | + Assert::equal($callable, $callable->complete($resolver)); |
64 | 94 | } |
65 | 95 | }); |
66 | 96 |
|
@@ -111,9 +141,15 @@ testException('complete(): reference to missing service inside target', function |
111 | 141 | }, DI\ServiceCreationException::class, "Reference to missing service 'missing'."); |
112 | 142 |
|
113 | 143 |
|
| 144 | +testException('complete(): plain arguments without any placeholder are rejected', function () { |
| 145 | + [$resolver] = harness(); |
| 146 | + (new PartialCall(null, 'trim', [1, 2]))->complete($resolver); |
| 147 | +}, DI\ServiceCreationException::class, 'First-class callable trim() must contain at least one placeholder (? or ...).'); |
| 148 | + |
| 149 | + |
114 | 150 | test('transformValues(): callback is applied to target and name, original is untouched', function () { |
115 | 151 | $callable = new PartialCall('%class%', '%method%'); |
116 | | - $transformed = $callable->transformValues(fn($v) => strtr($v, ['%class%' => 'Subject', '%method%' => 'pub'])); |
| 152 | + $transformed = $callable->transformValues(fn($v) => is_string($v) ? strtr($v, ['%class%' => 'Subject', '%method%' => 'pub']) : $v); |
117 | 153 | Assert::notSame($callable, $transformed); |
118 | 154 | Assert::same('Subject', $transformed->target); |
119 | 155 | Assert::same('pub', $transformed->name); |
|
0 commit comments