Newer
Older
Angie Byron
committed
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Form\FormTestBase.
*/
namespace Drupal\Tests\Core\Form {
use Drupal\Component\Utility\Html;
Angie Byron
committed
use Drupal\Core\Form\FormBuilder;
use Drupal\Core\Form\FormInterface;
Dries Buytaert
committed
use Drupal\Core\Form\FormStateInterface;
Angie Byron
committed
use Drupal\Core\Session\AccountInterface;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
Angie Byron
committed
use Symfony\Component\HttpFoundation\Response;
/**
* Provides a base class for testing form functionality.
*
* @see \Drupal\Core\Form\FormBuilder
*/
abstract class FormTestBase extends UnitTestCase {
/**
* The form builder being tested.
*
* @var \Drupal\Core\Form\FormBuilderInterface
*/
protected $formBuilder;
Alex Pott
committed
/**
* @var \Drupal\Core\Form\FormValidatorInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $formValidator;
/**
* @var \Drupal\Core\Form\FormSubmitterInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $formSubmitter;
Angie Byron
committed
/**
* The mocked URL generator.
*
Alex Pott
committed
* @var \Drupal\Core\Routing\UrlGeneratorInterface|\PHPUnit_Framework_MockObject_MockObject
Angie Byron
committed
*/
protected $urlGenerator;
/**
* The mocked module handler.
*
Alex Pott
committed
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
Angie Byron
committed
*/
protected $moduleHandler;
/**
Angie Byron
committed
* The form cache.
Angie Byron
committed
*
Angie Byron
committed
* @var \Drupal\Core\Form\FormCacheInterface|\PHPUnit_Framework_MockObject_MockObject
Angie Byron
committed
*/
protected $formCache;
/**
* The current user.
*
Alex Pott
committed
* @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
Angie Byron
committed
*/
protected $account;
Alex Pott
committed
/**
* The controller resolver.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $controllerResolver;
Angie Byron
committed
/**
* The CSRF token generator.
*
Alex Pott
committed
* @var \Drupal\Core\Access\CsrfTokenGenerator|\PHPUnit_Framework_MockObject_MockObject
Angie Byron
committed
*/
protected $csrfToken;
/**
* The request.
*
* @var \Symfony\Component\HttpFoundation\Request
*/
protected $request;
/**
* The request stack.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
Alex Pott
committed
/**
* The class results.
*
* @var \Drupal\Core\DependencyInjection\ClassResolverInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $classResolver;
Angie Byron
committed
/**
* The event dispatcher.
*
Alex Pott
committed
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject
Angie Byron
committed
*/
protected $eventDispatcher;
/**
Alex Pott
committed
* @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $translationManager;
/**
* @var \Symfony\Component\HttpKernel\HttpKernel|\PHPUnit_Framework_MockObject_MockObject
Angie Byron
committed
*/
protected $httpKernel;
/**
* @var \PHPUnit_Framework_MockObject_MockObject|\Psr\Log\LoggerInterface
*/
protected $logger;
/**
* The mocked theme manager.
*
* @var \Drupal\Core\Theme\ThemeManagerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $themeManager;
Alex Pott
committed
protected function setUp() {
Angie Byron
committed
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
Angie Byron
committed
$this->formCache = $this->getMock('Drupal\Core\Form\FormCacheInterface');
Angie Byron
committed
$this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface');
Alex Pott
committed
$this->classResolver = $this->getClassResolverStub();
Angie Byron
committed
$this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
->disableOriginalConstructor()
->getMock();
$this->httpKernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel')
Angie Byron
committed
->disableOriginalConstructor()
->getMock();
$this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
$this->themeManager = $this->getMock('Drupal\Core\Theme\ThemeManagerInterface');
$this->request = new Request();
$this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
$this->requestStack = new RequestStack();
$this->requestStack->push($this->request);
$this->logger = $this->getMock('Drupal\Core\Logger\LoggerChannelInterface');
$this->formValidator = $this->getMockBuilder('Drupal\Core\Form\FormValidator')
->setConstructorArgs(array($this->requestStack, $this->getStringTranslationStub(), $this->csrfToken, $this->logger))
->setMethods(array('drupalSetMessage'))
->getMock();
$this->formSubmitter = $this->getMockBuilder('Drupal\Core\Form\FormSubmitter')
->setConstructorArgs(array($this->requestStack, $this->urlGenerator))
->setMethods(array('batchGet', 'drupalInstallationAttempted'))
->getMock();
Angie Byron
committed
Angie Byron
committed
$this->formBuilder = new TestFormBuilder($this->formValidator, $this->formSubmitter, $this->formCache, $this->moduleHandler, $this->eventDispatcher, $this->requestStack, $this->classResolver, $this->themeManager, $this->csrfToken, $this->httpKernel);
$this->formBuilder->setCurrentUser($this->account);
Angie Byron
committed
}
/**
* {@inheritdoc}
*/
protected function tearDown() {
Html::resetSeenIds();
Angie Byron
committed
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
}
/**
* Provides a mocked form object.
*
* @param string $form_id
* (optional) The form ID to be used. If none is provided, the form will be
* set with no expectation about getFormId().
* @param mixed $expected_form
* (optional) If provided, the expected form response for buildForm() to
* return. Defaults to NULL.
* @param int $count
* (optional) The number of times the form is expected to be built. Defaults
* to 1.
*
* @return \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Form\FormInterface
* The mocked form object.
*/
protected function getMockForm($form_id, $expected_form = NULL, $count = 1) {
$form = $this->getMock('Drupal\Core\Form\FormInterface');
$form->expects($this->once())
->method('getFormId')
->will($this->returnValue($form_id));
if ($expected_form) {
$form->expects($this->exactly($count))
->method('buildForm')
->will($this->returnValue($expected_form));
}
return $form;
}
/**
* Simulates a form submission within a request, bypassing submitForm().
*
* Calling submitForm() will reset the form builder, if two forms were on the
* same page, they will be submitted simultaneously.
*
* @param string $form_id
* The unique string identifying the form.
* @param \Drupal\Core\Form\FormInterface $form_arg
* The form object.
Dries Buytaert
committed
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
Alex Pott
committed
* @param bool $programmed
* Whether $form_state['programmed'] should be set to TRUE or not. If it is
* not set to TRUE, you must provide additional data in $form_state for the
* submission to take place.
Angie Byron
committed
*
* @return array
* The built form.
*/
Dries Buytaert
committed
protected function simulateFormSubmission($form_id, FormInterface $form_arg, FormStateInterface $form_state, $programmed = TRUE) {
Angie Byron
committed
$form_state['build_info']['callback_object'] = $form_arg;
$form_state['build_info']['args'] = array();
Angie Byron
committed
$input = $form_state->getUserInput();
$input['op'] = 'Submit';
$form_state->setUserInput($input);
Alex Pott
committed
$form_state['programmed'] = $programmed;
Angie Byron
committed
$form_state['submitted'] = TRUE;
return $this->formBuilder->buildForm($form_arg, $form_state);
Angie Byron
committed
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
}
/**
* Asserts that the expected form structure is found in a form for a given key.
*
* @param array $expected_form
* The expected form structure.
* @param array $actual_form
* The actual form.
* @param string|null $form_key
* (optional) The form key to look in. Otherwise the entire form will be
* compared.
*/
protected function assertFormElement(array $expected_form, array $actual_form, $form_key = NULL) {
$expected_element = $form_key ? $expected_form[$form_key] : $expected_form;
$actual_element = $form_key ? $actual_form[$form_key] : $actual_form;
$this->assertSame(array_intersect_key($expected_element, $actual_element), $expected_element);
}
}
/**
* Provides a test form builder class.
*/
class TestFormBuilder extends FormBuilder {
protected static $seenIds = array();
/**
* {@inheritdoc}
*/
protected function sendResponse(Response $response) {
parent::sendResponse($response);
// Throw an exception instead of exiting.
throw new \Exception('exit');
}
/**
* @param \Drupal\Core\Session\AccountInterface $account
*/
public function setCurrentUser(AccountInterface $account) {
$this->currentUser = $account;
}
/**
* {@inheritdoc}
*/
protected function getElementInfo($type) {
$types['token'] = array(
'#input' => TRUE,
);
$types['value'] = array(
'#input' => TRUE,
);
$types['radios'] = array(
'#input' => TRUE,
);
$types['textfield'] = array(
'#input' => TRUE,
);
$types['submit'] = array(
'#input' => TRUE,
'#name' => 'op',
'#is_button' => TRUE,
);
if (!isset($types[$type])) {
$types[$type] = array();
}
return $types[$type];
}
/**
* {@inheritdoc}
*/
protected function drupalHtmlClass($class) {
return $class;
}
/**
* {@inheritdoc}
*/
protected function drupalHtmlId($id) {
if (isset(static::$seenIds[$id])) {
$id = $id . '--' . ++static::$seenIds[$id];
}
else {
static::$seenIds[$id] = 1;
}
return $id;
}
/**
* {@inheritdoc}
*/
public function drupalStaticReset($name = NULL) {
static::$seenIds = array();
}
}
}
namespace {
function test_form_id() {
$form['test'] = array(
'#type' => 'textfield',
'#title' => 'Test',
);
$form['options'] = array(
'#type' => 'radios',
'#options' => array(
'foo' => 'foo',
'bar' => 'bar',
),
);
$form['value'] = array(
'#type' => 'value',
'#value' => 'bananas',
);
$form['actions'] = array(
'#type' => 'actions',
);
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
return $form;
}
}