public function FileFieldWidgetTest::testMultiValuedWidget in Drupal 8
Same name in this branch
- 8 core/modules/file/tests/src/Functional/FileFieldWidgetTest.php \Drupal\Tests\file\Functional\FileFieldWidgetTest::testMultiValuedWidget()
- 8 core/modules/file/tests/src/FunctionalJavascript/FileFieldWidgetTest.php \Drupal\Tests\file\FunctionalJavascript\FileFieldWidgetTest::testMultiValuedWidget()
Same name and namespace in other branches
- 9 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 121
Class
- FileFieldWidgetTest
- Tests the file field widget with public and private files.
Namespace
Drupal\Tests\file\FunctionalCode
public function testMultiValuedWidget() {
$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 drupalPostForm() 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
// SimpleTest triggers the last button with a given name, so 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, drupalPostForm() will
// automatically fail with an assertion message.
$this
->drupalPostForm(NULL, $edit, t('Upload'));
}
}
$this
->assertNoFieldByXpath('//input[@type="submit"]', t('Upload'), 'After uploading 3 files for each field, the "Upload" button is no longer displayed.');
$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, new FormattableMarkup('There are %n "Remove" buttons displayed.', [
'%n' => $num_expected_remove_buttons,
]));
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
->assertIdentical($button
->getAttribute('name'), $check_field_name . '_' . $key . '_remove_button');
}
// "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';
$buttons = $this
->xpath('//input[@type="submit" and @value="Upload" and @name=:name]', [
':name' => $upload_button_name,
]);
$this
->assertCount(1, $buttons, 'The upload button is displayed with the correct name.');
// Ensure only at most one button per field is displayed.
$buttons = $this
->xpath('//input[@type="submit" and @value="Upload"]');
$expected = $current_field_name == $field_name ? 1 : 2;
$this
->assertCount($expected, $buttons, 'After removing a file, only one "Upload" button for each possible field is displayed.');
}
}
// Ensure the page now has no Remove buttons.
$this
->assertNoFieldByXPath('//input[@type="submit"]', t('Remove'), 'After removing all files, there is no "Remove" button displayed.');
// Save the node and ensure it does not have any files.
$this
->drupalPostForm(NULL, [
'title[0][value]' => $this
->randomMachineName(),
], t('Save'));
preg_match('/node\\/([0-9])/', $this
->getUrl(), $matches);
$nid = $matches[1];
$node = $node_storage
->loadUnchanged($nid);
$this
->assertTrue(empty($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
->assertEqual(count($node->{$field_name}), $cardinality, '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
->assertEqual(count($node->{$field_name}), count($upload_files_node_creation), '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, [], TRUE);
$node = $node_storage
->loadUnchanged($nid);
$this
->assertEqual(count($node->{$field_name}), $cardinality, '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
->assertEqual(count($node->{$field_name}), $cardinality, 'Node was successfully saved with maximum number of files.');
}