ILIAS  trunk Revision v13.0_alpha-62-g3b72d83f2e5
LanguageActivityTest.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
32use PHPUnit\Framework\Attributes\DataProvider;
33
39{
40 use RealFieldsUiFactory;
41
47 {
48 $rbac = $this->createMock(\ilRbacSystem::class);
49 $rbac->expects($this->never())->method('checkAccessOfUser');
50
52 $this->rbacOf($rbac),
53 $this->languageFolder()
54 );
55
56 $result = $activity->maybePerformAs($this->createRealFieldsUiFactory()->input(), 6, []);
57
58 $this->assertTrue($result->isError());
59 $error = $result->error();
60 $this->assertInstanceOf(\RuntimeException::class, $error);
61 $this->assertSame(500, $error->getCode());
62 $this->assertSame('The activity could not be performed.', $error->getMessage());
63 $this->assertInstanceOf(\RuntimeException::class, $error->getPrevious());
64 $this->assertSame('simulated failure while building the input description', $error->getPrevious()->getMessage());
65 }
66
69 {
71 $this->rbacOf($this->createMock(\ilRbacSystem::class)),
72 $this->languageFolder(),
73 throw_type_error: true,
74 );
75
76 $error = $activity->maybePerformAs($this->createRealFieldsUiFactory()->input(), 6, [])->error();
77
78 $this->assertInstanceOf(\RuntimeException::class, $error);
79 $this->assertSame(500, $error->getCode());
80 $this->assertStringNotContainsString('TypeError', $error->getMessage());
81 $this->assertInstanceOf(\TypeError::class, $error->getPrevious());
82 }
83
86 {
88 $this->rbacOf($this->createMock(\ilRbacSystem::class)),
89 $this->languageFolder(),
90 $this->createMock(FormInput::class),
91 );
92
93 $error = $activity->maybePerformAs($this->createRealFieldsUiFactory()->input(), 6, [])->error();
94
95 $this->assertSame(500, $error->getCode());
96 $this->assertInstanceOf(\LogicException::class, $error->getPrevious());
97 }
98
100 public static function unknownUserIdProvider(): array
101 {
102 return ['zero' => [0], 'negative' => [-1], 'anonymous' => [null]];
103 }
104
106 #[DataProvider('unknownUserIdProvider')]
108 {
109 if (!defined('ANONYMOUS_USER_ID')) {
110 define('ANONYMOUS_USER_ID', 13);
111 }
112 $usr_id ??= ANONYMOUS_USER_ID;
113
114 $rbac_system = $this->createMock(\ilRbacSystem::class);
115 $rbac_system->expects($this->never())->method('checkAccessOfUser');
116
118 $this->rbacOf($rbac_system),
119 $this->languageFolder()
120 );
121
122 $this->assertFalse($activity->isAllowedToPerform($usr_id, []));
123 }
124
126 {
127 $rbac_system = $this->createMock(\ilRbacSystem::class);
128 $rbac_system->expects($this->never())->method('checkAccessOfUser');
129
131 $this->rbacOf($rbac_system),
132 $this->languageFolder()
133 );
134
135 $error = $activity->maybePerformAs($this->createRealFieldsUiFactory()->input(), 0, [])->error();
136
137 $this->assertSame(403, $error->getCode());
138 }
139
145 {
146 $rbac = $this->createStub(\ilRbacSystem::class);
147 $rbac->method('checkAccessOfUser')->willReturn(true);
148
150 $this->rbacOf($rbac),
151 $this->languageFolder()
152 );
153
154 $result = $activity->maybePerformAs($this->createRealFieldsUiFactory()->input(), 42, []);
155
156 $this->assertFalse($result->isError());
157 $parameters = $result->value();
158 // the trusted usr_id (42) wins over the spoofed one from normalizeParameters()
159 $this->assertSame(42, $parameters['usr_id']);
160 // a non-colliding key survives the merge
161 $this->assertSame('form', $parameters['source']);
162 }
163
169 {
171 $skipped = [
172 'de' => [
173 'tos#:#x' => $policy->findViolations('<script>a</script><script>b</script></form>'),
174 'tos#:#plain' => [],
175 ],
176 'en' => ['tos#:#y' => $policy->findViolations('<script>a</script>')],
177 'fr' => ['tos#:#z' => $policy->findViolations('<script>a</script>')],
178 ];
180 $this->rbacOf($this->createStub(\ilRbacSystem::class)),
181 $this->languageFolder()
182 );
183
184 $this->assertSame(
185 ['en: tos#:#y: <script>', 'de: tos#:#x: <script>, </form>', 'de: tos#:#plain'],
186 $activity->entries($skipped, ['en', 'de', 'it'])
187 );
188 }
189
191 {
192 $skipped = [
193 'de' => ['tos#:#x' => ['common: x', 'pilot: X'], 'tos#:#y' => ['mme: y']],
194 'en' => ['tos#:#z' => ['mme: z']],
195 'fr' => ['tos#:#z' => ['mme: z']],
196 ];
198 $this->rbacOf($this->createStub(\ilRbacSystem::class)),
199 $this->languageFolder()
200 );
201
202 $this->assertSame(
203 ['en: tos#:#z (mme: z)', 'de: tos#:#x (common: x, pilot: X)', 'de: tos#:#y (mme: y)'],
204 $activity->duplicateEntries($skipped, ['en', 'de', 'it'])
205 );
206 }
207}
208
210{
211 public function __construct(
212 RBAC $rbac,
213 LanguageFolder $language_folder,
214 private readonly bool $throw_type_error = false,
215 ) {
216 parent::__construct($rbac, $language_folder);
217 }
218
220 {
221 return $this->data->text()->markdown()->simpleDocument('Test double for LanguageActivity::maybePerformAs().');
222 }
223
224 public function getInputDescription(FieldFactory $f): FormInput
225 {
226 if ($this->throw_type_error) {
227 throw new \TypeError('simulated TypeError while building the input description');
228 }
229
230 throw new \RuntimeException('simulated failure while building the input description');
231 }
232
234 {
235 throw new \LogicException(__METHOD__ . ' is not used by this test double.');
236 }
237
238 public function perform(mixed $parameters): mixed
239 {
240 throw new \LogicException(__METHOD__ . ' is not used by this test double.');
241 }
242
243 protected function normalizeParameters(array $grind_result): array
244 {
245 throw new \LogicException(__METHOD__ . ' is not used by this test double.');
246 }
247}
248
254{
255 public function __construct(
256 RBAC $rbac,
257 LanguageFolder $language_folder,
258 private readonly ?FormInput $description = null,
259 ) {
260 parent::__construct($rbac, $language_folder);
261 }
262
264 {
265 return $this->data->text()->markdown()->simpleDocument('Test double for the usr_id precedence in maybePerformAs().');
266 }
267
268 public function getInputDescription(FieldFactory $f): FormInput
269 {
270 return $this->description ?? $f->group([]);
271 }
272
274 {
275 throw new \LogicException(__METHOD__ . ' is not used by this test double.');
276 }
277
278 public function perform(mixed $parameters): mixed
279 {
280 return $parameters;
281 }
282
286 protected function normalizeParameters(array $grind_result): array
287 {
288 // spoofed 'usr_id' that must lose against the one maybePerformAs() passes
289 return ['usr_id' => 'SPOOFED-VALUE', 'source' => 'form'];
290 }
291}
292
297{
303 public function entries(array $skipped, array $language_keys): array
304 {
305 return $this->invalidMarkupCustomizingEntries($skipped, $language_keys);
306 }
307
313 public function duplicateEntries(array $skipped, array $language_keys): array
314 {
315 return $this->duplicateCustomizingEntries($skipped, $language_keys);
316 }
317
319 {
320 return $this->data->text()->markdown()->simpleDocument('Test double for invalidMarkupCustomizingEntries().');
321 }
322
323 public function getInputDescription(FieldFactory $f): FormInput
324 {
325 throw new \LogicException(__METHOD__ . ' is not used by this test double.');
326 }
327
329 {
330 throw new \LogicException(__METHOD__ . ' is not used by this test double.');
331 }
332
333 public function perform(mixed $parameters): mixed
334 {
335 throw new \LogicException(__METHOD__ . ' is not used by this test double.');
336 }
337
341 protected function normalizeParameters(array $grind_result): array
342 {
343 throw new \LogicException(__METHOD__ . ' is not used by this test double.');
344 }
345}
This describes some datastructure in terms of standard data structures such as primitives,...
Definition: Description.php:33
duplicateCustomizingEntries(array $skipped, array $language_keys)
invalidMarkupCustomizingEntries(array $skipped, array $language_keys)
The HTML a translation value may contain, decided in one place for the shipped files (cleaned in Setu...
Minimal LanguageActivity making the protected invalidMarkupCustomizingEntries() callable.
normalizeParameters() always returns a colliding 'usr_id' (spoofed form input); perform() returns $pa...
__construct(RBAC $rbac, LanguageFolder $language_folder, private readonly ?FormInput $description=null,)
perform(mixed $parameters)
This shall perform the activity.
Targets LanguageActivity::maybePerformAs() directly via throwing test doubles, for behaviour no concr...
testMaybePerformAsPassesTheTrustedUsrIdToPerformOverASpoofedFormKey()
perform() gets the usr_id of maybePerformAs(), not the spoofed one from normalizeParameters().
testExceptionWhileBuildingTheInputDescriptionIsMaskedAsA500ResultError()
A defect while building the input description comes back masked as 500 (original only as previous),...
testADefectThrownByGrindIsMaskedAsA500ResultError()
grind() throws on a defect (FormInput without InputInternal); maybePerformAs() must mask it as 500.
testATypeErrorWhileBuildingTheInputDescriptionIsMaskedAsA500ResultError()
A non-\Exception \Throwable (\TypeError) is masked as well.
testIsAllowedToPerformRefusesNonUsersWithoutAskingRbac(?int $usr_id)
No RBAC lookup for a non-user: the anonymous user (null: ANONYMOUS_USER_ID) must not pass on its role...
testInvalidMarkupCustomizingEntriesAppendTheMarkupConcernedToEachEntry()
Skipped entries are listed with their markup, language-neutral and without duplicates; only the reque...
__construct(RBAC $rbac, LanguageFolder $language_folder, private readonly bool $throw_type_error=false,)
ilErrorHandling $error
Definition: class.ilias.php:69
Class ilLanguageBaseTest.
rbacOf(\ilRbacSystem $system)
const ANONYMOUS_USER_ID
Definition: constants.php:27
Public RBAC service of the AccessControl component.
Definition: RBAC.php:30
The language folder in the administration, whose "write" permission guards the language Activities.
This describes inputs that can be used in forms.
Definition: FormInput.php:33
This is what a factory for input fields looks like.
Definition: Factory.php:31
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...