23579a12a9b81e4dbeb14e9eb461274f8dd0b0a1
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Form / FormStateTest.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\Tests\Core\Form\FormStateTest.
6  */
7
8 namespace Drupal\Tests\Core\Form;
9
10 use Drupal\Core\Form\FormInterface;
11 use Drupal\Core\Form\FormState;
12 use Drupal\Core\Form\FormStateInterface;
13 use Drupal\Core\Url;
14 use Drupal\Tests\UnitTestCase;
15 use Symfony\Component\HttpFoundation\RedirectResponse;
16
17 /**
18  * @coversDefaultClass \Drupal\Core\Form\FormState
19  *
20  * @group Form
21  */
22 class FormStateTest extends UnitTestCase {
23
24   /**
25    * Tests the getRedirect() method.
26    *
27    * @covers ::getRedirect
28    *
29    * @dataProvider providerTestGetRedirect
30    */
31   public function testGetRedirect($form_state_additions, $expected) {
32     $form_state = (new FormState())->setFormState($form_state_additions);
33     $redirect = $form_state->getRedirect();
34     $this->assertEquals($expected, $redirect);
35   }
36
37   /**
38    * Provides test data for testing the getRedirect() method.
39    *
40    * @return array
41    *   Returns some test data.
42    */
43   public function providerTestGetRedirect() {
44     $data = [];
45     $data[] = [[], NULL];
46
47     $redirect = new RedirectResponse('/example');
48     $data[] = [['redirect' => $redirect], $redirect];
49
50     $data[] = [['redirect' => new Url('test_route_b', ['key' => 'value'])], new Url('test_route_b', ['key' => 'value'])];
51
52     $data[] = [['programmed' => TRUE], NULL];
53     $data[] = [['rebuild' => TRUE], NULL];
54     $data[] = [['no_redirect' => TRUE], NULL];
55
56     return $data;
57   }
58
59   /**
60    * Tests the setError() method.
61    *
62    * @covers ::setError
63    */
64   public function testSetError() {
65     $form_state = new FormState();
66     $element['#parents'] = ['foo', 'bar'];
67     $form_state->setError($element, 'Fail');
68     $this->assertSame(['foo][bar' => 'Fail'], $form_state->getErrors());
69   }
70
71   /**
72    * Tests the getError() method.
73    *
74    * @covers ::getError
75    *
76    * @dataProvider providerTestGetError
77    */
78   public function testGetError($errors, $parents, $error = NULL) {
79     $element['#parents'] = $parents;
80     $form_state = (new FormState())->setFormState([
81       'errors' => $errors,
82     ]);
83     $this->assertSame($error, $form_state->getError($element));
84   }
85
86   public function providerTestGetError() {
87     return [
88       [[], ['foo']],
89       [['foo][bar' => 'Fail'], []],
90       [['foo][bar' => 'Fail'], ['foo']],
91       [['foo][bar' => 'Fail'], ['bar']],
92       [['foo][bar' => 'Fail'], ['baz']],
93       [['foo][bar' => 'Fail'], ['foo', 'bar'], 'Fail'],
94       [['foo][bar' => 'Fail'], ['foo', 'bar', 'baz'], 'Fail'],
95       [['foo][bar' => 'Fail 2'], ['foo']],
96       [['foo' => 'Fail 1', 'foo][bar' => 'Fail 2'], ['foo'], 'Fail 1'],
97       [['foo' => 'Fail 1', 'foo][bar' => 'Fail 2'], ['foo', 'bar'], 'Fail 1'],
98     ];
99   }
100
101   /**
102    * @covers ::setErrorByName
103    *
104    * @dataProvider providerTestSetErrorByName
105    */
106   public function testSetErrorByName($limit_validation_errors, $expected_errors) {
107     $form_state = new FormState();
108     $form_state->setLimitValidationErrors($limit_validation_errors);
109     $form_state->clearErrors();
110
111     $form_state->setErrorByName('test', 'Fail 1');
112     $form_state->setErrorByName('test', 'Fail 2');
113     $form_state->setErrorByName('options');
114
115     $this->assertSame(!empty($expected_errors), $form_state::hasAnyErrors());
116     $this->assertSame($expected_errors, $form_state->getErrors());
117   }
118
119   public function providerTestSetErrorByName() {
120     return [
121       // Only validate the 'options' element.
122       [[['options']], ['options' => '']],
123       // Do not limit an validation, and, ensuring the first error is returned
124       // for the 'test' element.
125       [NULL, ['test' => 'Fail 1', 'options' => '']],
126       // Limit all validation.
127       [[], []],
128     ];
129   }
130
131   /**
132    * Tests that form errors during submission throw an exception.
133    *
134    * @covers ::setErrorByName
135    */
136   public function testFormErrorsDuringSubmission() {
137     $form_state = new FormState();
138     $form_state->setValidationComplete();
139     $this->setExpectedException(\LogicException::class, 'Form errors cannot be set after form validation has finished.');
140     $form_state->setErrorByName('test', 'message');
141   }
142
143   /**
144    * @covers ::prepareCallback
145    */
146   public function testPrepareCallbackValidMethod() {
147     $form_state = new FormState();
148     $form_state->setFormObject(new PrepareCallbackTestForm());
149     $processed_callback = $form_state->prepareCallback('::buildForm');
150     $this->assertEquals([$form_state->getFormObject(), 'buildForm'], $processed_callback);
151   }
152
153   /**
154    * @covers ::prepareCallback
155    */
156   public function testPrepareCallbackInValidMethod() {
157     $form_state = new FormState();
158     $form_state->setFormObject(new PrepareCallbackTestForm());
159     $processed_callback = $form_state->prepareCallback('not_a_method');
160     // The callback was not changed as no such method exists.
161     $this->assertEquals('not_a_method', $processed_callback);
162   }
163
164   /**
165    * @covers ::prepareCallback
166    */
167   public function testPrepareCallbackArray() {
168     $form_state = new FormState();
169     $form_state->setFormObject(new PrepareCallbackTestForm());
170     $callback = [$form_state->getFormObject(), 'buildForm'];
171     $processed_callback = $form_state->prepareCallback($callback);
172     $this->assertEquals($callback, $processed_callback);
173   }
174
175   /**
176    * @covers ::loadInclude
177    */
178   public function testLoadInclude() {
179     $type = 'some_type';
180     $module = 'some_module';
181     $name = 'some_name';
182     $form_state = $this->getMockBuilder('Drupal\Core\Form\FormState')
183       ->setMethods(['moduleLoadInclude'])
184       ->getMock();
185     $form_state->expects($this->once())
186       ->method('moduleLoadInclude')
187       ->with($module, $type, $name)
188       ->willReturn(TRUE);
189     $this->assertTrue($form_state->loadInclude($module, $type, $name));
190   }
191
192   /**
193    * @covers ::loadInclude
194    */
195   public function testLoadIncludeNoName() {
196     $type = 'some_type';
197     $module = 'some_module';
198     $form_state = $this->getMockBuilder('Drupal\Core\Form\FormState')
199       ->setMethods(['moduleLoadInclude'])
200       ->getMock();
201     $form_state->expects($this->once())
202       ->method('moduleLoadInclude')
203       ->with($module, $type, $module)
204       ->willReturn(TRUE);
205     $this->assertTrue($form_state->loadInclude($module, $type));
206   }
207
208   /**
209    * @covers ::loadInclude
210    */
211   public function testLoadIncludeNotFound() {
212     $type = 'some_type';
213     $module = 'some_module';
214     $form_state = $this->getMockBuilder('Drupal\Core\Form\FormState')
215       ->setMethods(['moduleLoadInclude'])
216       ->getMock();
217     $form_state->expects($this->once())
218       ->method('moduleLoadInclude')
219       ->with($module, $type, $module)
220       ->willReturn(FALSE);
221     $this->assertFalse($form_state->loadInclude($module, $type));
222   }
223
224   /**
225    * @covers ::loadInclude
226    */
227   public function testLoadIncludeAlreadyLoaded() {
228     $type = 'some_type';
229     $module = 'some_module';
230     $name = 'some_name';
231     $form_state = $this->getMockBuilder('Drupal\Core\Form\FormState')
232       ->setMethods(['moduleLoadInclude'])
233       ->getMock();
234
235     $form_state->addBuildInfo('files', [
236       'some_module:some_name.some_type' => [
237         'type' => $type,
238         'module' => $module,
239         'name' => $name,
240       ],
241     ]);
242     $form_state->expects($this->never())
243       ->method('moduleLoadInclude');
244
245     $this->assertFalse($form_state->loadInclude($module, $type, $name));
246   }
247
248   /**
249    * @covers ::isCached
250    *
251    * @dataProvider providerTestIsCached
252    */
253   public function testIsCached($cache_key, $no_cache_key, $expected) {
254     $form_state = (new FormState())->setFormState([
255       'cache' => $cache_key,
256       'no_cache' => $no_cache_key,
257     ]);
258
259     $form_state->setMethod('POST');
260     $this->assertSame($expected, $form_state->isCached());
261
262     $form_state->setMethod('GET');
263     $this->assertSame($expected, $form_state->isCached());
264   }
265
266   /**
267    * Provides test data for testIsCached().
268    */
269   public function providerTestIsCached() {
270     $data = [];
271     $data[] = [
272       TRUE,
273       TRUE,
274       FALSE,
275     ];
276     $data[] = [
277       FALSE,
278       TRUE,
279       FALSE,
280     ];
281     $data[] = [
282       FALSE,
283       FALSE,
284       FALSE,
285     ];
286     $data[] = [
287       TRUE,
288       FALSE,
289       TRUE,
290     ];
291     $data[] = [
292       TRUE,
293       NULL,
294       TRUE,
295     ];
296     $data[] = [
297       FALSE,
298       NULL,
299       FALSE,
300     ];
301     return $data;
302   }
303
304   /**
305    * @covers ::setCached
306    */
307   public function testSetCachedPost() {
308     $form_state = new FormState();
309     $form_state->setRequestMethod('POST');
310     $form_state->setCached();
311     $this->assertTrue($form_state->isCached());
312   }
313
314   /**
315    * @covers ::setCached
316    */
317   public function testSetCachedGet() {
318     $form_state = new FormState();
319     $form_state->setRequestMethod('GET');
320     $this->setExpectedException(\LogicException::class, 'Form state caching on GET requests is not allowed.');
321     $form_state->setCached();
322   }
323
324   /**
325    * @covers ::isMethodType
326    * @covers ::setMethod
327    *
328    * @dataProvider providerTestIsMethodType
329    */
330   public function testIsMethodType($set_method_type, $input, $expected) {
331     $form_state = (new FormState())
332       ->setMethod($set_method_type);
333     $this->assertSame($expected, $form_state->isMethodType($input));
334   }
335
336   /**
337    * Provides test data for testIsMethodType().
338    */
339   public function providerTestIsMethodType() {
340     $data = [];
341     $data[] = [
342       'get',
343       'get',
344       TRUE,
345     ];
346     $data[] = [
347       'get',
348       'GET',
349       TRUE,
350     ];
351     $data[] = [
352       'GET',
353       'GET',
354       TRUE,
355     ];
356     $data[] = [
357       'post',
358       'get',
359       FALSE,
360     ];
361     return $data;
362   }
363
364   /**
365    * @covers ::getTemporaryValue
366    * @covers ::hasTemporaryValue
367    * @covers ::setTemporaryValue
368    */
369   public function testTemporaryValue() {
370     $form_state = new FormState();
371     $this->assertFalse($form_state->hasTemporaryValue('rainbow_sparkles'));
372     $form_state->setTemporaryValue('rainbow_sparkles', 'yes please');
373     $this->assertSame($form_state->getTemporaryValue('rainbow_sparkles'), 'yes please');
374     $this->assertTrue($form_state->hasTemporaryValue('rainbow_sparkles'), TRUE);
375     $form_state->setTemporaryValue(['rainbow_sparkles', 'magic_ponies'], 'yes please');
376     $this->assertSame($form_state->getTemporaryValue(['rainbow_sparkles', 'magic_ponies']), 'yes please');
377     $this->assertTrue($form_state->hasTemporaryValue(['rainbow_sparkles', 'magic_ponies']), TRUE);
378   }
379
380   /**
381    * @covers ::getCleanValueKeys
382    */
383   public function testGetCleanValueKeys() {
384     $form_state = new FormState();
385     $this->assertSame($form_state->getCleanValueKeys(), ['form_id', 'form_token', 'form_build_id', 'op']);
386   }
387
388   /**
389    * @covers ::setCleanValueKeys
390    */
391   public function testSetCleanValueKeys() {
392     $form_state = new FormState();
393     $form_state->setCleanValueKeys(['key1', 'key2']);
394     $this->assertSame($form_state->getCleanValueKeys(), ['key1', 'key2']);
395   }
396
397   /**
398    * @covers ::addCleanValueKey
399    */
400   public function testAddCleanValueKey() {
401     $form_state = new FormState();
402     $form_state->setValue('value_to_clean', 'rainbow_sprinkles');
403     $form_state->addCleanValueKey('value_to_clean');
404     $this->assertSame($form_state->getCleanValueKeys(), ['form_id', 'form_token', 'form_build_id', 'op', 'value_to_clean']);
405     return $form_state;
406   }
407
408   /**
409    * @depends testAddCleanValueKey
410    *
411    * @covers ::cleanValues
412    */
413   public function testCleanValues($form_state) {
414     $form_state->setValue('value_to_keep', 'magic_ponies');
415     $this->assertSame($form_state->cleanValues()->getValues(), ['value_to_keep' => 'magic_ponies']);
416   }
417
418   /**
419    * @covers ::setValues
420    * @covers ::getValues
421    */
422   public function testGetValues() {
423     $values = [
424       'foo' => 'bar',
425     ];
426     $form_state = new FormState();
427     $form_state->setValues($values);
428     $this->assertSame($values, $form_state->getValues());
429   }
430
431 }
432
433 /**
434  * A test form used for the prepareCallback() tests.
435  */
436 class PrepareCallbackTestForm implements FormInterface {
437   public function getFormId() {
438     return 'test_form';
439   }
440
441   public function buildForm(array $form, FormStateInterface $form_state) {}
442   public function validateForm(array &$form, FormStateInterface $form_state) {}
443   public function submitForm(array &$form, FormStateInterface $form_state) {}
444
445 }