5 * Contains \Drupal\Tests\Core\Form\FormStateTest.
8 namespace Drupal\Tests\Core\Form;
10 use Drupal\Core\Form\FormInterface;
11 use Drupal\Core\Form\FormState;
12 use Drupal\Core\Form\FormStateInterface;
14 use Drupal\Tests\UnitTestCase;
15 use Symfony\Component\HttpFoundation\RedirectResponse;
18 * @coversDefaultClass \Drupal\Core\Form\FormState
22 class FormStateTest extends UnitTestCase {
25 * Tests the getRedirect() method.
27 * @covers ::getRedirect
29 * @dataProvider providerTestGetRedirect
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);
38 * Provides test data for testing the getRedirect() method.
41 * Returns some test data.
43 public function providerTestGetRedirect() {
47 $redirect = new RedirectResponse('/example');
48 $data[] = [['redirect' => $redirect], $redirect];
50 $data[] = [['redirect' => new Url('test_route_b', ['key' => 'value'])], new Url('test_route_b', ['key' => 'value'])];
52 $data[] = [['programmed' => TRUE], NULL];
53 $data[] = [['rebuild' => TRUE], NULL];
54 $data[] = [['no_redirect' => TRUE], NULL];
60 * Tests the setError() method.
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());
72 * Tests the getError() method.
76 * @dataProvider providerTestGetError
78 public function testGetError($errors, $parents, $error = NULL) {
79 $element['#parents'] = $parents;
80 $form_state = (new FormState())->setFormState([
83 $this->assertSame($error, $form_state->getError($element));
86 public function providerTestGetError() {
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'],
102 * @covers ::setErrorByName
104 * @dataProvider providerTestSetErrorByName
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();
111 $form_state->setErrorByName('test', 'Fail 1');
112 $form_state->setErrorByName('test', 'Fail 2');
113 $form_state->setErrorByName('options');
115 $this->assertSame(!empty($expected_errors), $form_state::hasAnyErrors());
116 $this->assertSame($expected_errors, $form_state->getErrors());
119 public function providerTestSetErrorByName() {
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.
132 * Tests that form errors during submission throw an exception.
134 * @covers ::setErrorByName
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');
144 * @covers ::prepareCallback
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);
154 * @covers ::prepareCallback
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);
165 * @covers ::prepareCallback
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);
176 * @covers ::loadInclude
178 public function testLoadInclude() {
180 $module = 'some_module';
182 $form_state = $this->getMockBuilder('Drupal\Core\Form\FormState')
183 ->setMethods(['moduleLoadInclude'])
185 $form_state->expects($this->once())
186 ->method('moduleLoadInclude')
187 ->with($module, $type, $name)
189 $this->assertTrue($form_state->loadInclude($module, $type, $name));
193 * @covers ::loadInclude
195 public function testLoadIncludeNoName() {
197 $module = 'some_module';
198 $form_state = $this->getMockBuilder('Drupal\Core\Form\FormState')
199 ->setMethods(['moduleLoadInclude'])
201 $form_state->expects($this->once())
202 ->method('moduleLoadInclude')
203 ->with($module, $type, $module)
205 $this->assertTrue($form_state->loadInclude($module, $type));
209 * @covers ::loadInclude
211 public function testLoadIncludeNotFound() {
213 $module = 'some_module';
214 $form_state = $this->getMockBuilder('Drupal\Core\Form\FormState')
215 ->setMethods(['moduleLoadInclude'])
217 $form_state->expects($this->once())
218 ->method('moduleLoadInclude')
219 ->with($module, $type, $module)
221 $this->assertFalse($form_state->loadInclude($module, $type));
225 * @covers ::loadInclude
227 public function testLoadIncludeAlreadyLoaded() {
229 $module = 'some_module';
231 $form_state = $this->getMockBuilder('Drupal\Core\Form\FormState')
232 ->setMethods(['moduleLoadInclude'])
235 $form_state->addBuildInfo('files', [
236 'some_module:some_name.some_type' => [
242 $form_state->expects($this->never())
243 ->method('moduleLoadInclude');
245 $this->assertFalse($form_state->loadInclude($module, $type, $name));
251 * @dataProvider providerTestIsCached
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,
259 $form_state->setMethod('POST');
260 $this->assertSame($expected, $form_state->isCached());
262 $form_state->setMethod('GET');
263 $this->assertSame($expected, $form_state->isCached());
267 * Provides test data for testIsCached().
269 public function providerTestIsCached() {
305 * @covers ::setCached
307 public function testSetCachedPost() {
308 $form_state = new FormState();
309 $form_state->setRequestMethod('POST');
310 $form_state->setCached();
311 $this->assertTrue($form_state->isCached());
315 * @covers ::setCached
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();
325 * @covers ::isMethodType
326 * @covers ::setMethod
328 * @dataProvider providerTestIsMethodType
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));
337 * Provides test data for testIsMethodType().
339 public function providerTestIsMethodType() {
365 * @covers ::getTemporaryValue
366 * @covers ::hasTemporaryValue
367 * @covers ::setTemporaryValue
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);
381 * @covers ::getCleanValueKeys
383 public function testGetCleanValueKeys() {
384 $form_state = new FormState();
385 $this->assertSame($form_state->getCleanValueKeys(), ['form_id', 'form_token', 'form_build_id', 'op']);
389 * @covers ::setCleanValueKeys
391 public function testSetCleanValueKeys() {
392 $form_state = new FormState();
393 $form_state->setCleanValueKeys(['key1', 'key2']);
394 $this->assertSame($form_state->getCleanValueKeys(), ['key1', 'key2']);
398 * @covers ::addCleanValueKey
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']);
409 * @depends testAddCleanValueKey
411 * @covers ::cleanValues
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']);
419 * @covers ::setValues
420 * @covers ::getValues
422 public function testGetValues() {
426 $form_state = new FormState();
427 $form_state->setValues($values);
428 $this->assertSame($values, $form_state->getValues());
434 * A test form used for the prepareCallback() tests.
436 class PrepareCallbackTestForm implements FormInterface {
437 public function getFormId() {
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) {}