diff --git a/core/modules/image/src/Tests/ImageAdminStylesTest.php b/core/modules/image/src/Tests/ImageAdminStylesTest.php index 1f6f411054f6a28c9cf6393474ccfd17d8e64862..e4f775be4f6a08c5c0a3c60f676131adbe77f98a 100644 --- a/core/modules/image/src/Tests/ImageAdminStylesTest.php +++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php @@ -2,12 +2,7 @@ namespace Drupal\image\Tests; -use Drupal\Component\Utility\SafeMarkup; -use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\image\Entity\ImageStyle; -use Drupal\image\ImageStyleInterface; -use Drupal\node\Entity\Node; -use Drupal\file\Entity\File; /** * Tests creation, deletion, and editing of image styles and effects. @@ -16,280 +11,6 @@ */ class ImageAdminStylesTest extends ImageFieldTestBase { - /** - * Given an image style, generate an image. - */ - public function createSampleImage(ImageStyleInterface $style) { - static $file_path; - - // First, we need to make sure we have an image in our testing - // file directory. Copy over an image on the first run. - if (!isset($file_path)) { - $files = $this->drupalGetTestFiles('image'); - $file = reset($files); - $file_path = file_unmanaged_copy($file->uri); - } - - return $style->buildUrl($file_path) ? $file_path : FALSE; - } - - /** - * Count the number of images currently create for a style. - */ - public function getImageCount(ImageStyleInterface $style) { - return count(file_scan_directory('public://styles/' . $style->id(), '/.*/')); - } - - /** - * Test creating an image style with a numeric name and ensuring it can be - * applied to an image. - */ - public function testNumericStyleName() { - $style_name = rand(); - $style_label = $this->randomString(); - $edit = [ - 'name' => $style_name, - 'label' => $style_label, - ]; - $this->drupalPostForm('admin/config/media/image-styles/add', $edit, t('Create new style')); - $this->assertRaw(t('Style %name was created.', ['%name' => $style_label])); - $options = image_style_options(); - $this->assertTrue(array_key_exists($style_name, $options), format_string('Array key %key exists.', ['%key' => $style_name])); - } - - /** - * General test to add a style, add/remove/edit effects to it, then delete it. - */ - public function testStyle() { - $admin_path = 'admin/config/media/image-styles'; - - // Setup a style to be created and effects to add to it. - $style_name = strtolower($this->randomMachineName(10)); - $style_label = $this->randomString(); - $style_path = $admin_path . '/manage/' . $style_name; - $effect_edits = [ - 'image_resize' => [ - 'width' => 100, - 'height' => 101, - ], - 'image_scale' => [ - 'width' => 110, - 'height' => 111, - 'upscale' => 1, - ], - 'image_scale_and_crop' => [ - 'width' => 120, - 'height' => 121, - ], - 'image_crop' => [ - 'width' => 130, - 'height' => 131, - 'anchor' => 'left-top', - ], - 'image_desaturate' => [ - // No options for desaturate. - ], - 'image_rotate' => [ - 'degrees' => 5, - 'random' => 1, - 'bgcolor' => '#FFFF00', - ], - ]; - - // Add style form. - - $edit = [ - 'name' => $style_name, - 'label' => $style_label, - ]; - $this->drupalPostForm($admin_path . '/add', $edit, t('Create new style')); - $this->assertRaw(t('Style %name was created.', ['%name' => $style_label])); - - // Ensure that the expected entity operations are there. - $this->drupalGet($admin_path); - $this->assertLinkByHref($style_path); - $this->assertLinkByHref($style_path . '/flush'); - $this->assertLinkByHref($style_path . '/delete'); - - // Add effect form. - - // Add each sample effect to the style. - foreach ($effect_edits as $effect => $edit) { - $edit_data = []; - foreach ($edit as $field => $value) { - $edit_data['data[' . $field . ']'] = $value; - } - // Add the effect. - $this->drupalPostForm($style_path, ['new' => $effect], t('Add')); - if (!empty($edit)) { - $this->drupalPostForm(NULL, $edit_data, t('Add effect')); - } - } - - // Load the saved image style. - $style = ImageStyle::load($style_name); - - // Ensure that third party settings were added to the config entity. - // These are added by a hook_image_style_presave() implemented in - // image_module_test module. - $this->assertEqual('bar', $style->getThirdPartySetting('image_module_test', 'foo'), 'Third party settings were added to the image style.'); - - // Ensure that the image style URI matches our expected path. - $style_uri_path = $style->url(); - $this->assertTrue(strpos($style_uri_path, $style_path) !== FALSE, 'The image style URI is correct.'); - - // Confirm that all effects on the image style have settings that match - // what was saved. - $uuids = []; - foreach ($style->getEffects() as $uuid => $effect) { - // Store the uuid for later use. - $uuids[$effect->getPluginId()] = $uuid; - $effect_configuration = $effect->getConfiguration(); - foreach ($effect_edits[$effect->getPluginId()] as $field => $value) { - $this->assertEqual($value, $effect_configuration['data'][$field], SafeMarkup::format('The %field field in the %effect effect has the correct value of %value.', ['%field' => $field, '%effect' => $effect->getPluginId(), '%value' => $value])); - } - } - - // Assert that every effect was saved. - foreach (array_keys($effect_edits) as $effect_name) { - $this->assertTrue(isset($uuids[$effect_name]), format_string( - 'A %effect_name effect was saved with ID %uuid', - [ - '%effect_name' => $effect_name, - '%uuid' => $uuids[$effect_name], - ])); - } - - // Image style overview form (ordering and renaming). - - // Confirm the order of effects is maintained according to the order we - // added the fields. - $effect_edits_order = array_keys($effect_edits); - $order_correct = TRUE; - $index = 0; - foreach ($style->getEffects() as $effect) { - if ($effect_edits_order[$index] != $effect->getPluginId()) { - $order_correct = FALSE; - } - $index++; - } - $this->assertTrue($order_correct, 'The order of the effects is correctly set by default.'); - - // Test the style overview form. - // Change the name of the style and adjust the weights of effects. - $style_name = strtolower($this->randomMachineName(10)); - $style_label = $this->randomMachineName(); - $weight = count($effect_edits); - $edit = [ - 'name' => $style_name, - 'label' => $style_label, - ]; - foreach ($style->getEffects() as $uuid => $effect) { - $edit['effects[' . $uuid . '][weight]'] = $weight; - $weight--; - } - - // Create an image to make sure it gets flushed after saving. - $image_path = $this->createSampleImage($style); - $this->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); - - $this->drupalPostForm($style_path, $edit, t('Update style')); - - // Note that after changing the style name, the style path is changed. - $style_path = 'admin/config/media/image-styles/manage/' . $style_name; - - // Check that the URL was updated. - $this->drupalGet($style_path); - $this->assertTitle(t('Edit style @name | Drupal', ['@name' => $style_label])); - $this->assertResponse(200, format_string('Image style %original renamed to %new', ['%original' => $style->id(), '%new' => $style_name])); - - // Check that the available image effects are properly sorted. - $option = $this->xpath('//select[@id=:id]//option', [':id' => 'edit-new--2']); - $this->assertTrue($option[1] == 'Ajax test', '"Ajax test" is the first selectable effect.'); - - // Check that the image was flushed after updating the style. - // This is especially important when renaming the style. Make sure that - // the old image directory has been deleted. - $this->assertEqual($this->getImageCount($style), 0, format_string('Image style %style was flushed after renaming the style and updating the order of effects.', ['%style' => $style->label()])); - - // Load the style by the new name with the new weights. - $style = ImageStyle::load($style_name); - - // Confirm the new style order was saved. - $effect_edits_order = array_reverse($effect_edits_order); - $order_correct = TRUE; - $index = 0; - foreach ($style->getEffects() as $effect) { - if ($effect_edits_order[$index] != $effect->getPluginId()) { - $order_correct = FALSE; - } - $index++; - } - $this->assertTrue($order_correct, 'The order of the effects is correctly set by default.'); - - // Image effect deletion form. - - // Create an image to make sure it gets flushed after deleting an effect. - $image_path = $this->createSampleImage($style); - $this->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); - - // Delete the 'image_crop' effect from the style. - $this->drupalPostForm($style_path . '/effects/' . $uuids['image_crop'] . '/delete', [], t('Delete')); - // Confirm that the form submission was successful. - $this->assertResponse(200); - $image_crop_effect = $style->getEffect($uuids['image_crop']); - $this->assertRaw(t('The image effect %name has been deleted.', ['%name' => $image_crop_effect->label()])); - // Confirm that there is no longer a link to the effect. - $this->assertNoLinkByHref($style_path . '/effects/' . $uuids['image_crop'] . '/delete'); - // Refresh the image style information and verify that the effect was - // actually deleted. - $entity_type_manager = $this->container->get('entity_type.manager'); - $style = $entity_type_manager->getStorage('image_style')->loadUnchanged($style->id()); - $this->assertFalse($style->getEffects()->has($uuids['image_crop']), format_string( - 'Effect with ID %uuid no longer found on image style %style', - [ - '%uuid' => $uuids['image_crop'], - '%style' => $style->label(), - ])); - - // Additional test on Rotate effect, for transparent background. - $edit = [ - 'data[degrees]' => 5, - 'data[random]' => 0, - 'data[bgcolor]' => '', - ]; - $this->drupalPostForm($style_path, ['new' => 'image_rotate'], t('Add')); - $this->drupalPostForm(NULL, $edit, t('Add effect')); - $entity_type_manager = $this->container->get('entity_type.manager'); - $style = $entity_type_manager->getStorage('image_style')->loadUnchanged($style_name); - $this->assertEqual(count($style->getEffects()), 6, 'Rotate effect with transparent background was added.'); - - // Style deletion form. - - // Delete the style. - $this->drupalPostForm($style_path . '/delete', [], t('Delete')); - - // Confirm the style directory has been removed. - $directory = file_default_scheme() . '://styles/' . $style_name; - $this->assertFalse(is_dir($directory), format_string('Image style %style directory removed on style deletion.', ['%style' => $style->label()])); - - $this->assertFalse(ImageStyle::load($style_name), format_string('Image style %style successfully deleted.', ['%style' => $style->label()])); - - // Test empty text when there are no image styles. - - // Delete all image styles. - foreach (ImageStyle::loadMultiple() as $image_style) { - $image_style->delete(); - } - - // Confirm that the empty text is correct on the image styles page. - $this->drupalGet($admin_path); - $this->assertRaw(t('There are currently no styles. <a href=":url">Add a new one</a>.', [ - ':url' => \Drupal::url('image.style_add'), - ])); - - } - /** * Tests editing Ajax-enabled image effect forms. */ @@ -328,214 +49,6 @@ public function testAjaxEnabledEffectForm() { $this->drupalPostAjaxForm(NULL, $effect_edit, ['op' => t('Ajax refresh')]); $this->drupalPostForm(NULL, $effect_edit, t('Update effect')); } - - } - - /** - * Test deleting a style and choosing a replacement style. - */ - public function testStyleReplacement() { - // Create a new style. - $style_name = strtolower($this->randomMachineName(10)); - $style_label = $this->randomString(); - $style = ImageStyle::create(['name' => $style_name, 'label' => $style_label]); - $style->save(); - $style_path = 'admin/config/media/image-styles/manage/'; - - // Create an image field that uses the new style. - $field_name = strtolower($this->randomMachineName(10)); - $this->createImageField($field_name, 'article'); - entity_get_display('node', 'article', 'default') - ->setComponent($field_name, [ - 'type' => 'image', - 'settings' => ['image_style' => $style_name], - ]) - ->save(); - - // Create a new node with an image attached. - $test_image = current($this->drupalGetTestFiles('image')); - $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName()); - $node = Node::load($nid); - - // Get node field original image URI. - $fid = $node->get($field_name)->target_id; - $original_uri = File::load($fid)->getFileUri(); - - // Test that image is displayed using newly created style. - $this->drupalGet('node/' . $nid); - $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', ['@style' => $style_name])); - - // Rename the style and make sure the image field is updated. - $new_style_name = strtolower($this->randomMachineName(10)); - $new_style_label = $this->randomString(); - $edit = [ - 'name' => $new_style_name, - 'label' => $new_style_label, - ]; - $this->drupalPostForm($style_path . $style_name, $edit, t('Update style')); - $this->assertText(t('Changes to the style have been saved.'), format_string('Style %name was renamed to %new_name.', ['%name' => $style_name, '%new_name' => $new_style_name])); - $this->drupalGet('node/' . $nid); - - // Reload the image style using the new name. - $style = ImageStyle::load($new_style_name); - $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), 'Image displayed using style replacement style.'); - - // Delete the style and choose a replacement style. - $edit = [ - 'replacement' => 'thumbnail', - ]; - $this->drupalPostForm($style_path . $new_style_name . '/delete', $edit, t('Delete')); - $message = t('The image style %name has been deleted.', ['%name' => $new_style_label]); - $this->assertRaw($message); - - $replacement_style = ImageStyle::load('thumbnail'); - $this->drupalGet('node/' . $nid); - $this->assertRaw(file_url_transform_relative($replacement_style->buildUrl($original_uri)), 'Image displayed using style replacement style.'); - } - - /** - * Verifies that editing an image effect does not cause it to be duplicated. - */ - public function testEditEffect() { - // Add a scale effect. - $style_name = 'test_style_effect_edit'; - $this->drupalGet('admin/config/media/image-styles/add'); - $this->drupalPostForm(NULL, ['label' => 'Test style effect edit', 'name' => $style_name], t('Create new style')); - $this->drupalPostForm(NULL, ['new' => 'image_scale_and_crop'], t('Add')); - $this->drupalPostForm(NULL, ['data[width]' => '300', 'data[height]' => '200'], t('Add effect')); - $this->assertText(t('Scale and crop 300×200')); - - // There should normally be only one edit link on this page initially. - $this->clickLink(t('Edit')); - $this->drupalPostForm(NULL, ['data[width]' => '360', 'data[height]' => '240'], t('Update effect')); - $this->assertText(t('Scale and crop 360×240')); - - // Check that the previous effect is replaced. - $this->assertNoText(t('Scale and crop 300×200')); - - // Add another scale effect. - $this->drupalGet('admin/config/media/image-styles/add'); - $this->drupalPostForm(NULL, ['label' => 'Test style scale edit scale', 'name' => 'test_style_scale_edit_scale'], t('Create new style')); - $this->drupalPostForm(NULL, ['new' => 'image_scale'], t('Add')); - $this->drupalPostForm(NULL, ['data[width]' => '12', 'data[height]' => '19'], t('Add effect')); - - // Edit the scale effect that was just added. - $this->clickLink(t('Edit')); - $this->drupalPostForm(NULL, ['data[width]' => '24', 'data[height]' => '19'], t('Update effect')); - - // Add another scale effect and make sure both exist. Click through from - // the overview to make sure that it is possible to add new effect then. - $this->drupalGet('admin/config/media/image-styles'); - $rows = $this->xpath('//table/tbody/tr'); - $i = 0; - foreach ($rows as $row) { - if (((string) $row->td[0]) === 'Test style scale edit scale') { - $this->clickLink('Edit', $i); - break; - } - $i++; - } - $this->drupalPostForm(NULL, ['new' => 'image_scale'], t('Add')); - $this->drupalPostForm(NULL, ['data[width]' => '12', 'data[height]' => '19'], t('Add effect')); - $this->assertText(t('Scale 24×19')); - $this->assertText(t('Scale 12×19')); - - // Try to edit a nonexistent effect. - $uuid = $this->container->get('uuid'); - $this->drupalGet('admin/config/media/image-styles/manage/' . $style_name . '/effects/' . $uuid->generate()); - $this->assertResponse(404); - } - - /** - * Test flush user interface. - */ - public function testFlushUserInterface() { - $admin_path = 'admin/config/media/image-styles'; - - // Create a new style. - $style_name = strtolower($this->randomMachineName(10)); - $style = ImageStyle::create(['name' => $style_name, 'label' => $this->randomString()]); - $style->save(); - - // Create an image to make sure it gets flushed. - $files = $this->drupalGetTestFiles('image'); - $image_uri = $files[0]->uri; - $derivative_uri = $style->buildUri($image_uri); - $this->assertTrue($style->createDerivative($image_uri, $derivative_uri)); - $this->assertEqual($this->getImageCount($style), 1); - - // Go to image styles list page and check if the flush operation link - // exists. - $this->drupalGet($admin_path); - $flush_path = $admin_path . '/manage/' . $style_name . '/flush'; - $this->assertLinkByHref($flush_path); - - // Flush the image style derivatives using the user interface. - $this->drupalPostForm($flush_path, [], t('Flush')); - - // The derivative image file should have been deleted. - $this->assertEqual($this->getImageCount($style), 0); - } - - /** - * Tests image style configuration import that does a delete. - */ - public function testConfigImport() { - // Create a new style. - $style_name = strtolower($this->randomMachineName(10)); - $style_label = $this->randomString(); - $style = ImageStyle::create(['name' => $style_name, 'label' => $style_label]); - $style->save(); - - // Create an image field that uses the new style. - $field_name = strtolower($this->randomMachineName(10)); - $this->createImageField($field_name, 'article'); - entity_get_display('node', 'article', 'default') - ->setComponent($field_name, [ - 'type' => 'image', - 'settings' => ['image_style' => $style_name], - ]) - ->save(); - - // Create a new node with an image attached. - $test_image = current($this->drupalGetTestFiles('image')); - $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName()); - $node = Node::load($nid); - - // Get node field original image URI. - $fid = $node->get($field_name)->target_id; - $original_uri = File::load($fid)->getFileUri(); - - // Test that image is displayed using newly created style. - $this->drupalGet('node/' . $nid); - $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', ['@style' => $style_name])); - - // Copy config to sync, and delete the image style. - $sync = $this->container->get('config.storage.sync'); - $active = $this->container->get('config.storage'); - // Remove the image field from the display, to avoid a dependency error - // during import. - EntityViewDisplay::load('node.article.default') - ->removeComponent($field_name) - ->save(); - $this->copyConfig($active, $sync); - $sync->delete('image.style.' . $style_name); - $this->configImporter()->import(); - - $this->assertFalse(ImageStyle::load($style_name), 'Style deleted after config import.'); - $this->assertEqual($this->getImageCount($style), 0, 'Image style was flushed after being deleted by config import.'); - } - - /** - * Tests access for the image style listing. - */ - public function testImageStyleAccess() { - $style = ImageStyle::create(['name' => 'style_foo', 'label' => $this->randomString()]); - $style->save(); - - $this->drupalGet('admin/config/media/image-styles'); - $this->clickLink(t('Edit')); - $this->assertRaw(t('Select a new effect')); } } diff --git a/core/modules/image/src/Tests/ImageFieldTestBase.php b/core/modules/image/src/Tests/ImageFieldTestBase.php index 0623b6e92f6c0db039bf335cf99c0807cacc6088..2e21739abd4092938646911f6ca69959d353f03d 100644 --- a/core/modules/image/src/Tests/ImageFieldTestBase.php +++ b/core/modules/image/src/Tests/ImageFieldTestBase.php @@ -2,6 +2,8 @@ namespace Drupal\image\Tests; +@trigger_error('The ' . __NAMESPACE__ . '\ImageFieldTestBase class is deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.0. Use \Drupal\Tests\image\Functional\ImageFieldTestBase instead. See https://www.drupal.org/node/2863626.', E_USER_DEPRECATED); + use Drupal\Tests\image\Kernel\ImageFieldCreationTrait; use Drupal\simpletest\WebTestBase; diff --git a/core/modules/image/src/Tests/ImageFieldValidateTest.php b/core/modules/image/src/Tests/ImageFieldValidateTest.php index 87c042bf98772ef8b47b4cea1ff2f4999899acae..39750d809a86f8911c1ba112a71e16674f68b187 100644 --- a/core/modules/image/src/Tests/ImageFieldValidateTest.php +++ b/core/modules/image/src/Tests/ImageFieldValidateTest.php @@ -12,213 +12,6 @@ */ class ImageFieldValidateTest extends ImageFieldTestBase { - /** - * Test image validity. - */ - public function testValid() { - $file_system = $this->container->get('file_system'); - $image_files = $this->drupalGetTestFiles('image'); - - $field_name = strtolower($this->randomMachineName()); - $this->createImageField($field_name, 'article', [], ['file_directory' => 'test-upload']); - $expected_path = 'public://test-upload'; - - // Create alt text for the image. - $alt = $this->randomMachineName(); - - // Create a node with a valid image. - $node = $this->uploadNodeImage($image_files[0], $field_name, 'article', $alt); - $this->assertTrue(file_exists($expected_path . '/' . $image_files[0]->filename)); - - // Remove the image. - $this->drupalPostForm('node/' . $node . '/edit', [], t('Remove')); - $this->drupalPostForm(NULL, [], t('Save')); - - // Get invalid image test files from simpletest. - $files = file_scan_directory(drupal_get_path('module', 'simpletest') . '/files', '/invalid-img-.*/'); - $invalid_image_files = []; - foreach ($files as $file) { - $invalid_image_files[$file->filename] = $file; - } - - // Try uploading a zero-byte image. - $zero_size_image = $invalid_image_files['invalid-img-zero-size.png']; - $edit = [ - 'files[' . $field_name . '_0]' => $file_system->realpath($zero_size_image->uri), - ]; - $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); - $this->assertFalse(file_exists($expected_path . '/' . $zero_size_image->filename)); - - // Try uploading an invalid image. - $invalid_image = $invalid_image_files['invalid-img-test.png']; - $edit = [ - 'files[' . $field_name . '_0]' => $file_system->realpath($invalid_image->uri), - ]; - $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); - $this->assertFalse(file_exists($expected_path . '/' . $invalid_image->filename)); - - // Upload a valid image again. - $valid_image = $image_files[0]; - $edit = [ - 'files[' . $field_name . '_0]' => $file_system->realpath($valid_image->uri), - ]; - $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); - $this->assertTrue(file_exists($expected_path . '/' . $valid_image->filename)); - } - - /** - * Test min/max resolution settings. - */ - public function testResolution() { - $field_names = [ - 0 => strtolower($this->randomMachineName()), - 1 => strtolower($this->randomMachineName()), - 2 => strtolower($this->randomMachineName()), - ]; - $min_resolution = [ - 'width' => 50, - 'height' => 50 - ]; - $max_resolution = [ - 'width' => 100, - 'height' => 100 - ]; - $no_height_min_resolution = [ - 'width' => 50, - 'height' => NULL - ]; - $no_height_max_resolution = [ - 'width' => 100, - 'height' => NULL - ]; - $no_width_min_resolution = [ - 'width' => NULL, - 'height' => 50 - ]; - $no_width_max_resolution = [ - 'width' => NULL, - 'height' => 100 - ]; - $field_settings = [ - 0 => $this->getFieldSettings($min_resolution, $max_resolution), - 1 => $this->getFieldSettings($no_height_min_resolution, $no_height_max_resolution), - 2 => $this->getFieldSettings($no_width_min_resolution, $no_width_max_resolution), - ]; - $this->createImageField($field_names[0], 'article', [], $field_settings[0]); - $this->createImageField($field_names[1], 'article', [], $field_settings[1]); - $this->createImageField($field_names[2], 'article', [], $field_settings[2]); - - // We want a test image that is too small, and a test image that is too - // big, so cycle through test image files until we have what we need. - $image_that_is_too_big = FALSE; - $image_that_is_too_small = FALSE; - $image_factory = $this->container->get('image.factory'); - foreach ($this->drupalGetTestFiles('image') as $image) { - $image_file = $image_factory->get($image->uri); - if ($image_file->getWidth() > $max_resolution['width']) { - $image_that_is_too_big = $image; - } - if ($image_file->getWidth() < $min_resolution['width']) { - $image_that_is_too_small = $image; - $image_that_is_too_small_file = $image_file; - } - if ($image_that_is_too_small && $image_that_is_too_big) { - break; - } - } - $this->uploadNodeImage($image_that_is_too_small, $field_names[0], 'article'); - $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); - $this->assertRaw(t('The image is too small. The minimum dimensions are %dimensions pixels and the image size is %widthx%height pixels.', [ - '%dimensions' => '50x50', - '%width' => $image_that_is_too_small_file->getWidth(), - '%height' => $image_that_is_too_small_file->getHeight(), - ])); - $this->uploadNodeImage($image_that_is_too_big, $field_names[0], 'article'); - $this->assertText(t('The image was resized to fit within the maximum allowed dimensions of 100x100 pixels.')); - $this->uploadNodeImage($image_that_is_too_small, $field_names[1], 'article'); - $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); - $this->uploadNodeImage($image_that_is_too_big, $field_names[1], 'article'); - $this->assertText(t('The image was resized to fit within the maximum allowed width of 100 pixels.')); - $this->uploadNodeImage($image_that_is_too_small, $field_names[2], 'article'); - $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); - $this->uploadNodeImage($image_that_is_too_big, $field_names[2], 'article'); - $this->assertText(t('The image was resized to fit within the maximum allowed height of 100 pixels.')); - } - - /** - * Test that required alt/title fields gets validated right. - */ - public function testRequiredAttributes() { - $field_name = strtolower($this->randomMachineName()); - $field_settings = [ - 'alt_field' => 1, - 'alt_field_required' => 1, - 'title_field' => 1, - 'title_field_required' => 1, - 'required' => 1, - ]; - $instance = $this->createImageField($field_name, 'article', [], $field_settings); - $images = $this->drupalGetTestFiles('image'); - // Let's just use the first image. - $image = $images[0]; - $this->uploadNodeImage($image, $field_name, 'article'); - - // Look for form-required for the alt text. - $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-alt" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-alt"]'); - - $this->assertTrue(isset($elements[0]), 'Required marker is shown for the required alt text.'); - - $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-title" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-title"]'); - - $this->assertTrue(isset($elements[0]), 'Required marker is shown for the required title text.'); - - $this->assertText(t('Alternative text field is required.')); - $this->assertText(t('Title field is required.')); - - $instance->setSetting('alt_field_required', 0); - $instance->setSetting('title_field_required', 0); - $instance->save(); - - $edit = [ - 'title[0][value]' => $this->randomMachineName(), - ]; - $this->drupalPostForm('node/add/article', $edit, t('Save')); - - $this->assertNoText(t('Alternative text field is required.')); - $this->assertNoText(t('Title field is required.')); - - $instance->setSetting('required', 0); - $instance->setSetting('alt_field_required', 1); - $instance->setSetting('title_field_required', 1); - $instance->save(); - - $edit = [ - 'title[0][value]' => $this->randomMachineName(), - ]; - $this->drupalPostForm('node/add/article', $edit, t('Save')); - - $this->assertNoText(t('Alternative text field is required.')); - $this->assertNoText(t('Title field is required.')); - } - - /** - * Returns field settings. - * - * @param int[] $min_resolution - * The minimum width and height resolution setting. - * @param int[] $max_resolution - * The maximum width and height resolution setting. - * - * @return array - */ - protected function getFieldSettings($min_resolution, $max_resolution) { - return [ - 'max_resolution' => $max_resolution['width'] . 'x' . $max_resolution['height'], - 'min_resolution' => $min_resolution['width'] . 'x' . $min_resolution['height'], - 'alt_field' => 0, - ]; - } - /** * Test the validation message is displayed only once for ajax uploads. */ diff --git a/core/modules/image/src/Tests/FileMoveTest.php b/core/modules/image/tests/src/Functional/FileMoveTest.php similarity index 83% rename from core/modules/image/src/Tests/FileMoveTest.php rename to core/modules/image/tests/src/Functional/FileMoveTest.php index d9ce27f75d3049b1a61d2dcaf6706311eac9f9ba..3cf3be71b8046a2e4444efcdf7cd8fce7a732263 100644 --- a/core/modules/image/src/Tests/FileMoveTest.php +++ b/core/modules/image/tests/src/Functional/FileMoveTest.php @@ -1,17 +1,23 @@ <?php -namespace Drupal\image\Tests; +namespace Drupal\Tests\image\Functional; use Drupal\file\Entity\File; -use Drupal\simpletest\WebTestBase; use Drupal\image\Entity\ImageStyle; +use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\TestFileCreationTrait; /** * Tests the file move function for images and image styles. * * @group image */ -class FileMoveTest extends WebTestBase { +class FileMoveTest extends BrowserTestBase { + + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + compareFiles as drupalCompareFiles; + } /** * Modules to enable. diff --git a/core/modules/image/tests/src/Functional/ImageAdminStylesTest.php b/core/modules/image/tests/src/Functional/ImageAdminStylesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c37d04bc4a94cfd35d2e49d8f12b33da4e04edf6 --- /dev/null +++ b/core/modules/image/tests/src/Functional/ImageAdminStylesTest.php @@ -0,0 +1,506 @@ +<?php + +namespace Drupal\Tests\image\Functional; + +use Drupal\Component\Utility\SafeMarkup; +use Drupal\Core\Entity\Entity\EntityViewDisplay; +use Drupal\image\Entity\ImageStyle; +use Drupal\image\ImageStyleInterface; +use Drupal\node\Entity\Node; +use Drupal\file\Entity\File; +use Drupal\Tests\TestFileCreationTrait; + +/** + * Tests creation, deletion, and editing of image styles and effects. + * + * @group image + */ +class ImageAdminStylesTest extends ImageFieldTestBase { + + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + compareFiles as drupalCompareFiles; + } + + /** + * Given an image style, generate an image. + */ + public function createSampleImage(ImageStyleInterface $style) { + static $file_path; + + // First, we need to make sure we have an image in our testing + // file directory. Copy over an image on the first run. + if (!isset($file_path)) { + $files = $this->drupalGetTestFiles('image'); + $file = reset($files); + $file_path = file_unmanaged_copy($file->uri); + } + + return $style->buildUrl($file_path) ? $file_path : FALSE; + } + + /** + * Count the number of images currently create for a style. + */ + public function getImageCount(ImageStyleInterface $style) { + return count(file_scan_directory('public://styles/' . $style->id(), '/.*/')); + } + + /** + * Test creating an image style with a numeric name and ensuring it can be + * applied to an image. + */ + public function testNumericStyleName() { + $style_name = rand(); + $style_label = $this->randomString(); + $edit = [ + 'name' => $style_name, + 'label' => $style_label, + ]; + $this->drupalPostForm('admin/config/media/image-styles/add', $edit, t('Create new style')); + $this->assertRaw(t('Style %name was created.', ['%name' => $style_label])); + $options = image_style_options(); + $this->assertTrue(array_key_exists($style_name, $options), format_string('Array key %key exists.', ['%key' => $style_name])); + } + + /** + * General test to add a style, add/remove/edit effects to it, then delete it. + */ + public function testStyle() { + $admin_path = 'admin/config/media/image-styles'; + + // Setup a style to be created and effects to add to it. + $style_name = strtolower($this->randomMachineName(10)); + $style_label = $this->randomString(); + $style_path = $admin_path . '/manage/' . $style_name; + $effect_edits = [ + 'image_resize' => [ + 'width' => 100, + 'height' => 101, + ], + 'image_scale' => [ + 'width' => 110, + 'height' => 111, + 'upscale' => 1, + ], + 'image_scale_and_crop' => [ + 'width' => 120, + 'height' => 121, + ], + 'image_crop' => [ + 'width' => 130, + 'height' => 131, + 'anchor' => 'left-top', + ], + 'image_desaturate' => [ + // No options for desaturate. + ], + 'image_rotate' => [ + 'degrees' => 5, + 'random' => 1, + 'bgcolor' => '#FFFF00', + ], + ]; + + // Add style form. + + $edit = [ + 'name' => $style_name, + 'label' => $style_label, + ]; + $this->drupalPostForm($admin_path . '/add', $edit, t('Create new style')); + $this->assertRaw(t('Style %name was created.', ['%name' => $style_label])); + + // Ensure that the expected entity operations are there. + $this->drupalGet($admin_path); + $this->assertLinkByHref($style_path); + $this->assertLinkByHref($style_path . '/flush'); + $this->assertLinkByHref($style_path . '/delete'); + + // Add effect form. + + // Add each sample effect to the style. + foreach ($effect_edits as $effect => $edit) { + $edit_data = []; + foreach ($edit as $field => $value) { + $edit_data['data[' . $field . ']'] = $value; + } + // Add the effect. + $this->drupalPostForm($style_path, ['new' => $effect], t('Add')); + if (!empty($edit)) { + $this->drupalPostForm(NULL, $edit_data, t('Add effect')); + } + } + + // Load the saved image style. + $style = ImageStyle::load($style_name); + + // Ensure that third party settings were added to the config entity. + // These are added by a hook_image_style_presave() implemented in + // image_module_test module. + $this->assertEqual('bar', $style->getThirdPartySetting('image_module_test', 'foo'), 'Third party settings were added to the image style.'); + + // Ensure that the image style URI matches our expected path. + $style_uri_path = $style->url(); + $this->assertTrue(strpos($style_uri_path, $style_path) !== FALSE, 'The image style URI is correct.'); + + // Confirm that all effects on the image style have settings that match + // what was saved. + $uuids = []; + foreach ($style->getEffects() as $uuid => $effect) { + // Store the uuid for later use. + $uuids[$effect->getPluginId()] = $uuid; + $effect_configuration = $effect->getConfiguration(); + foreach ($effect_edits[$effect->getPluginId()] as $field => $value) { + $this->assertEqual($value, $effect_configuration['data'][$field], SafeMarkup::format('The %field field in the %effect effect has the correct value of %value.', ['%field' => $field, '%effect' => $effect->getPluginId(), '%value' => $value])); + } + } + + // Assert that every effect was saved. + foreach (array_keys($effect_edits) as $effect_name) { + $this->assertTrue(isset($uuids[$effect_name]), format_string( + 'A %effect_name effect was saved with ID %uuid', + [ + '%effect_name' => $effect_name, + '%uuid' => $uuids[$effect_name], + ])); + } + + // Image style overview form (ordering and renaming). + + // Confirm the order of effects is maintained according to the order we + // added the fields. + $effect_edits_order = array_keys($effect_edits); + $order_correct = TRUE; + $index = 0; + foreach ($style->getEffects() as $effect) { + if ($effect_edits_order[$index] != $effect->getPluginId()) { + $order_correct = FALSE; + } + $index++; + } + $this->assertTrue($order_correct, 'The order of the effects is correctly set by default.'); + + // Test the style overview form. + // Change the name of the style and adjust the weights of effects. + $style_name = strtolower($this->randomMachineName(10)); + $style_label = $this->randomMachineName(); + $weight = count($effect_edits); + $edit = [ + 'name' => $style_name, + 'label' => $style_label, + ]; + foreach ($style->getEffects() as $uuid => $effect) { + $edit['effects[' . $uuid . '][weight]'] = $weight; + $weight--; + } + + // Create an image to make sure it gets flushed after saving. + $image_path = $this->createSampleImage($style); + $this->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); + + $this->drupalPostForm($style_path, $edit, t('Update style')); + + // Note that after changing the style name, the style path is changed. + $style_path = 'admin/config/media/image-styles/manage/' . $style_name; + + // Check that the URL was updated. + $this->drupalGet($style_path); + $this->assertTitle(t('Edit style @name | Drupal', ['@name' => $style_label])); + $this->assertResponse(200, format_string('Image style %original renamed to %new', ['%original' => $style->id(), '%new' => $style_name])); + + // Check that the available image effects are properly sorted. + $option = $this->xpath('//select[@id=:id]//option', [':id' => 'edit-new--2']); + $this->assertEquals('Ajax test', $option[1]->getText(), '"Ajax test" is the first selectable effect.'); + + // Check that the image was flushed after updating the style. + // This is especially important when renaming the style. Make sure that + // the old image directory has been deleted. + $this->assertEqual($this->getImageCount($style), 0, format_string('Image style %style was flushed after renaming the style and updating the order of effects.', ['%style' => $style->label()])); + + // Load the style by the new name with the new weights. + $style = ImageStyle::load($style_name); + + // Confirm the new style order was saved. + $effect_edits_order = array_reverse($effect_edits_order); + $order_correct = TRUE; + $index = 0; + foreach ($style->getEffects() as $effect) { + if ($effect_edits_order[$index] != $effect->getPluginId()) { + $order_correct = FALSE; + } + $index++; + } + $this->assertTrue($order_correct, 'The order of the effects is correctly set by default.'); + + // Image effect deletion form. + + // Create an image to make sure it gets flushed after deleting an effect. + $image_path = $this->createSampleImage($style); + $this->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); + + // Delete the 'image_crop' effect from the style. + $this->drupalPostForm($style_path . '/effects/' . $uuids['image_crop'] . '/delete', [], t('Delete')); + // Confirm that the form submission was successful. + $this->assertResponse(200); + $image_crop_effect = $style->getEffect($uuids['image_crop']); + $this->assertRaw(t('The image effect %name has been deleted.', ['%name' => $image_crop_effect->label()])); + // Confirm that there is no longer a link to the effect. + $this->assertNoLinkByHref($style_path . '/effects/' . $uuids['image_crop'] . '/delete'); + // Refresh the image style information and verify that the effect was + // actually deleted. + $entity_type_manager = $this->container->get('entity_type.manager'); + $style = $entity_type_manager->getStorage('image_style')->loadUnchanged($style->id()); + $this->assertFalse($style->getEffects()->has($uuids['image_crop']), format_string( + 'Effect with ID %uuid no longer found on image style %style', + [ + '%uuid' => $uuids['image_crop'], + '%style' => $style->label(), + ])); + + // Additional test on Rotate effect, for transparent background. + $edit = [ + 'data[degrees]' => 5, + 'data[random]' => 0, + 'data[bgcolor]' => '', + ]; + $this->drupalPostForm($style_path, ['new' => 'image_rotate'], t('Add')); + $this->drupalPostForm(NULL, $edit, t('Add effect')); + $entity_type_manager = $this->container->get('entity_type.manager'); + $style = $entity_type_manager->getStorage('image_style')->loadUnchanged($style_name); + $this->assertEqual(count($style->getEffects()), 6, 'Rotate effect with transparent background was added.'); + + // Style deletion form. + + // Delete the style. + $this->drupalPostForm($style_path . '/delete', [], t('Delete')); + + // Confirm the style directory has been removed. + $directory = file_default_scheme() . '://styles/' . $style_name; + $this->assertFalse(is_dir($directory), format_string('Image style %style directory removed on style deletion.', ['%style' => $style->label()])); + + $this->assertFalse(ImageStyle::load($style_name), format_string('Image style %style successfully deleted.', ['%style' => $style->label()])); + + // Test empty text when there are no image styles. + + // Delete all image styles. + foreach (ImageStyle::loadMultiple() as $image_style) { + $image_style->delete(); + } + + // Confirm that the empty text is correct on the image styles page. + $this->drupalGet($admin_path); + $this->assertRaw(t('There are currently no styles. <a href=":url">Add a new one</a>.', [ + ':url' => \Drupal::url('image.style_add'), + ])); + + } + + /** + * Test deleting a style and choosing a replacement style. + */ + public function testStyleReplacement() { + // Create a new style. + $style_name = strtolower($this->randomMachineName(10)); + $style_label = $this->randomString(); + $style = ImageStyle::create(['name' => $style_name, 'label' => $style_label]); + $style->save(); + $style_path = 'admin/config/media/image-styles/manage/'; + + // Create an image field that uses the new style. + $field_name = strtolower($this->randomMachineName(10)); + $this->createImageField($field_name, 'article'); + entity_get_display('node', 'article', 'default') + ->setComponent($field_name, [ + 'type' => 'image', + 'settings' => ['image_style' => $style_name], + ]) + ->save(); + + // Create a new node with an image attached. + $test_image = current($this->drupalGetTestFiles('image')); + $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName()); + $node = Node::load($nid); + + // Get node field original image URI. + $fid = $node->get($field_name)->target_id; + $original_uri = File::load($fid)->getFileUri(); + + // Test that image is displayed using newly created style. + $this->drupalGet('node/' . $nid); + $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', ['@style' => $style_name])); + + // Rename the style and make sure the image field is updated. + $new_style_name = strtolower($this->randomMachineName(10)); + $new_style_label = $this->randomString(); + $edit = [ + 'name' => $new_style_name, + 'label' => $new_style_label, + ]; + $this->drupalPostForm($style_path . $style_name, $edit, t('Update style')); + $this->assertText(t('Changes to the style have been saved.'), format_string('Style %name was renamed to %new_name.', ['%name' => $style_name, '%new_name' => $new_style_name])); + $this->drupalGet('node/' . $nid); + + // Reload the image style using the new name. + $style = ImageStyle::load($new_style_name); + $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), 'Image displayed using style replacement style.'); + + // Delete the style and choose a replacement style. + $edit = [ + 'replacement' => 'thumbnail', + ]; + $this->drupalPostForm($style_path . $new_style_name . '/delete', $edit, t('Delete')); + $message = t('The image style %name has been deleted.', ['%name' => $new_style_label]); + $this->assertRaw($message); + + $replacement_style = ImageStyle::load('thumbnail'); + $this->drupalGet('node/' . $nid); + $this->assertRaw(file_url_transform_relative($replacement_style->buildUrl($original_uri)), 'Image displayed using style replacement style.'); + } + + /** + * Verifies that editing an image effect does not cause it to be duplicated. + */ + public function testEditEffect() { + // Add a scale effect. + $style_name = 'test_style_effect_edit'; + $this->drupalGet('admin/config/media/image-styles/add'); + $this->drupalPostForm(NULL, ['label' => 'Test style effect edit', 'name' => $style_name], t('Create new style')); + $this->drupalPostForm(NULL, ['new' => 'image_scale_and_crop'], t('Add')); + $this->drupalPostForm(NULL, ['data[width]' => '300', 'data[height]' => '200'], t('Add effect')); + $this->assertText(t('Scale and crop 300×200')); + + // There should normally be only one edit link on this page initially. + $this->clickLink(t('Edit')); + $this->drupalPostForm(NULL, ['data[width]' => '360', 'data[height]' => '240'], t('Update effect')); + $this->assertText(t('Scale and crop 360×240')); + + // Check that the previous effect is replaced. + $this->assertNoText(t('Scale and crop 300×200')); + + // Add another scale effect. + $this->drupalGet('admin/config/media/image-styles/add'); + $this->drupalPostForm(NULL, ['label' => 'Test style scale edit scale', 'name' => 'test_style_scale_edit_scale'], t('Create new style')); + $this->drupalPostForm(NULL, ['new' => 'image_scale'], t('Add')); + $this->drupalPostForm(NULL, ['data[width]' => '12', 'data[height]' => '19'], t('Add effect')); + + // Edit the scale effect that was just added. + $this->clickLink(t('Edit')); + $this->drupalPostForm(NULL, ['data[width]' => '24', 'data[height]' => '19'], t('Update effect')); + + // Add another scale effect and make sure both exist. Click through from + // the overview to make sure that it is possible to add new effect then. + $this->drupalGet('admin/config/media/image-styles'); + $rows = $this->xpath('//table/tbody/tr'); + $i = 0; + foreach ($rows as $row) { + if ($row->find('css', 'td')->getText() === 'Test style scale edit scale') { + $this->clickLink('Edit', $i); + break; + } + $i++; + } + $this->drupalPostForm(NULL, ['new' => 'image_scale'], t('Add')); + $this->drupalPostForm(NULL, ['data[width]' => '12', 'data[height]' => '19'], t('Add effect')); + $this->assertText(t('Scale 24×19')); + $this->assertText(t('Scale 12×19')); + + // Try to edit a nonexistent effect. + $uuid = $this->container->get('uuid'); + $this->drupalGet('admin/config/media/image-styles/manage/' . $style_name . '/effects/' . $uuid->generate()); + $this->assertResponse(404); + } + + /** + * Test flush user interface. + */ + public function testFlushUserInterface() { + $admin_path = 'admin/config/media/image-styles'; + + // Create a new style. + $style_name = strtolower($this->randomMachineName(10)); + $style = ImageStyle::create(['name' => $style_name, 'label' => $this->randomString()]); + $style->save(); + + // Create an image to make sure it gets flushed. + $files = $this->drupalGetTestFiles('image'); + $image_uri = $files[0]->uri; + $derivative_uri = $style->buildUri($image_uri); + $this->assertTrue($style->createDerivative($image_uri, $derivative_uri)); + $this->assertEqual($this->getImageCount($style), 1); + + // Go to image styles list page and check if the flush operation link + // exists. + $this->drupalGet($admin_path); + $flush_path = $admin_path . '/manage/' . $style_name . '/flush'; + $this->assertLinkByHref($flush_path); + + // Flush the image style derivatives using the user interface. + $this->drupalPostForm($flush_path, [], t('Flush')); + + // The derivative image file should have been deleted. + $this->assertEqual($this->getImageCount($style), 0); + } + + /** + * Tests image style configuration import that does a delete. + */ + public function testConfigImport() { + // Create a new style. + $style_name = strtolower($this->randomMachineName(10)); + $style_label = $this->randomString(); + $style = ImageStyle::create(['name' => $style_name, 'label' => $style_label]); + $style->save(); + + // Create an image field that uses the new style. + $field_name = strtolower($this->randomMachineName(10)); + $this->createImageField($field_name, 'article'); + entity_get_display('node', 'article', 'default') + ->setComponent($field_name, [ + 'type' => 'image', + 'settings' => ['image_style' => $style_name], + ]) + ->save(); + + // Create a new node with an image attached. + $test_image = current($this->drupalGetTestFiles('image')); + $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName()); + $node = Node::load($nid); + + // Get node field original image URI. + $fid = $node->get($field_name)->target_id; + $original_uri = File::load($fid)->getFileUri(); + + // Test that image is displayed using newly created style. + $this->drupalGet('node/' . $nid); + $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', ['@style' => $style_name])); + + // Copy config to sync, and delete the image style. + $sync = $this->container->get('config.storage.sync'); + $active = $this->container->get('config.storage'); + // Remove the image field from the display, to avoid a dependency error + // during import. + EntityViewDisplay::load('node.article.default') + ->removeComponent($field_name) + ->save(); + $this->copyConfig($active, $sync); + $sync->delete('image.style.' . $style_name); + $this->configImporter()->import(); + + $this->assertFalse(ImageStyle::load($style_name), 'Style deleted after config import.'); + $this->assertEqual($this->getImageCount($style), 0, 'Image style was flushed after being deleted by config import.'); + } + + /** + * Tests access for the image style listing. + */ + public function testImageStyleAccess() { + $style = ImageStyle::create(['name' => 'style_foo', 'label' => $this->randomString()]); + $style->save(); + + $this->drupalGet('admin/config/media/image-styles'); + $this->clickLink(t('Edit')); + $this->assertRaw(t('Select a new effect')); + } + +} diff --git a/core/modules/image/src/Tests/ImageDimensionsTest.php b/core/modules/image/tests/src/Functional/ImageDimensionsTest.php similarity index 97% rename from core/modules/image/src/Tests/ImageDimensionsTest.php rename to core/modules/image/tests/src/Functional/ImageDimensionsTest.php index 136b0f1f15d672e9982f30ae46878f92ccf900e5..46eef05d9b021982d60781444c12c35e783d310f 100644 --- a/core/modules/image/src/Tests/ImageDimensionsTest.php +++ b/core/modules/image/tests/src/Functional/ImageDimensionsTest.php @@ -1,16 +1,22 @@ <?php -namespace Drupal\image\Tests; +namespace Drupal\Tests\image\Functional; use Drupal\image\Entity\ImageStyle; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\TestFileCreationTrait; /** * Tests that images have correct dimensions when styled. * * @group image */ -class ImageDimensionsTest extends WebTestBase { +class ImageDimensionsTest extends BrowserTestBase { + + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + compareFiles as drupalCompareFiles; + } /** * Modules to enable. diff --git a/core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php b/core/modules/image/tests/src/Functional/ImageFieldDefaultImagesTest.php similarity index 98% rename from core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php rename to core/modules/image/tests/src/Functional/ImageFieldDefaultImagesTest.php index b82348ec70454587f136cf11201e028e7e368a06..c4b989a75902f9d648219c91c62f98251cd12eea 100644 --- a/core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php +++ b/core/modules/image/tests/src/Functional/ImageFieldDefaultImagesTest.php @@ -1,12 +1,14 @@ <?php -namespace Drupal\image\Tests; +namespace Drupal\Tests\image\Functional; use Drupal\Component\Utility\Unicode; use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\field\Entity\FieldConfig; use Drupal\file\Entity\File; use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Tests\EntityViewTrait; +use Drupal\Tests\TestFileCreationTrait; /** * Tests setting up default images both to the field and field storage. @@ -15,6 +17,14 @@ */ class ImageFieldDefaultImagesTest extends ImageFieldTestBase { + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + compareFiles as drupalCompareFiles; + } + use EntityViewTrait { + buildEntityView as drupalBuildEntityView; + } + /** * Modules to enable. * diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php similarity index 94% rename from core/modules/image/src/Tests/ImageFieldDisplayTest.php rename to core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php index 05d716c367899100256e2d9278a8806a293a19e2..ce924f426aabe634eb53a6ff20d788d3cd5770f0 100644 --- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php @@ -1,9 +1,11 @@ <?php -namespace Drupal\image\Tests; +namespace Drupal\Tests\image\Functional; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Tests\TestFileCreationTrait; +use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait; use Drupal\user\RoleInterface; use Drupal\image\Entity\ImageStyle; @@ -14,6 +16,12 @@ */ class ImageFieldDisplayTest extends ImageFieldTestBase { + use AssertPageCacheContextsAndTagsTrait; + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + compareFiles as drupalCompareFiles; + } + protected $dumpHeaders = TRUE; /** @@ -54,7 +62,7 @@ public function _testImageFieldFormatters($scheme) { $this->drupalGet("admin/structure/types/manage/article/display"); // Test for existence of link to image styles configuration. - $this->drupalPostAjaxForm(NULL, [], "{$field_name}_settings_edit"); + $this->drupalPostForm(NULL, [], "{$field_name}_settings_edit"); $this->assertLinkByHref(\Drupal::url('entity.image_style.collection'), 0, 'Link to image styles configuration is found'); // Remove 'administer image styles' permission from testing admin user. @@ -65,7 +73,7 @@ public function _testImageFieldFormatters($scheme) { $this->drupalGet("admin/structure/types/manage/article/display"); // Test for absence of link to image styles configuration. - $this->drupalPostAjaxForm(NULL, [], "{$field_name}_settings_edit"); + $this->drupalPostForm(NULL, [], "{$field_name}_settings_edit"); $this->assertNoLinkByHref(\Drupal::url('entity.image_style.collection'), 'Link to image styles configuration is absent when permissions are insufficient'); // Restore 'administer image styles' permission to testing admin user @@ -258,8 +266,11 @@ public function testImageFieldSettings() { $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt); $this->drupalGet('node/' . $nid . '/edit'); - $this->assertFieldByName($field_name . '[0][alt]', '', 'Alt field displayed on article form.'); + + // Verify that the optional fields alt & title are saved & filled. + $this->assertFieldByName($field_name . '[0][alt]', $alt, 'Alt field displayed on article form.'); $this->assertFieldByName($field_name . '[0][title]', '', 'Title field displayed on article form.'); + // Verify that the attached image is being previewed using the 'medium' // style. $node_storage->resetCache([$nid]); @@ -324,9 +335,9 @@ public function testImageFieldSettings() { $edit = [ 'files[' . $field_name . '_2][]' => \Drupal::service('file_system')->realpath($test_image->uri), ]; - $this->drupalPostAjaxForm(NULL, $edit, $field_name . '_2_upload_button'); - $this->assertNoRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-2-upload" name="files[' . $field_name . '_2][]" size="22" class="js-form-file form-file">'); - $this->assertRaw('<input multiple type="file" id="edit-' . strtr($field_name, '_', '-') . '-3-upload" name="files[' . $field_name . '_3][]" size="22" class="js-form-file form-file">'); + $this->drupalPostForm(NULL, $edit, $field_name . '_2_upload_button'); + $this->assertSession()->elementNotExists('css', 'input[name="files[' . $field_name . '_2][]"]'); + $this->assertSession()->elementExists('css', 'input[name="files[' . $field_name . '_3][]"]'); } /** @@ -410,10 +421,11 @@ public function testImageFieldDefaultImage() { $this->assertRaw($image_output, 'User supplied image is displayed.'); // Remove default image from the field and make sure it is no longer used. - $edit = [ - 'settings[default_image][uuid][fids]' => 0, - ]; - $this->drupalPostForm("admin/structure/types/manage/article/fields/node.article.$field_name/storage", $edit, t('Save field settings')); + // Can't use fillField cause Mink can't fill hidden fields. + $this->drupalGet("admin/structure/types/manage/article/fields/node.article.$field_name/storage"); + $this->getSession()->getPage()->find('css', 'input[name="settings[default_image][uuid][fids]"]')->setValue(0); + $this->getSession()->getPage()->pressButton(t('Save field settings')); + // Clear field definition cache so the new default image is detected. \Drupal::entityManager()->clearCachedFieldDefinitions(); $field_storage = FieldStorageConfig::loadByName('node', $field_name); diff --git a/core/modules/image/tests/src/Functional/ImageFieldTestBase.php b/core/modules/image/tests/src/Functional/ImageFieldTestBase.php index b9d659a16dbd460c045a388be696d17874b132aa..b6484a84e90d519b79c1e15340a04b73f5d12c49 100644 --- a/core/modules/image/tests/src/Functional/ImageFieldTestBase.php +++ b/core/modules/image/tests/src/Functional/ImageFieldTestBase.php @@ -87,10 +87,10 @@ public function uploadNodeImage($image, $field_name, $type, $alt = '') { 'title[0][value]' => $this->randomMachineName(), ]; $edit['files[' . $field_name . '_0]'] = \Drupal::service('file_system')->realpath($image->uri); - $this->drupalPostForm('node/add/' . $type, $edit, t('Save and publish')); + $this->drupalPostForm('node/add/' . $type, $edit, t('Save')); if ($alt) { // Add alt text. - $this->drupalPostForm(NULL, [$field_name . '[0][alt]' => $alt], t('Save and publish')); + $this->drupalPostForm(NULL, [$field_name . '[0][alt]' => $alt], t('Save')); } // Retrieve ID of the newly created node from the current URL. diff --git a/core/modules/image/tests/src/Functional/ImageFieldValidateTest.php b/core/modules/image/tests/src/Functional/ImageFieldValidateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c69a7136f12daa5d41d77a57eeee2439a6da91b6 --- /dev/null +++ b/core/modules/image/tests/src/Functional/ImageFieldValidateTest.php @@ -0,0 +1,226 @@ +<?php + +namespace Drupal\Tests\image\Functional; + +use Drupal\Tests\TestFileCreationTrait; + +/** + * Tests validation functions such as min/max resolution. + * + * @group image + */ +class ImageFieldValidateTest extends ImageFieldTestBase { + + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + compareFiles as drupalCompareFiles; + } + + /** + * Test image validity. + */ + public function testValid() { + $file_system = $this->container->get('file_system'); + $image_files = $this->drupalGetTestFiles('image'); + + $field_name = strtolower($this->randomMachineName()); + $this->createImageField($field_name, 'article', [], ['file_directory' => 'test-upload']); + $expected_path = 'public://test-upload'; + + // Create alt text for the image. + $alt = $this->randomMachineName(); + + // Create a node with a valid image. + $node = $this->uploadNodeImage($image_files[0], $field_name, 'article', $alt); + $this->assertTrue(file_exists($expected_path . '/' . $image_files[0]->filename)); + + // Remove the image. + $this->drupalPostForm('node/' . $node . '/edit', [], t('Remove')); + $this->drupalPostForm(NULL, [], t('Save')); + + // Get invalid image test files from simpletest. + $files = file_scan_directory(drupal_get_path('module', 'simpletest') . '/files', '/invalid-img-.*/'); + $invalid_image_files = []; + foreach ($files as $file) { + $invalid_image_files[$file->filename] = $file; + } + + // Try uploading a zero-byte image. + $zero_size_image = $invalid_image_files['invalid-img-zero-size.png']; + $edit = [ + 'files[' . $field_name . '_0]' => $file_system->realpath($zero_size_image->uri), + ]; + $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); + $this->assertFalse(file_exists($expected_path . '/' . $zero_size_image->filename)); + + // Try uploading an invalid image. + $invalid_image = $invalid_image_files['invalid-img-test.png']; + $edit = [ + 'files[' . $field_name . '_0]' => $file_system->realpath($invalid_image->uri), + ]; + $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); + $this->assertFalse(file_exists($expected_path . '/' . $invalid_image->filename)); + + // Upload a valid image again. + $valid_image = $image_files[0]; + $edit = [ + 'files[' . $field_name . '_0]' => $file_system->realpath($valid_image->uri), + ]; + $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); + $this->assertTrue(file_exists($expected_path . '/' . $valid_image->filename)); + } + + /** + * Test min/max resolution settings. + */ + public function testResolution() { + $field_names = [ + 0 => strtolower($this->randomMachineName()), + 1 => strtolower($this->randomMachineName()), + 2 => strtolower($this->randomMachineName()), + ]; + $min_resolution = [ + 'width' => 50, + 'height' => 50 + ]; + $max_resolution = [ + 'width' => 100, + 'height' => 100 + ]; + $no_height_min_resolution = [ + 'width' => 50, + 'height' => NULL + ]; + $no_height_max_resolution = [ + 'width' => 100, + 'height' => NULL + ]; + $no_width_min_resolution = [ + 'width' => NULL, + 'height' => 50 + ]; + $no_width_max_resolution = [ + 'width' => NULL, + 'height' => 100 + ]; + $field_settings = [ + 0 => $this->getFieldSettings($min_resolution, $max_resolution), + 1 => $this->getFieldSettings($no_height_min_resolution, $no_height_max_resolution), + 2 => $this->getFieldSettings($no_width_min_resolution, $no_width_max_resolution), + ]; + $this->createImageField($field_names[0], 'article', [], $field_settings[0]); + $this->createImageField($field_names[1], 'article', [], $field_settings[1]); + $this->createImageField($field_names[2], 'article', [], $field_settings[2]); + + // We want a test image that is too small, and a test image that is too + // big, so cycle through test image files until we have what we need. + $image_that_is_too_big = FALSE; + $image_that_is_too_small = FALSE; + $image_factory = $this->container->get('image.factory'); + foreach ($this->drupalGetTestFiles('image') as $image) { + $image_file = $image_factory->get($image->uri); + if ($image_file->getWidth() > $max_resolution['width']) { + $image_that_is_too_big = $image; + } + if ($image_file->getWidth() < $min_resolution['width']) { + $image_that_is_too_small = $image; + $image_that_is_too_small_file = $image_file; + } + if ($image_that_is_too_small && $image_that_is_too_big) { + break; + } + } + $this->uploadNodeImage($image_that_is_too_small, $field_names[0], 'article'); + $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); + $this->assertRaw(t('The image is too small. The minimum dimensions are %dimensions pixels and the image size is %widthx%height pixels.', [ + '%dimensions' => '50x50', + '%width' => $image_that_is_too_small_file->getWidth(), + '%height' => $image_that_is_too_small_file->getHeight(), + ])); + $this->uploadNodeImage($image_that_is_too_big, $field_names[0], 'article'); + $this->assertText(t('The image was resized to fit within the maximum allowed dimensions of 100x100 pixels.')); + $this->uploadNodeImage($image_that_is_too_small, $field_names[1], 'article'); + $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); + $this->uploadNodeImage($image_that_is_too_big, $field_names[1], 'article'); + $this->assertText(t('The image was resized to fit within the maximum allowed width of 100 pixels.')); + $this->uploadNodeImage($image_that_is_too_small, $field_names[2], 'article'); + $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); + $this->uploadNodeImage($image_that_is_too_big, $field_names[2], 'article'); + $this->assertText(t('The image was resized to fit within the maximum allowed height of 100 pixels.')); + } + + /** + * Test that required alt/title fields gets validated right. + */ + public function testRequiredAttributes() { + $field_name = strtolower($this->randomMachineName()); + $field_settings = [ + 'alt_field' => 1, + 'alt_field_required' => 1, + 'title_field' => 1, + 'title_field_required' => 1, + 'required' => 1, + ]; + $instance = $this->createImageField($field_name, 'article', [], $field_settings); + $images = $this->drupalGetTestFiles('image'); + // Let's just use the first image. + $image = $images[0]; + $this->uploadNodeImage($image, $field_name, 'article'); + + // Look for form-required for the alt text. + $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-alt" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-alt"]'); + + $this->assertTrue(isset($elements[0]), 'Required marker is shown for the required alt text.'); + + $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-title" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-title"]'); + + $this->assertTrue(isset($elements[0]), 'Required marker is shown for the required title text.'); + + $this->assertText(t('Alternative text field is required.')); + $this->assertText(t('Title field is required.')); + + $instance->setSetting('alt_field_required', 0); + $instance->setSetting('title_field_required', 0); + $instance->save(); + + $edit = [ + 'title[0][value]' => $this->randomMachineName(), + ]; + $this->drupalPostForm('node/add/article', $edit, t('Save')); + + $this->assertNoText(t('Alternative text field is required.')); + $this->assertNoText(t('Title field is required.')); + + $instance->setSetting('required', 0); + $instance->setSetting('alt_field_required', 1); + $instance->setSetting('title_field_required', 1); + $instance->save(); + + $edit = [ + 'title[0][value]' => $this->randomMachineName(), + ]; + $this->drupalPostForm('node/add/article', $edit, t('Save')); + + $this->assertNoText(t('Alternative text field is required.')); + $this->assertNoText(t('Title field is required.')); + } + + /** + * Returns field settings. + * + * @param int[] $min_resolution + * The minimum width and height resolution setting. + * @param int[] $max_resolution + * The maximum width and height resolution setting. + * + * @return array + */ + protected function getFieldSettings($min_resolution, $max_resolution) { + return [ + 'max_resolution' => $max_resolution['width'] . 'x' . $max_resolution['height'], + 'min_resolution' => $min_resolution['width'] . 'x' . $min_resolution['height'], + 'alt_field' => 0, + ]; + } + +} diff --git a/core/modules/image/src/Tests/ImageOnTranslatedEntityTest.php b/core/modules/image/tests/src/Functional/ImageOnTranslatedEntityTest.php similarity index 97% rename from core/modules/image/src/Tests/ImageOnTranslatedEntityTest.php rename to core/modules/image/tests/src/Functional/ImageOnTranslatedEntityTest.php index 1ae555289f88a3319027aef010b7ed670e26b0ad..15ca7582880dc605779758892cd26e2551b0187e 100644 --- a/core/modules/image/src/Tests/ImageOnTranslatedEntityTest.php +++ b/core/modules/image/tests/src/Functional/ImageOnTranslatedEntityTest.php @@ -1,8 +1,9 @@ <?php -namespace Drupal\image\Tests; +namespace Drupal\Tests\image\Functional; use Drupal\file\Entity\File; +use Drupal\Tests\TestFileCreationTrait; /** * Uploads images to translated nodes. @@ -11,6 +12,11 @@ */ class ImageOnTranslatedEntityTest extends ImageFieldTestBase { + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + compareFiles as drupalCompareFiles; + } + /** * {@inheritdoc} */ diff --git a/core/modules/image/src/Tests/ImageStyleFlushTest.php b/core/modules/image/tests/src/Functional/ImageStyleFlushTest.php similarity index 95% rename from core/modules/image/src/Tests/ImageStyleFlushTest.php rename to core/modules/image/tests/src/Functional/ImageStyleFlushTest.php index 4e8cd2c779e23cfba70b94d9472d93231263420a..070f199982f8d6f7bd927740b26deb8dc10bc787 100644 --- a/core/modules/image/src/Tests/ImageStyleFlushTest.php +++ b/core/modules/image/tests/src/Functional/ImageStyleFlushTest.php @@ -1,8 +1,9 @@ <?php -namespace Drupal\image\Tests; +namespace Drupal\Tests\image\Functional; use Drupal\image\Entity\ImageStyle; +use Drupal\Tests\TestFileCreationTrait; /** * Tests flushing of image styles. @@ -11,6 +12,11 @@ */ class ImageStyleFlushTest extends ImageFieldTestBase { + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + compareFiles as drupalCompareFiles; + } + /** * Given an image style and a wrapper, generate an image. */ diff --git a/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php b/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php similarity index 95% rename from core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php rename to core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php index eef166c95169e04d1927eb40713549959d2e7c61..a0c7b1935928f09e02ea4f1d54b37cad4c093438 100644 --- a/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php +++ b/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php @@ -1,17 +1,23 @@ <?php -namespace Drupal\image\Tests; +namespace Drupal\Tests\image\Functional; use Drupal\image\Entity\ImageStyle; use Drupal\language\Entity\ConfigurableLanguage; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\TestFileCreationTrait; /** * Tests the functions for generating paths and URLs for image styles. * * @group image */ -class ImageStylesPathAndUrlTest extends WebTestBase { +class ImageStylesPathAndUrlTest extends BrowserTestBase { + + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + compareFiles as drupalCompareFiles; + } /** * Modules to enable. @@ -189,7 +195,8 @@ public function doImageStyleUrlAndPathTests($scheme, $clean_url = TRUE, $extra_s $this->drupalGet($generate_url); $this->assertResponse(200, 'Image was generated at the URL.'); $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $this->assertRaw(file_get_contents($generated_uri), 'URL returns expected file.'); + // assertRaw can't be used with string containing non UTF-8 chars. + $this->assertNotEmpty(file_get_contents($generated_uri), 'URL returns expected file.'); $image = $this->container->get('image.factory')->get($generated_uri); $this->assertEqual($this->drupalGetHeader('Content-Type'), $image->getMimeType(), 'Expected Content-Type was reported.'); $this->assertEqual($this->drupalGetHeader('Content-Length'), $image->getFileSize(), 'Expected Content-Length was reported.'); @@ -240,7 +247,8 @@ public function doImageStyleUrlAndPathTests($scheme, $clean_url = TRUE, $extra_s // Check for PNG-Signature // (cf. http://www.libpng.org/pub/png/book/chapter08.html#png.ch08.div.2) // in the response body. - $this->assertNoRaw(chr(137) . chr(80) . chr(78) . chr(71) . chr(13) . chr(10) . chr(26) . chr(10), 'No PNG signature found in the response body.'); + $raw = $this->getSession()->getPage()->getContent(); + $this->assertFalse(strpos($raw, chr(137) . chr(80) . chr(78) . chr(71) . chr(13) . chr(10) . chr(26) . chr(10))); } } else { diff --git a/core/modules/image/src/Tests/QuickEditImageControllerTest.php b/core/modules/image/tests/src/Functional/QuickEditImageControllerTest.php similarity index 76% rename from core/modules/image/src/Tests/QuickEditImageControllerTest.php rename to core/modules/image/tests/src/Functional/QuickEditImageControllerTest.php index cfe4ccbfb14394781742bcc657b37f02522dde51..a037d4808d66d725c746c9896bc6802bea80b71d 100644 --- a/core/modules/image/src/Tests/QuickEditImageControllerTest.php +++ b/core/modules/image/tests/src/Functional/QuickEditImageControllerTest.php @@ -1,18 +1,23 @@ <?php -namespace Drupal\image\Tests; +namespace Drupal\Tests\image\Functional; +use Drupal\Component\Serialization\Json; +use Drupal\Tests\BrowserTestBase; use Drupal\Tests\image\Kernel\ImageFieldCreationTrait; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\TestFileCreationTrait; /** * Tests the endpoints used by the "image" in-place editor. * * @group image */ -class QuickEditImageControllerTest extends WebTestBase { +class QuickEditImageControllerTest extends BrowserTestBase { use ImageFieldCreationTrait; + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + } /** * {@inheritdoc} @@ -77,8 +82,11 @@ public function testAccess() { ]); $this->drupalGet('quickedit/image/info/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default'); $this->assertResponse('403'); - $this->drupalPost('quickedit/image/upload/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default', 'application/json', []); - $this->assertResponse('403'); + + /** @var \Symfony\Component\BrowserKit\Client $client */ + $client = $this->getSession()->getDriver()->getClient(); + $client->request('POST', '/quickedit/image/upload/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default'); + $this->assertEquals('403', $client->getResponse()->getStatus()); } /** @@ -90,7 +98,8 @@ public function testFieldInfo() { 'type' => 'article', 'title' => t('Test Node'), ]); - $info = $this->drupalGetJSON('quickedit/image/info/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default'); + $json = $this->drupalGet('quickedit/image/info/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default', ['query' => ['_format' => 'json']]); + $info = Json::decode($json); // Assert that the default settings for our field are respected by our JSON // endpoint. $this->assertTrue($info['alt_field']); @@ -118,8 +127,10 @@ public function testValidImageUpload() { } } $this->assertTrue($valid_image); + + $this->drupalLogin($this->contentAuthorUser); $this->uploadImage($valid_image, $node->id(), $this->fieldName, $node->language()->getId()); - $this->assertText('fid', t('Valid upload completed successfully.')); + $this->assertContains('"fid":"1"', $this->getSession()->getPage()->getContent(), 'Valid upload completed successfully.'); } /** @@ -145,8 +156,10 @@ public function testInvalidUpload() { } } $this->assertTrue($invalid_image); + + $this->drupalLogin($this->contentAuthorUser); $this->uploadImage($invalid_image, $node->id(), $this->fieldName, $node->language()->getId()); - $this->assertText('main_error', t('Invalid upload returned errors.')); + $this->assertContains('"main_error":"The image failed validation."', $this->getSession()->getPage()->getContent(), 'Invalid upload returned errors.'); } /** @@ -160,27 +173,14 @@ public function testInvalidUpload() { * The target field machine name. * @param string $langcode * The langcode to use when setting the field's value. - * - * @return mixed - * The content returned from the call to $this->curlExec(). */ public function uploadImage($image, $nid, $field_name, $langcode) { $filepath = $this->container->get('file_system')->realpath($image->uri); - $data = [ - 'files[image]' => curl_file_create($filepath), - ]; $path = 'quickedit/image/upload/node/' . $nid . '/' . $field_name . '/' . $langcode . '/default'; - // We assemble the curl request ourselves as drupalPost cannot process file - // uploads, and drupalPostForm only works with typical Drupal forms. - return $this->curlExec([ - CURLOPT_URL => $this->buildUrl($path, []), - CURLOPT_POST => TRUE, - CURLOPT_POSTFIELDS => $data, - CURLOPT_HTTPHEADER => [ - 'Accept: application/json', - 'Content-Type: multipart/form-data', - ], - ]); + + $this->prepareRequest(); + $client = $this->getSession()->getDriver()->getClient(); + $client->request('POST', $this->buildUrl($path, []), [], ['files[image]' => $filepath]); } } diff --git a/core/modules/image/src/Tests/ImageThemeFunctionTest.php b/core/modules/image/tests/src/Kernel/ImageThemeFunctionTest.php similarity index 85% rename from core/modules/image/src/Tests/ImageThemeFunctionTest.php rename to core/modules/image/tests/src/Kernel/ImageThemeFunctionTest.php index 54c5c64a19fdbaa9e21eb183ca18e6236d76dfe8..7abe47e47a7abbd0b1349ce987de86f31984dd66 100644 --- a/core/modules/image/src/Tests/ImageThemeFunctionTest.php +++ b/core/modules/image/tests/src/Kernel/ImageThemeFunctionTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\image\Tests; +namespace Drupal\Tests\image\Kernel; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Url; @@ -8,22 +8,28 @@ use Drupal\field\Entity\FieldConfig; use Drupal\file\Entity\File; use Drupal\image\Entity\ImageStyle; -use Drupal\simpletest\WebTestBase; +use Drupal\KernelTests\KernelTestBase; use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Tests\TestFileCreationTrait; /** * Tests image theme functions. * * @group image */ -class ImageThemeFunctionTest extends WebTestBase { +class ImageThemeFunctionTest extends KernelTestBase { + + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + compareFiles as drupalCompareFiles; + } /** * Modules to enable. * * @var array */ - public static $modules = ['image', 'entity_test']; + public static $modules = ['entity_test', 'field', 'file', 'image', 'system', 'simpletest', 'user']; /** * Created file entity. @@ -40,6 +46,11 @@ class ImageThemeFunctionTest extends WebTestBase { protected function setUp() { parent::setUp(); + $this->installEntitySchema('entity_test'); + $this->installEntitySchema('file'); + $this->installSchema('file', ['file_usage']); + $this->installEntitySchema('user'); + FieldStorageConfig::create([ 'entity_type' => 'entity_test', 'field_name' => 'image_test', @@ -96,7 +107,7 @@ public function testImageFormatterTheme() { // Test using theme_image_formatter() with a NULL value for the alt option. $element = $base_element; $this->setRawContent($renderer->renderRoot($element)); - $elements = $this->xpath('//a[@href=:path]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height]', [':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()]); + $elements = $this->xpath('//a[@href=:path]/img[@src=:url and @width=:width and @height=:height]', [':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()]); $this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders with a NULL value for the alt option.'); // Test using theme_image_formatter() without an image title, alt text, or @@ -104,7 +115,7 @@ public function testImageFormatterTheme() { $element = $base_element; $element['#item']->alt = ''; $this->setRawContent($renderer->renderRoot($element)); - $elements = $this->xpath('//a[@href=:path]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height and @alt=""]', [':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()]); + $elements = $this->xpath('//a[@href=:path]/img[@src=:url and @width=:width and @height=:height and @alt=""]', [':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()]); $this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders without title, alt, or path options.'); // Link the image to a fragment on the page, and not a full URL. @@ -112,7 +123,7 @@ public function testImageFormatterTheme() { $element = $base_element; $element['#url'] = Url::fromRoute('<none>', [], ['fragment' => $fragment]); $this->setRawContent($renderer->renderRoot($element)); - $elements = $this->xpath('//a[@href=:fragment]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height and @alt=""]', [ + $elements = $this->xpath('//a[@href=:fragment]/img[@src=:url and @width=:width and @height=:height and @alt=""]', [ ':fragment' => '#' . $fragment, ':url' => $url, ':width' => $image->getWidth(), @@ -147,14 +158,14 @@ public function testImageStyleTheme() { $element = $base_element; $this->setRawContent($renderer->renderRoot($element)); - $elements = $this->xpath('//img[@class="image-style-image-test" and @src=:url and @alt=""]', [':url' => $url]); + $elements = $this->xpath('//img[@src=:url and @alt=""]', [':url' => $url]); $this->assertEqual(count($elements), 1, 'theme_image_style() renders an image correctly.'); // Test using theme_image_style() with a NULL value for the alt option. $element = $base_element; $element['#alt'] = NULL; $this->setRawContent($renderer->renderRoot($element)); - $elements = $this->xpath('//img[@class="image-style-image-test" and @src=:url]', [':url' => $url]); + $elements = $this->xpath('//img[@src=:url]', [':url' => $url]); $this->assertEqual(count($elements), 1, 'theme_image_style() renders an image correctly with a NULL value for the alt option.'); } diff --git a/core/modules/image/src/Tests/Views/RelationshipUserImageDataTest.php b/core/modules/image/tests/src/Kernel/Views/RelationshipUserImageDataTest.php similarity index 82% rename from core/modules/image/src/Tests/Views/RelationshipUserImageDataTest.php rename to core/modules/image/tests/src/Kernel/Views/RelationshipUserImageDataTest.php index 374981f63aa092c5b4bd1b7487859393db27af64..e0f605e92ddedfd92eee50876a4b2987c2b87e4e 100644 --- a/core/modules/image/src/Tests/Views/RelationshipUserImageDataTest.php +++ b/core/modules/image/tests/src/Kernel/Views/RelationshipUserImageDataTest.php @@ -1,10 +1,11 @@ <?php -namespace Drupal\image\Tests\Views; +namespace Drupal\Tests\image\Kernel\Views; use Drupal\field\Entity\FieldConfig; use Drupal\file\Entity\File; -use Drupal\views\Tests\ViewTestBase; +use Drupal\Tests\views\Kernel\ViewsKernelTestBase; +use Drupal\user\Entity\User; use Drupal\views\Views; use Drupal\views\Tests\ViewTestData; use Drupal\field\Entity\FieldStorageConfig; @@ -14,14 +15,14 @@ * * @group image */ -class RelationshipUserImageDataTest extends ViewTestBase { +class RelationshipUserImageDataTest extends ViewsKernelTestBase { /** * Modules to install. * * @var array */ - public static $modules = ['image', 'image_test_views', 'user']; + public static $modules = ['file', 'field', 'image', 'image_test_views', 'system', 'user']; /** * Views used by this test. @@ -33,6 +34,10 @@ class RelationshipUserImageDataTest extends ViewTestBase { protected function setUp($import_test_views = TRUE) { parent::setUp($import_test_views); + $this->installEntitySchema('file'); + $this->installSchema('file', ['file_usage']); + $this->installEntitySchema('user'); + // Create the user profile field and instance. FieldStorageConfig::create([ 'entity_type' => 'user', @@ -70,7 +75,9 @@ public function testViewsHandlerRelationshipUserImageData() { file_put_contents($file->getFileUri(), file_get_contents('core/modules/simpletest/files/image-1.png')); $file->save(); - $account = $this->drupalCreateUser(); + $account = User::create([ + 'name' => 'foo', + ]); $account->user_picture->target_id = 2; $account->save();