Issue #1987716 by pfrenssen, tim.plunkett, kgoel: Provide a FormTestBase class to allow PHPUnit form tests.
parent
aa15f0ca32
commit
eacd8a50b1
|
@ -620,7 +620,7 @@ class FormBuilder implements FormBuilderInterface {
|
|||
// possibly ending execution. We make sure we do not react to the batch
|
||||
// that is already being processed (if a batch operation performs a
|
||||
// self::submitForm).
|
||||
if ($batch =& batch_get() && !isset($batch['current_set'])) {
|
||||
if ($batch = &$this->batchGet() && !isset($batch['current_set'])) {
|
||||
// Store $form_state information in the batch definition.
|
||||
// We need the full $form_state when either:
|
||||
// - Some submit handlers were saved to be called during batch
|
||||
|
@ -1195,7 +1195,7 @@ class FormBuilder implements FormBuilderInterface {
|
|||
// Check if a previous _submit handler has set a batch, but make sure we
|
||||
// do not react to a batch that is already being processed (for instance
|
||||
// if a batch operation performs a self::submitForm()).
|
||||
if ($type == 'submit' && ($batch =& batch_get()) && !isset($batch['id'])) {
|
||||
if ($type == 'submit' && ($batch = &$this->batchGet()) && !isset($batch['id'])) {
|
||||
// Some previous submit handler has set a batch. To ensure correct
|
||||
// execution order, store the call in a special 'control' batch set.
|
||||
// See _batch_next_set().
|
||||
|
@ -1837,4 +1837,11 @@ class FormBuilder implements FormBuilderInterface {
|
|||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps batch_get().
|
||||
*/
|
||||
protected function &batchGet() {
|
||||
return batch_get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -656,17 +656,6 @@ class FormTest extends WebTestBase {
|
|||
$this->assertTrue(!empty($element), 'The textarea has the proper required attribute.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests error border of multiple fields with same name in a page.
|
||||
*/
|
||||
function testMultiFormSameNameErrorClass() {
|
||||
$this->drupalGet('form-test/double-form');
|
||||
$edit = array();
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$this->assertFieldByXpath('//input[@id="edit-name" and contains(@class, "error")]', NULL, 'Error input form element class found for first element.');
|
||||
$this->assertNoFieldByXpath('//input[@id="edit-name--2" and contains(@class, "error")]', NULL, 'No error input form element class found for second element.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a form with a form state storing a database connection.
|
||||
*/
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\system\Tests\Form\HTMLIdTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\system\Tests\Form;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests uniqueness of generated HTML IDs.
|
||||
*/
|
||||
class HTMLIdTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('form_test');
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Unique HTML IDs',
|
||||
'description' => 'Tests functionality of drupal_html_id().',
|
||||
'group' => 'Form API',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that HTML IDs do not get duplicated when form validation fails.
|
||||
*/
|
||||
function testHTMLId() {
|
||||
$this->drupalGet('form-test/double-form');
|
||||
$this->assertNoDuplicateIds('There are no duplicate IDs');
|
||||
|
||||
// Submit second form with empty title.
|
||||
$edit = array();
|
||||
$this->drupalPostForm(NULL, $edit, 'Save', array(), array(), 'form-test-html-id--2');
|
||||
$this->assertNoDuplicateIds('There are no duplicate IDs');
|
||||
}
|
||||
|
||||
}
|
|
@ -2056,34 +2056,6 @@ function form_test_required_attribute($form, &$form_state) {
|
|||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback returns two instances of the same form.
|
||||
*
|
||||
* @deprecated \Drupal\form_test\Controller\FormTestController::doubleForm()
|
||||
*/
|
||||
function form_test_double_form() {
|
||||
return array(
|
||||
'form1' => drupal_get_form('form_test_html_id'),
|
||||
'form2' => drupal_get_form('form_test_html_id'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a simple form to test duplicate HTML IDs.
|
||||
*/
|
||||
function form_test_html_id($form, &$form_state) {
|
||||
$form['name'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => 'name',
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => 'Save',
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a simple form to test form button classes.
|
||||
*
|
||||
|
|
|
@ -77,14 +77,6 @@ form_test.wrapper:
|
|||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
form_test.double_form:
|
||||
path: '/form-test/double-form'
|
||||
defaults:
|
||||
_title: 'Double form test'
|
||||
_content: '\Drupal\form_test\Controller\FormTestController::doubleForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
form_test.alter_form:
|
||||
path: '/form-test/alter'
|
||||
defaults:
|
||||
|
|
|
@ -42,11 +42,4 @@ class FormTestController extends ControllerBase {
|
|||
return form_test_wrapper_callback($form_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Remove form_test_double_form().
|
||||
*/
|
||||
public function doubleForm() {
|
||||
return form_test_double_form();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,68 +8,17 @@
|
|||
namespace Drupal\Tests\Core\Form {
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Form\FormBuilder;
|
||||
use Drupal\Core\Form\FormInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Tests the form builder.
|
||||
*
|
||||
* @group Drupal
|
||||
* @group Form
|
||||
*/
|
||||
class FormBuilderTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The form builder being tested.
|
||||
*
|
||||
* @var \Drupal\Core\Form\FormBuilder
|
||||
*/
|
||||
protected $formBuilder;
|
||||
|
||||
/**
|
||||
* The mocked URL generator.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Routing\UrlGeneratorInterface
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
|
||||
/**
|
||||
* The mocked module handler.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The expirable key value store used by form cache.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
|
||||
*/
|
||||
protected $formCache;
|
||||
|
||||
/**
|
||||
* The expirable key value store used by form state cache.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
|
||||
*/
|
||||
protected $formStateCache;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* The CSRF token generator.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Access\CsrfTokenGenerator
|
||||
*/
|
||||
protected $csrfToken;
|
||||
class FormBuilderTest extends FormTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -82,39 +31,6 @@ class FormBuilderTest extends UnitTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
|
||||
|
||||
$this->formCache = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface');
|
||||
$this->formStateCache = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface');
|
||||
$key_value_expirable_factory = $this->getMockBuilder('\Drupal\Core\KeyValueStore\KeyValueExpirableFactory')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$key_value_expirable_factory->expects($this->any())
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('form', $this->formCache),
|
||||
array('form_state', $this->formStateCache),
|
||||
)));
|
||||
|
||||
$event_dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
$this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface');
|
||||
$translation_manager = $this->getStringTranslationStub();
|
||||
$this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$http_kernel = $this->getMockBuilder('Drupal\Core\HttpKernel')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->formBuilder = new TestFormBuilder($this->moduleHandler, $key_value_expirable_factory, $event_dispatcher, $this->urlGenerator, $translation_manager, $this->csrfToken, $http_kernel);
|
||||
$this->formBuilder->setRequest(new Request());
|
||||
|
||||
$this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
|
||||
$this->formBuilder->setCurrentUser($this->account);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getFormId() method with a string based form ID.
|
||||
*/
|
||||
|
@ -729,147 +645,6 @@ class FormBuilderTest extends UnitTestCase {
|
|||
$this->formBuilder->buildForm($form_arg, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
/**
|
||||
* {@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['select'] = array(
|
||||
'#input' => TRUE,
|
||||
'#multiple' => FALSE,
|
||||
'#empty_value' => '',
|
||||
);
|
||||
$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 drupalInstallationAttempted() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function drupalSetMessage($message = NULL, $type = 'status', $repeat = FALSE) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function watchdog($type, $message, array $variables = NULL, $severity = WATCHDOG_NOTICE, $link = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function drupalHtmlClass($class) {
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function drupalHtmlId($id) {
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function drupalStaticReset($name = NULL) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestForm implements FormInterface {
|
||||
|
@ -892,48 +667,9 @@ class TestFormInjected extends TestForm implements ContainerInjectionInterface {
|
|||
}
|
||||
|
||||
namespace {
|
||||
function test_form_id() {
|
||||
$form['test'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => 'Test',
|
||||
);
|
||||
$form['select'] = array(
|
||||
'#type' => 'select',
|
||||
'#options' => array(
|
||||
'foo' => 'foo',
|
||||
'bar' => 'bar',
|
||||
),
|
||||
);
|
||||
$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;
|
||||
}
|
||||
function test_form_id_custom_submit(array &$form, array &$form_state) {
|
||||
}
|
||||
|
||||
if (!defined('WATCHDOG_ERROR')) {
|
||||
define('WATCHDOG_ERROR', 3);
|
||||
}
|
||||
if (!function_exists('batch_get')) {
|
||||
function &batch_get() {
|
||||
$batch = array();
|
||||
return $batch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,366 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Form\FormTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Form {
|
||||
|
||||
use Drupal\Core\Form\FormBuilder;
|
||||
use Drupal\Core\Form\FormInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
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;
|
||||
|
||||
/**
|
||||
* The mocked URL generator.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Routing\UrlGeneratorInterface
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
|
||||
/**
|
||||
* The mocked module handler.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The expirable key value store used by form cache.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
|
||||
*/
|
||||
protected $formCache;
|
||||
|
||||
/**
|
||||
* The expirable key value store used by form state cache.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
|
||||
*/
|
||||
protected $formStateCache;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* The CSRF token generator.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Access\CsrfTokenGenerator
|
||||
*/
|
||||
protected $csrfToken;
|
||||
|
||||
/**
|
||||
* The request.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* The event dispatcher.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Symfony\Component\EventDispatcher\EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* The expirable key value factory.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\KeyValueStore\KeyValueExpirableFactory
|
||||
*/
|
||||
protected $keyValueExpirableFactory;
|
||||
|
||||
/**
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\StringTranslation\TranslationInterface
|
||||
*/
|
||||
protected $translationManager;
|
||||
|
||||
/**
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\HttpKernel
|
||||
*/
|
||||
protected $httpKernel;
|
||||
|
||||
public function setUp() {
|
||||
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
|
||||
|
||||
$this->formCache = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface');
|
||||
$this->formStateCache = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface');
|
||||
$this->keyValueExpirableFactory = $this->getMockBuilder('Drupal\Core\KeyValueStore\KeyValueExpirableFactory')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->keyValueExpirableFactory->expects($this->any())
|
||||
->method('get')
|
||||
->will($this->returnValueMap(array(
|
||||
array('form', $this->formCache),
|
||||
array('form_state', $this->formStateCache),
|
||||
)));
|
||||
|
||||
$this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
$this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface');
|
||||
$this->translationManager = $this->getStringTranslationStub();
|
||||
$this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->httpKernel = $this->getMockBuilder('Drupal\Core\HttpKernel')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->request = new Request();
|
||||
$this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
|
||||
|
||||
$this->setupFormBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function tearDown() {
|
||||
$this->formBuilder->drupalStaticReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a new form builder object to test.
|
||||
*/
|
||||
protected function setupFormBuilder() {
|
||||
$this->formBuilder = new TestFormBuilder($this->moduleHandler, $this->keyValueExpirableFactory, $this->eventDispatcher, $this->urlGenerator, $this->translationManager, $this->csrfToken, $this->httpKernel);
|
||||
$this->formBuilder->setRequest($this->request);
|
||||
$this->formBuilder->setCurrentUser($this->account);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param array $form_state
|
||||
* An associative array containing the current state of the form.
|
||||
*
|
||||
* @return array
|
||||
* The built form.
|
||||
*/
|
||||
protected function simulateFormSubmission($form_id, FormInterface $form_arg, array &$form_state) {
|
||||
$form_state['build_info']['callback_object'] = $form_arg;
|
||||
$form_state['build_info']['args'] = array();
|
||||
$form_state['input']['op'] = 'Submit';
|
||||
$form_state['programmed'] = TRUE;
|
||||
$form_state['submitted'] = TRUE;
|
||||
return $this->formBuilder->buildForm($form_id, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 drupalInstallationAttempted() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function menuGetItem() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function drupalSetMessage($message = NULL, $type = 'status', $repeat = FALSE) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function watchdog($type, $message, array $variables = NULL, $severity = WATCHDOG_NOTICE, $link = NULL) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function &batchGet() {
|
||||
$batch = array();
|
||||
return $batch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Form\FormValidationTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Form;
|
||||
|
||||
/**
|
||||
* Tests various form element validation mechanisms.
|
||||
*
|
||||
* @group Drupal
|
||||
* @group Form
|
||||
*/
|
||||
class FormValidationTest extends FormTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Form element validation',
|
||||
'description' => 'Tests various form element validation mechanisms.',
|
||||
'group' => 'Form API',
|
||||
);
|
||||
}
|
||||
|
||||
public function testNoDuplicateErrorsForIdenticalForm() {
|
||||
$form_id = 'test_form_id';
|
||||
$expected_form = $form_id();
|
||||
$expected_form['test']['#required'] = TRUE;
|
||||
|
||||
// Mock a form object that will be built three times.
|
||||
$form_arg = $this->getMockForm($form_id, $expected_form, 3);
|
||||
|
||||
// The first form will have errors.
|
||||
$form_state = array();
|
||||
$this->formBuilder->getFormId($form_arg, $form_state);
|
||||
$this->simulateFormSubmission($form_id, $form_arg, $form_state);
|
||||
$errors = $this->formBuilder->getErrors($form_state);
|
||||
$this->assertNotEmpty($errors['test']);
|
||||
|
||||
// The second form will not have errors.
|
||||
$form_state = array();
|
||||
$this->simulateFormSubmission($form_id, $form_arg, $form_state);
|
||||
$errors = $this->formBuilder->getErrors($form_state);
|
||||
$this->assertEmpty($errors);
|
||||
|
||||
// Reset the form builder.
|
||||
$this->setupFormBuilder();
|
||||
|
||||
// On a new request, the first form will have errors again.
|
||||
$form_state = array();
|
||||
$this->simulateFormSubmission($form_id, $form_arg, $form_state);
|
||||
$errors = $this->formBuilder->getErrors($form_state);
|
||||
$this->assertNotEmpty($errors['test']);
|
||||
}
|
||||
|
||||
public function testUniqueHtmlId() {
|
||||
$form_id = 'test_form_id';
|
||||
$expected_form = $form_id();
|
||||
$expected_form['test']['#required'] = TRUE;
|
||||
|
||||
// Mock a form object that will be built three times.
|
||||
$form_arg = $this->getMockForm($form_id, $expected_form, 2);
|
||||
|
||||
$form_state = array();
|
||||
$this->formBuilder->getFormId($form_arg, $form_state);
|
||||
$form = $this->simulateFormSubmission($form_id, $form_arg, $form_state);
|
||||
$this->assertSame($form_id, $form['#id']);
|
||||
|
||||
$form_state = array();
|
||||
$form = $this->simulateFormSubmission($form_id, $form_arg, $form_state);
|
||||
$this->assertSame("$form_id--2", $form['#id']);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue