Unverified Commit 47d067a1 authored by alexpott's avatar alexpott
Browse files

Issue #2900291 by martin107, Lendude, RytoEX, vijaycs85, borisson_, jibran,...

Issue #2900291 by martin107, Lendude, RytoEX, vijaycs85, borisson_, jibran, dawehner: Form: Convert system functional tests to phpunit Part 2
parent 9df150e1
<?php
namespace Drupal\system\Tests\Form;
namespace Drupal\Tests\system\Functional\Form;
use Drupal\Core\Form\FormState;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\system\Functional\Form\StubForm;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the tableselect form element for expected behavior.
*
* @group Form
*/
class ElementsTableSelectTest extends WebTestBase {
class ElementsTableSelectTest extends BrowserTestBase {
/**
* Modules to enable.
......@@ -27,35 +26,14 @@ public function testMultipleTrue() {
$this->drupalGet('form_test/tableselect/multiple-true');
$this->assertNoText(t('Empty text.'), 'Empty text should not be displayed.');
$this->assertSession()->responseNotContains('Empty text.', 'Empty text should not be displayed.');
// Test for the presence of the Select all rows tableheader.
$this->assertFieldByXPath('//th[@class="select-all"]', NULL, 'Presence of the "Select all" checkbox.');
$this->assertNotEmpty($this->xpath('//th[@class="select-all"]'), 'Presence of the "Select all" checkbox.');
$rows = ['row1', 'row2', 'row3'];
foreach ($rows as $row) {
$this->assertFieldByXPath('//input[@type="checkbox"]', $row, format_string('Checkbox for value @row.', ['@row' => $row]));
}
}
/**
* Test the presence of ajax functionality for all options.
*/
public function testAjax() {
$rows = ['row1', 'row2', 'row3'];
// Test checkboxes (#multiple == TRUE).
foreach ($rows as $row) {
$element = 'tableselect[' . $row . ']';
$edit = [$element => TRUE];
$result = $this->drupalPostAjaxForm('form_test/tableselect/multiple-true', $edit, $element);
$this->assertFalse(empty($result), t('Ajax triggers on checkbox for @row.', ['@row' => $row]));
}
// Test radios (#multiple == FALSE).
$element = 'tableselect';
foreach ($rows as $row) {
$edit = [$element => $row];
$result = $this->drupalPostAjaxForm('form_test/tableselect/multiple-false', $edit, $element);
$this->assertFalse(empty($result), t('Ajax triggers on radio for @row.', ['@row' => $row]));
$this->assertNotEmpty($this->xpath('//input[@type="checkbox"]', [$row]), "Checkbox for the value $row.");
}
}
......@@ -65,40 +43,39 @@ public function testAjax() {
public function testMultipleFalse() {
$this->drupalGet('form_test/tableselect/multiple-false');
$this->assertNoText(t('Empty text.'), 'Empty text should not be displayed.');
$this->assertSession()->pageTextNotContains('Empty text.');
// Test for the absence of the Select all rows tableheader.
$this->assertNoFieldByXPath('//th[@class="select-all"]', '', 'Absence of the "Select all" checkbox.');
$this->assertFalse($this->xpath('//th[@class="select-all"]'));
$rows = ['row1', 'row2', 'row3'];
foreach ($rows as $row) {
$this->assertFieldByXPath('//input[@type="radio"]', $row, format_string('Radio button for value @row.', ['@row' => $row]));
$this->assertNotEmpty($this->xpath('//input[@type="radio"]', [$row], "Radio button value: $row"));
}
}
/**
* Tests the display when #colspan is set.
*/
public function testTableselectColSpan() {
public function testTableSelectColSpan() {
$this->drupalGet('form_test/tableselect/colspan');
$this->assertText(t('Three'), 'Presence of the third column');
$this->assertNoText(t('Four'), 'Absence of a fourth column');
$this->assertSession()->pageTextContains('Three', 'Presence of the third column');
$this->assertSession()->pageTextNotContains('Four', 'Absence of a fourth column');
// There should be three labeled column headers and 1 for the input.
$table_head = $this->xpath('//thead');
$this->assertEqual(count($table_head[0]->tr->th), 4, 'There are four column headers');
$table_head = $this->xpath('//thead/tr/th');
$this->assertEquals(count($table_head), 4, 'There are four column headers');
$table_body = $this->xpath('//tbody');
// The first two body rows should each have 5 table cells: One for the
// radio, one cell in the first column, one cell in the second column,
// and two cells in the third column which has colspan 2.
for ($i = 0; $i <= 1; $i++) {
$this->assertEqual(count($table_body[0]->tr[$i]->td), 5, format_string('There are five cells in row @row.', ['@row' => $i]));
$this->assertEquals(count($this->xpath('//tbody/tr[' . ($i + 1) . ']/td')), 5, 'There are five cells in row ' . $i);
}
// The third row should have 3 cells, one for the radio, one spanning the
// first and second column, and a third in column 3 (which has colspan 3).
$this->assertEqual(count($table_body[0]->tr[2]->td), 3, 'There are three cells in row 3.');
$this->assertEquals(count($this->xpath('//tbody/tr[3]/td')), 3, 'There are three cells in row 3.');
}
/**
......@@ -106,7 +83,7 @@ public function testTableselectColSpan() {
*/
public function testEmptyText() {
$this->drupalGet('form_test/tableselect/empty-text');
$this->assertText(t('Empty text.'), 'Empty text should be displayed.');
$this->assertSession()->pageTextContains('Empty text.', 'Empty text should be displayed.');
}
/**
......@@ -119,18 +96,19 @@ public function testMultipleTrueSubmit() {
$edit['tableselect[row1]'] = TRUE;
$this->drupalPostForm('form_test/tableselect/multiple-true', $edit, 'Submit');
$this->assertText(t('Submitted: row1 = row1'), 'Checked checkbox row1');
$this->assertText(t('Submitted: row2 = 0'), 'Unchecked checkbox row2.');
$this->assertText(t('Submitted: row3 = 0'), 'Unchecked checkbox row3.');
$assert_session = $this->assertSession();
$assert_session->pageTextContains('Submitted: row1 = row1', 'Checked checkbox row1');
$assert_session->pageTextContains('Submitted: row2 = 0', 'Unchecked checkbox row2.');
$assert_session->pageTextContains('Submitted: row3 = 0', 'Unchecked checkbox row3.');
// Test a submission with multiple checkboxes checked.
$edit['tableselect[row1]'] = TRUE;
$edit['tableselect[row3]'] = TRUE;
$this->drupalPostForm('form_test/tableselect/multiple-true', $edit, 'Submit');
$this->assertText(t('Submitted: row1 = row1'), 'Checked checkbox row1.');
$this->assertText(t('Submitted: row2 = 0'), 'Unchecked checkbox row2.');
$this->assertText(t('Submitted: row3 = row3'), 'Checked checkbox row3.');
$assert_session->pageTextContains('Submitted: row1 = row1', 'Checked checkbox row1.');
$assert_session->pageTextContains('Submitted: row2 = 0', 'Unchecked checkbox row2.');
$assert_session->pageTextContains('Submitted: row3 = row3', 'Checked checkbox row3.');
}
......@@ -140,7 +118,7 @@ public function testMultipleTrueSubmit() {
public function testMultipleFalseSubmit() {
$edit['tableselect'] = 'row1';
$this->drupalPostForm('form_test/tableselect/multiple-false', $edit, 'Submit');
$this->assertText(t('Submitted: row1'), 'Selected radio button');
$this->assertSession()->pageTextContains('Submitted: row1', 'Selected radio button');
}
/**
......@@ -149,18 +127,18 @@ public function testMultipleFalseSubmit() {
public function testAdvancedSelect() {
// When #multiple = TRUE a Select all checkbox should be displayed by default.
$this->drupalGet('form_test/tableselect/advanced-select/multiple-true-default');
$this->assertFieldByXPath('//th[@class="select-all"]', NULL, 'Display a "Select all" checkbox by default when #multiple is TRUE.');
$this->xpath('//th[@class="select-all"]');
// When #js_select is set to FALSE, a "Select all" checkbox should not be displayed.
$this->drupalGet('form_test/tableselect/advanced-select/multiple-true-no-advanced-select');
$this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, 'Do not display a "Select all" checkbox when #js_select is FALSE.');
$this->assertFalse($this->xpath('//th[@class="select-all"]'));
// A "Select all" checkbox never makes sense when #multiple = FALSE, regardless of the value of #js_select.
$this->drupalGet('form_test/tableselect/advanced-select/multiple-false-default');
$this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, 'Do not display a "Select all" checkbox when #multiple is FALSE.');
$this->assertFalse($this->xpath('//th[@class="select-all"]'));
$this->drupalGet('form_test/tableselect/advanced-select/multiple-false-advanced-select');
$this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, 'Do not display a "Select all" checkbox when #multiple is FALSE, even when #js_select is TRUE.');
$this->assertFalse($this->xpath('//th[@class="select-all"]'));
}
/**
......
<?php
namespace Drupal\Tests\system\Functional\Form;
use Drupal\Tests\BrowserTestBase;
/**
* Tests functionality of \Drupal\Core\Form\FormBuilderInterface::rebuildForm().
*
* @group Form
*/
class RebuildTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['node', 'form_test'];
/**
* A user for testing.
*
* @var \Drupal\user\UserInterface
*/
protected $webUser;
protected function setUp() {
parent::setUp();
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']);
$this->webUser = $this->drupalCreateUser(['access content']);
$this->drupalLogin($this->webUser);
}
/**
* Tests preservation of values.
*/
public function testRebuildPreservesValues() {
$edit = [
'checkbox_1_default_off' => TRUE,
'checkbox_1_default_on' => FALSE,
'text_1' => 'foo',
];
$this->drupalPostForm('form-test/form-rebuild-preserve-values', $edit, 'Add more');
$assert_session = $this->assertSession();
// Verify that initial elements retained their submitted values.
$assert_session->checkboxChecked('edit-checkbox-1-default-off');
$assert_session->checkboxNotChecked('edit-checkbox-1-default-on');
$assert_session->fieldValueEquals('edit-text-1', 'foo');
// Verify that newly added elements were initialized with their default values.
$assert_session->checkboxChecked('edit-checkbox-2-default-on');
$assert_session->checkboxNotChecked('edit-checkbox-2-default-off');
$assert_session->fieldValueEquals('edit-text-2', 'DEFAULT 2');
}
}
<?php
namespace Drupal\system\Tests\Form;
namespace Drupal\Tests\system\Functional\Form;
use Drupal\Core\Database\Database;
use Drupal\simpletest\WebTestBase;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Tests\BrowserTestBase;
/**
* Tests a multistep form using form storage and makes sure validation and
......@@ -17,7 +18,7 @@
*
* @group Form
*/
class StorageTest extends WebTestBase {
class StorageTest extends BrowserTestBase {
/**
* Modules to enable.
......@@ -26,6 +27,9 @@ class StorageTest extends WebTestBase {
*/
public static $modules = ['form_test', 'dblog'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
......@@ -37,25 +41,27 @@ protected function setUp() {
*/
public function testForm() {
$this->drupalGet('form_test/form-storage');
$this->assertText('Form constructions: 1');
$assert_session = $this->assertSession();
$assert_session->pageTextContains('Form constructions: 1');
$edit = ['title' => 'new', 'value' => 'value_is_set'];
// Use form rebuilding triggered by a submit button.
$this->drupalPostForm(NULL, $edit, 'Continue submit');
$this->assertText('Form constructions: 2');
$this->assertText('Form constructions: 3');
$assert_session->pageTextContains('Form constructions: 2');
$assert_session->pageTextContains('Form constructions: 3');
// Reset the form to the values of the storage, using a form rebuild
// triggered by button of type button.
$this->drupalPostForm(NULL, ['title' => 'changed'], 'Reset');
$this->assertFieldByName('title', 'new', 'Values have been reset.');
$assert_session->fieldValueEquals('title', 'new');
// After rebuilding, the form has been cached.
$this->assertText('Form constructions: 4');
$assert_session->pageTextContains('Form constructions: 4');
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertText('Form constructions: 4');
$this->assertText('Title: new', 'The form storage has stored the values.');
$assert_session->pageTextContains('Form constructions: 4');
$assert_session->pageTextContains('Title: new', 'The form storage has stored the values.');
}
/**
......@@ -63,26 +69,26 @@ public function testForm() {
*/
public function testFormCached() {
$this->drupalGet('form_test/form-storage', ['query' => ['cache' => 1]]);
$this->assertText('Form constructions: 1');
$this->assertSession()->pageTextContains('Form constructions: 1');
$edit = ['title' => 'new', 'value' => 'value_is_set'];
// Use form rebuilding triggered by a submit button.
$this->drupalPostForm(NULL, $edit, 'Continue submit');
// The first one is for the building of the form.
$this->assertText('Form constructions: 2');
$this->assertSession()->pageTextContains('Form constructions: 2');
// The second one is for the rebuilding of the form.
$this->assertText('Form constructions: 3');
$this->assertSession()->pageTextContains('Form constructions: 3');
// Reset the form to the values of the storage, using a form rebuild
// triggered by button of type button.
$this->drupalPostForm(NULL, ['title' => 'changed'], 'Reset');
$this->assertFieldByName('title', 'new', 'Values have been reset.');
$this->assertText('Form constructions: 4');
$this->assertSession()->fieldValueEquals('title', 'new');
$this->assertSession()->pageTextContains('Form constructions: 4');
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertText('Form constructions: 4');
$this->assertText('Title: new', 'The form storage has stored the values.');
$this->assertSession()->pageTextContains('Form constructions: 4');
$this->assertSession()->pageTextContains('Title: new', 'The form storage has stored the values.');
}
/**
......@@ -125,7 +131,7 @@ public function testCachedFormStorageValidation() {
// validation error. Post again and verify that the rebuilt form contains
// the values of the updated form storage.
$this->drupalPostForm(NULL, ['title' => 'foo', 'value' => 'bar'], 'Save');
$this->assertText("The thing has been changed.", 'The altered form storage value was updated in cache and taken over.');
$this->assertSession()->pageTextContains("The thing has been changed.", 'The altered form storage value was updated in cache and taken over.');
}
/**
......@@ -136,27 +142,27 @@ public function testImmutableForm() {
// Request the form with 'cache' query parameter to enable form caching.
$this->drupalGet('form_test/form-storage', ['query' => ['cache' => 1, 'immutable' => 1]]);
$buildIdFields = $this->xpath('//input[@name="form_build_id"]');
$this->assertEqual(count($buildIdFields), 1, 'One form build id field on the page');
$buildId = (string) $buildIdFields[0]['value'];
$this->assertEquals(count($buildIdFields), 1, 'One form build id field on the page');
$buildId = $buildIdFields[0]->getValue();
// Trigger validation error by submitting an empty title.
$edit = ['title' => ''];
$this->drupalPostForm(NULL, $edit, 'Continue submit');
// Verify that the build-id did change.
$this->assertNoFieldByName('form_build_id', $buildId, 'Build id changes when form validation fails');
$this->assertSession()->hiddenFieldValueNotEquals('form_build_id', $buildId);
// Retrieve the new build-id.
$buildIdFields = $this->xpath('//input[@name="form_build_id"]');
$this->assertEqual(count($buildIdFields), 1, 'One form build id field on the page');
$buildId = (string) $buildIdFields[0]['value'];
$this->assertEquals(count($buildIdFields), 1, 'One form build id field on the page');
$buildId = (string) $buildIdFields[0]->getValue();
// Trigger validation error by again submitting an empty title.
$edit = ['title' => ''];
$this->drupalPostForm(NULL, $edit, 'Continue submit');
// Verify that the build-id does not change the second time.
$this->assertFieldByName('form_build_id', $buildId, 'Build id remains the same when form validation fails subsequently');
$this->assertSession()->hiddenFieldValueEquals('form_build_id', $buildId);
}
/**
......@@ -165,25 +171,28 @@ public function testImmutableForm() {
public function testImmutableFormLegacyProtection() {
$this->drupalGet('form_test/form-storage', ['query' => ['cache' => 1, 'immutable' => 1]]);
$build_id_fields = $this->xpath('//input[@name="form_build_id"]');
$this->assertEqual(count($build_id_fields), 1, 'One form build id field on the page');
$build_id = (string) $build_id_fields[0]['value'];
$this->assertEquals(count($build_id_fields), 1, 'One form build id field on the page');
$build_id = $build_id_fields[0]->getValue();
// Try to poison the form cache.
$original = $this->drupalGetAjax('form-test/form-storage-legacy/' . $build_id);
$this->assertEqual($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded');
$this->assertNotEqual($original['form']['#build_id'], $build_id, 'New build_id was generated');
$response = $this->drupalGet('form-test/form-storage-legacy/' . $build_id, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']], ['X-Requested-With: XMLHttpRequest']);
$original = json_decode($response, TRUE);
$this->assertEquals($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded');
$this->assertNotEquals($original['form']['#build_id'], $build_id, 'New build_id was generated');
// Assert that a watchdog message was logged by
// \Drupal::formBuilder()->setCache().
$status = (bool) Database::getConnection()->queryRange('SELECT 1 FROM {watchdog} WHERE message = :message', 0, 1, [':message' => 'Form build-id mismatch detected while attempting to store a form in the cache.']);
$this->assert($status, 'A watchdog message was logged by \Drupal::formBuilder()->setCache');
$this->assertTrue($status, 'A watchdog message was logged by \Drupal::formBuilder()->setCache');
// Ensure that the form state was not poisoned by the preceding call.
$original = $this->drupalGetAjax('form-test/form-storage-legacy/' . $build_id);
$this->assertEqual($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded');
$this->assertNotEqual($original['form']['#build_id'], $build_id, 'New build_id was generated');
$this->assert(empty($original['form']['#poisoned']), 'Original form structure was preserved');
$this->assert(empty($original['form_state']['poisoned']), 'Original form state was preserved');
$response = $this->drupalGet('form-test/form-storage-legacy/' . $build_id, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']], ['X-Requested-With: XMLHttpRequest']);
$original = json_decode($response, TRUE);
$this->assertEquals($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded');
$this->assertNotEquals($original['form']['#build_id'], $build_id, 'New build_id was generated');
$this->assertTrue(empty($original['form']['#poisoned']), 'Original form structure was preserved');
$this->assertTrue(empty($original['form_state']['poisoned']), 'Original form state was preserved');
}
}
<?php
namespace Drupal\Tests\system\FunctionalJavascript\Form;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
/**
* Tests the tableselect form element for expected behavior.
*
* @group Form
*/
class ElementsTableSelectTest extends WebDriverTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['form_test'];
/**
* Test the presence of ajax functionality for all options.
*/
public function testAjax() {
// Test checkboxes (#multiple == TRUE).
$this->drupalGet('form_test/tableselect/multiple-true');
$session = $this->getSession();
$page = $session->getPage();
for ($i = 1; $i <= 3; $i++) {
$row = 'row' . $i;
$page->hasUncheckedField($row);
$page->checkField($row);
$this->assertSession()->assertWaitOnAjaxRequest();
// Check current row and previous rows are checked.
for ($j = 1; $j <= $i; $j++) {
$other_row = 'row' . $j;
$page->hasCheckedField($other_row);
}
}
// Test radios (#multiple == FALSE).
$this->drupalGet('form_test/tableselect/multiple-false');
for ($i = 1; $i <= 3; $i++) {
$row = 'input[value="row' . $i . '"]';
$page->hasUncheckedField($row);
$this->click($row);
$this->assertSession()->assertWaitOnAjaxRequest();
$page->hasCheckedField($row);
// Check other rows are not checked
for ($j = 1; $j <= 3; $j++) {
if ($j == $i) {
continue;
}
$other_row = 'edit-tableselect-row' . $j;
$page->hasUncheckedField($other_row);
}
}
}
}
<?php
namespace Drupal\system\Tests\Form;
namespace Drupal\Tests\system\FunctionalJavascript\Form;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldConfig;
use Drupal\simpletest\WebTestBase;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
/**
* Tests functionality of \Drupal\Core\Form\FormBuilderInterface::rebuildForm().
......@@ -14,14 +14,12 @@
* @group Form
* @todo Add tests for other aspects of form rebuilding.
*/
class RebuildTest extends WebTestBase {
class RebuildTest extends WebDriverTestBase {
/**
* Modules to enable.
*
* @var array
* {@inheritdoc}
*/
public static $modules = ['node', 'form_test'];
protected static $modules = ['node', 'form_test'];
/**
* A user for testing.
......@@ -30,6 +28,9 @@ class RebuildTest extends WebTestBase {
*/
protected $webUser;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
......@@ -39,28 +40,6 @@ protected function setUp() {
$this->drupalLogin($this->webUser);
}
/**
* Tests preservation of values.
*/
public function testRebuildPreservesValues() {
$edit = [
'checkbox_1_default_off' => TRUE,
'checkbox_1_default_on' => FALSE,
'text_1' => 'foo',
];
$this->drupalPostForm('form-test/form-rebuild-preserve-values', $edit, 'Add more');
// Verify that initial elements retained their submitted values.
$this->assertFieldChecked('edit-checkbox-1-default-off', 'A submitted checked checkbox retained its checked state during a rebuild.');
$this->assertNoFieldChecked('edit-checkbox-1-default-on', 'A submitted unchecked checkbox retained its unchecked state during a rebuild.');
$this->assertFieldById('edit-text-1', 'foo', 'A textfield retained its submitted value during a rebuild.');
// Verify that newly added elements were initialized with their default values.
$this->assertFieldChecked('edit-checkbox-2-default-on', 'A newly added checkbox was initialized with a default checked state.');
$this->assertNoFieldChecked('edit-checkbox-2-default-off', 'A newly added checkbox was initialized with a default unchecked state.');
$this->assertFieldById('edit-text-2', 'DEFAULT 2', 'A newly added textfield was initialized with its default value.');
}
/**
* Tests that a form's action is retained after an Ajax submission.
*
......@@ -68,6 +47,7 @@ public function testRebuildPreservesValues() {
* followed by a non-Ajax submission, which triggers a validation error.
*/
public function testPreserveFormActionAfterAJAX() {
$page = $this->getSession()->getPage();
// Create a multi-valued field for 'page' nodes to use for Ajax testing.
$field_name = 'field_ajax_test';
FieldStorageConfig::create([
......@@ -81,8 +61,26 @@ public function testPreserveFormActionAfterAJAX() {
'entity_type' => 'node',
'bundle' => 'page',
])->save();
// Also create a file field to test server side validation error.
$field_file_name = 'field_file_test';
FieldStorageConfig::create([
'field_name' => $field_file_name,
'entity_type' => 'node',
'type' => 'file',
'cardinality' => 1,
])->save();
FieldConfig::create([
'field_name' => $field_file_name,
'entity_type' => 'node',
'bundle' => 'page',
'label' => 'Test file',
'required' => TRUE,
])->save();
entity_get_form_display('node', 'page', 'default')
->setComponent($field_name, ['type' => 'text_textfield'])
->setComponent($field_file_name, ['type' => 'file_generic'])
->save();
// Log in a user who can create 'page' nodes.
......@@ -93,27 +91,31 @@ public function testPreserveFormActionAfterAJAX() {