3 namespace Drupal\image_widget_crop\Tests;
5 use Drupal\crop\Entity\CropType;
6 use Drupal\file\Entity\File;
7 use Drupal\image\Entity\ImageStyle;
8 use Drupal\node\Entity\Node;
9 use Drupal\simpletest\WebTestBase;
12 * Minimal test case for the image_widget_crop module.
14 * @group image_widget_crop
18 class ImageWidgetCropTest extends WebTestBase {
21 * User with permissions to create content.
23 * @var \Drupal\user\Entity\User
32 public static $modules = [
41 * Prepares environment for the tests.
43 protected function setUp() {
46 $this->drupalCreateContentType(['name' => 'Crop test', 'type' => 'crop_test']);
48 $this->user = $this->createUser([
49 'access content overview',
50 'administer content types',
51 'edit any crop_test content',
52 'edit any image files',
55 $this->drupalLogin($this->user);
59 * Test Image Widget Crop UI.
61 public function testCropUi() {
62 // Test that when a crop has more than one usage we have a warning.
63 $this->createImageField('field_image_crop_test', 'crop_test', 'image_widget_crop', [], [], ['crop_list' => ['crop_16_9' => 'crop_16_9']]);
64 $this->drupalGetTestFiles('image');
66 $this->drupalGet('node/add/crop_test');
68 'title[0][value]' => $this->randomMachineName(),
69 'files[field_image_crop_test_0]' => \Drupal::service('file_system')->realpath('public://image-test.jpg'),
71 $this->drupalPostAjaxForm(NULL, $edit, $this->getButtonName('//input[@type="submit" and @value="Upload" and @data-drupal-selector="edit-field-image-crop-test-0-upload-button"]'));
73 $node = Node::create([
74 'title' => '2nd node using it',
75 'type' => 'crop_test',
76 'field_image_crop_test' => 1,
77 'alt' => $this->randomMachineName(),
81 /** @var \Drupal\file\FileUsage\FileUsageInterface $usage */
82 $usage = \Drupal::service('file.usage');
83 $usage->add(\Drupal::service('entity_type.manager')->getStorage('file')->load(1), 'image_widget_crop', 'node', $node->id());
85 $this->drupalGet('node/1/edit');
87 $this->assertRaw(t('This crop definition affects more usages of this image'));
92 * Test Image Widget Crop.
94 public function testImageWidgetCrop() {
95 // Test that crop widget works properly.
96 $this->createImageField('field_image_crop_test', 'crop_test', 'image_widget_crop', [], [], ['crop_list' => ['crop_16_9' => 'crop_16_9']]);
97 $this->drupalGetTestFiles('image');
99 $this->drupalGet('node/add/crop_test');
101 // Assert that there is no crop widget, neither 'Alternative text' text
102 // filed nor 'Remove' button yet.
103 $raw = '<summary role="button" aria-controls="edit-field-image-crop-test-0-image-crop-crop-wrapper" aria-expanded="false" aria-pressed="false">Crop image</summary>';
104 $this->assertNoRaw($raw);
105 $this->assertNoText('Alternative text');
106 $this->assertNoFieldByName('field_image_crop_test_0_remove_button');
108 // Upload an image in field_image_crop_test_0.
109 $image['files[field_image_crop_test_0]'] = $this->container->get('file_system')->realpath('public://image-test.jpg');
110 $this->drupalPostAjaxForm(NULL, $image, $this->getButtonName('//input[@type="submit" and @value="Upload" and @data-drupal-selector="edit-field-image-crop-test-0-upload-button"]'));
112 // Assert that now crop widget and 'Alternative text' text field appear and
113 // that 'Remove' button exists.
114 $this->assertRaw($raw);
115 $this->assertText('Alternative text');
116 $this->assertFieldByName('field_image_crop_test_0_remove_button');
118 // Set title and 'Alternative text' text field and save.
119 $title = $this->randomMachineName();
121 'title[0][value]' => $title,
122 'field_image_crop_test[0][alt]' => $this->randomMachineName(),
124 $this->drupalPostForm(NULL, $edit, 'Save');
125 $this->assertText('Crop test ' . $title . ' has been created.');
126 $url = $this->getUrl();
127 $nid = substr($url, -1, strrpos($url, '/'));
130 $this->drupalGet('node/' . $nid . '/edit');
132 // Verify that the 'Remove' button works properly.
133 $this->assertText('Alternative text');
134 $this->drupalPostForm(NULL, NULL, 'Remove');
135 $this->assertNoText('Alternative text');
137 // Re-upload the image and set the 'Alternative text'.
138 $this->drupalPostAjaxForm(NULL, $image, $this->getButtonName('//input[@type="submit" and @value="Upload" and @data-drupal-selector="edit-field-image-crop-test-0-upload-button"]'));
140 // Verify that the 'Preview' button works properly.
141 $this->drupalPostForm(NULL, $edit, 'Preview');
142 $this->assertLink('Back to content editing');
143 $this->clickLink('Back to content editing');
145 // Verify that there is an image style preview.
146 $this->assertFieldByName('field_image_crop_test[0][width]', '40');
147 $this->assertFieldByName('field_image_crop_test[0][height]', '20');
152 * Tests integration with file_entity module.
154 public function testFileEntityIntegration() {
155 $this->createImageField('field_image_file_entity', 'crop_test', 'file_editable');
157 $image = current($this->drupalGetTestFiles('image'));
158 $image = File::create((array) $image);
161 $node_title = $this->randomMachineName();
162 $this->drupalGet('node/add/crop_test');
164 'title[0][value]' => $node_title,
165 'files[field_image_file_entity_0]' => \Drupal::service('file_system')
166 ->realpath('public://image-test.jpg'),
168 $this->drupalPostForm(NULL, $edit, 'Save');
170 $node = $this->drupalGetNodeByTitle($node_title);
172 $this->drupalGet('node/' . $node->id() . '/edit');
173 $ajax_response = $this->drupalPostAjaxForm(NULL, [], ['file_editable_2' => t('Edit')]);
174 $this->assertTrue(preg_match('/Crop image/', $ajax_response[3]['data']), 'Cropping tool is available on inline edit.');
176 // Create a sample crop type.
177 $crop_type = CropType::create([
180 'aspect_ratio' => '16:9',
184 // Add a created crop type to an image style.
185 $crop_image_style = ImageStyle::load('large');
186 $crop_image_style->addImageEffect([
188 'data' => ['crop_type' => '16_9'],
190 $crop_image_style->save();
192 // Assert that crop widget is displayed by default, even if there are no
193 // crop types selected in the global image widget crop configuration.
194 $image_widget_crop_settings = \Drupal::config('image_widget_crop.settings')->get('crop_list');
195 $this->assertEqual($image_widget_crop_settings, []);
196 $this->drupalGet('file/' . $image->id() . '/edit');
197 $this->assertRaw('edit-image-crop-crop-wrapper-16-9');
198 $this->assertRaw('16_9');
200 $this->assertText('Crop image', 'Cropping tool available on file edit.');
204 * Gets IEF button name.
206 * @param string $xpath
207 * Xpath of the button.
210 * The name of the button.
212 protected function getButtonName($xpath) {
214 /** @var \SimpleXMLElement[] $elements */
215 if ($elements = $this->xpath($xpath)) {
216 foreach ($elements[0]->attributes() as $name => $value) {
217 if ($name == 'name') {
218 $retval = (string) $value;
227 * Create a new image field.
229 * @param string $name
230 * The name of the new field (all lowercase), exclude the "field_" prefix.
231 * @param string $type_name
232 * The node type that this field will be added to.
233 * @param string $widget_name
234 * The name of the widget.
235 * @param array $storage_settings
236 * A list of field storage settings that will be added to the defaults.
237 * @param array $field_settings
238 * A list of instance settings that will be added to the instance defaults.
239 * @param array $widget_settings
240 * A list of widget settings that will be added to the widget defaults.
242 protected function createImageField($name, $type_name, $widget_name, array $storage_settings = [], array $field_settings = [], array $widget_settings = []) {
243 \Drupal::entityTypeManager()->getStorage('field_storage_config')->create([
244 'field_name' => $name,
245 'entity_type' => 'node',
247 'settings' => $storage_settings,
248 'cardinality' => !empty($storage_settings['cardinality']) ? $storage_settings['cardinality'] : 1,
251 $field_config = \Drupal::entityTypeManager()->getStorage('field_config')->create([
252 'field_name' => $name,
254 'entity_type' => 'node',
255 'bundle' => $type_name,
256 'required' => !empty($field_settings['required']),
257 'settings' => $field_settings,
259 $field_config->save();
261 /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
262 $form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load('node.' . $type_name . '.default');
263 $form_display->setComponent($name, [
264 'type' => $widget_name,
265 'settings' => $widget_settings,
268 /** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $view_display */
269 $view_display = \Drupal::entityTypeManager()->getStorage('entity_view_display')->load('node.' . $type_name . '.default');
270 $view_display->setComponent($name)