3 namespace Drupal\Tests\Core\Form;
5 use Drupal\Core\DependencyInjection\ContainerBuilder;
6 use Drupal\Core\Form\FormState;
7 use Drupal\Core\Routing\UrlGeneratorInterface;
9 use Drupal\Core\Utility\UnroutedUrlAssemblerInterface;
10 use Drupal\Tests\UnitTestCase;
11 use Symfony\Component\HttpFoundation\RedirectResponse;
12 use Symfony\Component\HttpFoundation\Request;
13 use Symfony\Component\HttpFoundation\RequestStack;
16 * @coversDefaultClass \Drupal\Core\Form\FormSubmitter
19 class FormSubmitterTest extends UnitTestCase {
22 * The mocked URL generator.
24 * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Routing\UrlGeneratorInterface
26 protected $urlGenerator;
29 * The mocked unrouted URL assembler.
31 * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Utility\UnroutedUrlAssemblerInterface
33 protected $unroutedUrlAssembler;
38 protected function setUp() {
40 $this->urlGenerator = $this->getMock(UrlGeneratorInterface::class);
41 $this->unroutedUrlAssembler = $this->getMock(UnroutedUrlAssemblerInterface::class);
45 * @covers ::doSubmitForm
47 public function testHandleFormSubmissionNotSubmitted() {
48 $form_submitter = $this->getFormSubmitter();
50 $form_state = new FormState();
52 $return = $form_submitter->doSubmitForm($form, $form_state);
53 $this->assertFalse($form_state->isExecuted());
54 $this->assertNull($return);
58 * @covers ::doSubmitForm
60 public function testHandleFormSubmissionNoRedirect() {
61 $form_submitter = $this->getFormSubmitter();
63 $form_state = (new FormState())
67 $return = $form_submitter->doSubmitForm($form, $form_state);
68 $this->assertTrue($form_state->isExecuted());
69 $this->assertNull($return);
73 * @covers ::doSubmitForm
75 * @dataProvider providerTestHandleFormSubmissionWithResponses
77 public function testHandleFormSubmissionWithResponses($class, $form_state_key) {
78 $response = $this->getMockBuilder($class)
79 ->disableOriginalConstructor()
81 $response->expects($this->any())
83 ->will($this->returnValue($response));
85 $form_state = (new FormState())
87 ->setFormState([$form_state_key => $response]);
89 $form_submitter = $this->getFormSubmitter();
91 $return = $form_submitter->doSubmitForm($form, $form_state);
93 $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $return);
96 public function providerTestHandleFormSubmissionWithResponses() {
98 ['Symfony\Component\HttpFoundation\Response', 'response'],
99 ['Symfony\Component\HttpFoundation\RedirectResponse', 'redirect'],
104 * Tests the redirectForm() method when the redirect is NULL.
106 * @covers ::redirectForm
108 public function testRedirectWithNull() {
109 $form_submitter = $this->getFormSubmitter();
111 $form_state = $this->getMock('Drupal\Core\Form\FormStateInterface');
112 $form_state->expects($this->once())
113 ->method('getRedirect')
116 $this->urlGenerator->expects($this->once())
117 ->method('generateFromRoute')
118 ->with('<current>', [], ['query' => [], 'absolute' => TRUE])
119 ->willReturn('http://localhost/test-path');
121 $redirect = $form_submitter->redirectForm($form_state);
122 // If we have no redirect, we redirect to the current URL.
123 $this->assertSame('http://localhost/test-path', $redirect->getTargetUrl());
124 $this->assertSame(303, $redirect->getStatusCode());
128 * Tests redirectForm() when a redirect is a Url object.
130 * @covers ::redirectForm
132 * @dataProvider providerTestRedirectWithUrl
134 public function testRedirectWithUrl(Url $redirect_value, $result, $status = 303) {
135 $container = new ContainerBuilder();
136 $container->set('url_generator', $this->urlGenerator);
137 \Drupal::setContainer($container);
138 $form_submitter = $this->getFormSubmitter();
139 $this->urlGenerator->expects($this->once())
140 ->method('generateFromRoute')
141 ->will($this->returnValueMap([
142 ['test_route_a', [], ['absolute' => TRUE], FALSE, 'test-route'],
143 ['test_route_b', ['key' => 'value'], ['absolute' => TRUE], FALSE, 'test-route/value'],
147 $form_state = $this->getMock('Drupal\Core\Form\FormStateInterface');
148 $form_state->expects($this->once())
149 ->method('getRedirect')
150 ->willReturn($redirect_value);
151 $redirect = $form_submitter->redirectForm($form_state);
152 $this->assertSame($result, $redirect->getTargetUrl());
153 $this->assertSame($status, $redirect->getStatusCode());
157 * Provides test data for testing the redirectForm() method with a route name.
160 * Returns some test data.
162 public function providerTestRedirectWithUrl() {
164 [new Url('test_route_a', [], ['absolute' => TRUE]), 'test-route'],
165 [new Url('test_route_b', ['key' => 'value'], ['absolute' => TRUE]), 'test-route/value'],
170 * Tests the redirectForm() method with a response object.
172 * @covers ::redirectForm
174 public function testRedirectWithResponseObject() {
175 $form_submitter = $this->getFormSubmitter();
176 $redirect = new RedirectResponse('/example');
177 $form_state = $this->getMock('Drupal\Core\Form\FormStateInterface');
178 $form_state->expects($this->once())
179 ->method('getRedirect')
180 ->willReturn($redirect);
182 $result_redirect = $form_submitter->redirectForm($form_state);
184 $this->assertSame($redirect, $result_redirect);
188 * Tests the redirectForm() method when no redirect is expected.
190 * @covers ::redirectForm
192 public function testRedirectWithoutResult() {
193 $form_submitter = $this->getFormSubmitter();
194 $this->urlGenerator->expects($this->never())
195 ->method('generateFromRoute');
196 $this->unroutedUrlAssembler->expects($this->never())
197 ->method('assemble');
198 $container = new ContainerBuilder();
199 $container->set('url_generator', $this->urlGenerator);
200 $container->set('unrouted_url_assembler', $this->unroutedUrlAssembler);
201 \Drupal::setContainer($container);
202 $form_state = $this->getMock('Drupal\Core\Form\FormStateInterface');
203 $form_state->expects($this->once())
204 ->method('getRedirect')
206 $redirect = $form_submitter->redirectForm($form_state);
207 $this->assertNull($redirect);
211 * @covers ::executeSubmitHandlers
213 public function testExecuteSubmitHandlers() {
214 $form_submitter = $this->getFormSubmitter();
215 $mock = $this->getMockForAbstractClass('Drupal\Core\Form\FormBase', [], '', TRUE, TRUE, TRUE, ['submit_handler', 'hash_submit', 'simple_string_submit']);
216 $mock->expects($this->once())
217 ->method('submit_handler')
218 ->with($this->isType('array'), $this->isInstanceOf('Drupal\Core\Form\FormStateInterface'));
219 $mock->expects($this->once())
220 ->method('hash_submit')
221 ->with($this->isType('array'), $this->isInstanceOf('Drupal\Core\Form\FormStateInterface'));
222 $mock->expects($this->once())
223 ->method('simple_string_submit')
224 ->with($this->isType('array'), $this->isInstanceOf('Drupal\Core\Form\FormStateInterface'));
227 $form_state = new FormState();
228 $form_submitter->executeSubmitHandlers($form, $form_state);
230 $form['#submit'][] = [$mock, 'hash_submit'];
231 $form_submitter->executeSubmitHandlers($form, $form_state);
233 // $form_state submit handlers will supersede $form handlers.
234 $form_state->setSubmitHandlers([[$mock, 'submit_handler']]);
235 $form_submitter->executeSubmitHandlers($form, $form_state);
237 // Methods directly on the form object can be specified as a string.
238 $form_state = (new FormState())
239 ->setFormObject($mock)
240 ->setSubmitHandlers(['::simple_string_submit']);
241 $form_submitter->executeSubmitHandlers($form, $form_state);
245 * @return \Drupal\Core\Form\FormSubmitterInterface
247 protected function getFormSubmitter() {
248 $request_stack = new RequestStack();
249 $request_stack->push(Request::create('/test-path'));
250 return $this->getMockBuilder('Drupal\Core\Form\FormSubmitter')
251 ->setConstructorArgs([$request_stack, $this->urlGenerator])
252 ->setMethods(['batchGet', 'drupalInstallationAttempted'])