function FileFieldWidgetTest::testMultiValuedWidget
Same name in this branch
- 10 core/modules/file/tests/src/FunctionalJavascript/FileFieldWidgetTest.php \Drupal\Tests\file\FunctionalJavascript\FileFieldWidgetTest::testMultiValuedWidget()
Same name in other branches
- 9 core/modules/file/tests/src/FunctionalJavascript/FileFieldWidgetTest.php \Drupal\Tests\file\FunctionalJavascript\FileFieldWidgetTest::testMultiValuedWidget()
- 9 core/modules/file/tests/src/Functional/FileFieldWidgetTest.php \Drupal\Tests\file\Functional\FileFieldWidgetTest::testMultiValuedWidget()
- 8.9.x core/modules/file/tests/src/FunctionalJavascript/FileFieldWidgetTest.php \Drupal\Tests\file\FunctionalJavascript\FileFieldWidgetTest::testMultiValuedWidget()
- 8.9.x core/modules/file/tests/src/Functional/FileFieldWidgetTest.php \Drupal\Tests\file\Functional\FileFieldWidgetTest::testMultiValuedWidget()
- 11.x core/modules/file/tests/src/FunctionalJavascript/FileFieldWidgetTest.php \Drupal\Tests\file\FunctionalJavascript\FileFieldWidgetTest::testMultiValuedWidget()
- 11.x core/modules/file/tests/src/Functional/FileFieldWidgetTest.php \Drupal\Tests\file\Functional\FileFieldWidgetTest::testMultiValuedWidget()
Tests upload and remove buttons for multiple multi-valued File fields.
File
-
core/
modules/ file/ tests/ src/ Functional/ FileFieldWidgetTest.php, line 124
Class
- FileFieldWidgetTest
- Tests the file field widget with public and private files.
Namespace
Drupal\Tests\file\FunctionalCode
public function testMultiValuedWidget() : void {
$node_storage = $this->container
->get('entity_type.manager')
->getStorage('node');
$type_name = 'article';
// Use explicit names instead of random names for those fields, because of a
// bug in submitForm() with multiple file uploads in one form, where the
// order of uploads depends on the order in which the upload elements are
// added to the $form (which, in the current implementation of
// FileStorage::listAll(), comes down to the alphabetical order on field
// names).
$field_name = 'test_file_field_1';
$field_name2 = 'test_file_field_2';
$cardinality = 3;
$this->createFileField($field_name, 'node', $type_name, [
'cardinality' => $cardinality,
]);
$this->createFileField($field_name2, 'node', $type_name, [
'cardinality' => $cardinality,
]);
$test_file = $this->getTestFile('text');
// Visit the node creation form, and upload 3 files for each field. Since
// the field has cardinality of 3, ensure the "Upload" button is displayed
// until after the 3rd file, and after that, isn't displayed. Because
// the last button with a given name is triggered by default, upload to the
// second field first.
$this->drupalGet("node/add/{$type_name}");
foreach ([
$field_name2,
$field_name,
] as $each_field_name) {
for ($delta = 0; $delta < 3; $delta++) {
$edit = [
'files[' . $each_field_name . '_' . $delta . '][]' => \Drupal::service('file_system')->realpath($test_file->getFileUri()),
];
// If the Upload button doesn't exist, submitForm() will
// automatically fail with an assertion message.
$this->submitForm($edit, 'Upload');
}
}
$this->assertSession()
->buttonNotExists('Upload');
$num_expected_remove_buttons = 6;
foreach ([
$field_name,
$field_name2,
] as $current_field_name) {
// How many uploaded files for the current field are remaining.
$remaining = 3;
// Test clicking each "Remove" button. For extra robustness, test them out
// of sequential order. They are 0-indexed, and get renumbered after each
// iteration, so array(1, 1, 0) means:
// - First remove the 2nd file.
// - Then remove what is then the 2nd file (was originally the 3rd file).
// - Then remove the first file.
foreach ([
1,
1,
0,
] as $delta) {
// Ensure we have the expected number of Remove buttons, and that they
// are numbered sequentially.
$buttons = $this->xpath('//input[@type="submit" and @value="Remove"]');
$this->assertCount($num_expected_remove_buttons, $buttons, "There are {$num_expected_remove_buttons} \"Remove\" buttons displayed.");
foreach ($buttons as $i => $button) {
$key = $i >= $remaining ? $i - $remaining : $i;
$check_field_name = $field_name2;
if ($current_field_name == $field_name && $i < $remaining) {
$check_field_name = $field_name;
}
$this->assertSame($check_field_name . '_' . $key . '_remove_button', $button->getAttribute('name'));
}
// "Click" the remove button (emulating either a nojs or js submission).
$button_name = $current_field_name . '_' . $delta . '_remove_button';
$this->getSession()
->getPage()
->findButton($button_name)
->press();
$num_expected_remove_buttons--;
$remaining--;
// Ensure an "Upload" button for the current field is displayed with the
// correct name.
$upload_button_name = $current_field_name . '_' . $remaining . '_upload_button';
$button = $this->assertSession()
->buttonExists($upload_button_name);
$this->assertSame('Upload', $button->getValue());
// Ensure only at most one button per field is displayed.
$expected = $current_field_name == $field_name ? 1 : 2;
$this->assertSession()
->elementsCount('xpath', '//input[@type="submit" and @value="Upload"]', $expected);
}
}
// Ensure the page now has no Remove buttons.
$this->assertSession()
->buttonNotExists('Remove');
// Save the node and ensure it does not have any files.
$this->submitForm([
'title[0][value]' => $this->randomMachineName(),
], 'Save');
preg_match('/node\\/([0-9])/', $this->getUrl(), $matches);
$nid = $matches[1];
$node = $node_storage->loadUnchanged($nid);
$this->assertEmpty($node->{$field_name}->target_id, 'Node was successfully saved without any files.');
// Try to upload more files than allowed on revision.
$upload_files_node_revision = [
$test_file,
$test_file,
$test_file,
$test_file,
];
foreach ($upload_files_node_revision as $i => $file) {
$edit['files[test_file_field_1_0][' . $i . ']'] = \Drupal::service('file_system')->realpath($test_file->getFileUri());
}
// @todo Replace after https://www.drupal.org/project/drupal/issues/2917885
$this->drupalGet('node/' . $node->id() . '/edit');
$this->assertSession()
->fieldExists('files[test_file_field_1_0][]');
$submit_xpath = $this->assertSession()
->buttonExists('Save')
->getXpath();
$client = $this->getSession()
->getDriver()
->getClient();
$form = $client->getCrawler()
->filterXPath($submit_xpath)
->form();
$client->request($form->getMethod(), $form->getUri(), $form->getPhpValues(), $edit);
$node = $node_storage->loadUnchanged($nid);
$this->assertCount($cardinality, $node->{$field_name}, 'More files than allowed could not be saved to node.');
$upload_files_node_creation = [
$test_file,
$test_file,
];
// Try to upload multiple files, but fewer than the maximum.
$nid = $this->uploadNodeFiles($upload_files_node_creation, $field_name, $type_name, TRUE, []);
$node = $node_storage->loadUnchanged($nid);
$this->assertSameSize($upload_files_node_creation, $node->{$field_name}, 'Node was successfully saved with multiple files.');
// Try to upload exactly the allowed number of files on revision.
$this->uploadNodeFile($test_file, $field_name, $node->id(), 1);
$node = $node_storage->loadUnchanged($nid);
$this->assertCount($cardinality, $node->{$field_name}, 'Node was successfully revised to maximum number of files.');
// Try to upload exactly the allowed number of files, new node.
$upload_files = [
$test_file,
$test_file,
$test_file,
];
$nid = $this->uploadNodeFiles($upload_files, $field_name, $type_name, TRUE, []);
$node = $node_storage->loadUnchanged($nid);
$this->assertCount($cardinality, $node->{$field_name}, 'Node was successfully saved with maximum number of files.');
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.