Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Tests\image\FunctionalJavascript;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\file\Entity\File;
|
Chris@0
|
6 use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
|
Chris@0
|
7 use Drupal\Tests\image\Kernel\ImageFieldCreationTrait;
|
Chris@0
|
8 use Drupal\Tests\TestFileCreationTrait;
|
Chris@0
|
9
|
Chris@0
|
10 /**
|
Chris@0
|
11 * Tests the JavaScript functionality of the "image" in-place editor.
|
Chris@0
|
12 *
|
Chris@0
|
13 * @group image
|
Chris@0
|
14 */
|
Chris@0
|
15 class QuickEditImageTest extends JavascriptTestBase {
|
Chris@0
|
16
|
Chris@0
|
17 use ImageFieldCreationTrait;
|
Chris@0
|
18 use TestFileCreationTrait;
|
Chris@0
|
19
|
Chris@0
|
20 /**
|
Chris@0
|
21 * {@inheritdoc}
|
Chris@0
|
22 */
|
Chris@0
|
23 public static $modules = ['node', 'image', 'field_ui', 'contextual', 'quickedit', 'toolbar'];
|
Chris@0
|
24
|
Chris@0
|
25 /**
|
Chris@0
|
26 * A user with permissions to edit Articles and use Quick Edit.
|
Chris@0
|
27 *
|
Chris@0
|
28 * @var \Drupal\user\UserInterface
|
Chris@0
|
29 */
|
Chris@0
|
30 protected $contentAuthorUser;
|
Chris@0
|
31
|
Chris@0
|
32 /**
|
Chris@0
|
33 * {@inheritdoc}
|
Chris@0
|
34 */
|
Chris@0
|
35 protected function setUp() {
|
Chris@0
|
36 parent::setUp();
|
Chris@0
|
37
|
Chris@0
|
38 // Create the Article node type.
|
Chris@0
|
39 $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
Chris@0
|
40
|
Chris@0
|
41 // Log in as a content author who can use Quick Edit and edit Articles.
|
Chris@0
|
42 $this->contentAuthorUser = $this->drupalCreateUser([
|
Chris@0
|
43 'access contextual links',
|
Chris@0
|
44 'access toolbar',
|
Chris@0
|
45 'access in-place editing',
|
Chris@0
|
46 'access content',
|
Chris@0
|
47 'create article content',
|
Chris@0
|
48 'edit any article content',
|
Chris@0
|
49 'delete any article content',
|
Chris@0
|
50 ]);
|
Chris@0
|
51 $this->drupalLogin($this->contentAuthorUser);
|
Chris@0
|
52 }
|
Chris@0
|
53
|
Chris@0
|
54 /**
|
Chris@0
|
55 * Tests if an image can be uploaded inline with Quick Edit.
|
Chris@0
|
56 */
|
Chris@0
|
57 public function testUpload() {
|
Chris@0
|
58 // Create a field with a basic filetype restriction.
|
Chris@0
|
59 $field_name = strtolower($this->randomMachineName());
|
Chris@0
|
60 $field_settings = [
|
Chris@0
|
61 'file_extensions' => 'png',
|
Chris@0
|
62 ];
|
Chris@0
|
63 $formatter_settings = [
|
Chris@0
|
64 'image_style' => 'large',
|
Chris@0
|
65 'image_link' => '',
|
Chris@0
|
66 ];
|
Chris@0
|
67 $this->createImageField($field_name, 'article', [], $field_settings, [], $formatter_settings);
|
Chris@0
|
68
|
Chris@0
|
69 // Find images that match our field settings.
|
Chris@0
|
70 $valid_images = [];
|
Chris@0
|
71 foreach ($this->getTestFiles('image') as $image) {
|
Chris@0
|
72 // This regex is taken from file_validate_extensions().
|
Chris@0
|
73 $regex = '/\.(' . preg_replace('/ +/', '|', preg_quote($field_settings['file_extensions'])) . ')$/i';
|
Chris@0
|
74 if (preg_match($regex, $image->filename)) {
|
Chris@0
|
75 $valid_images[] = $image;
|
Chris@0
|
76 }
|
Chris@0
|
77 }
|
Chris@0
|
78
|
Chris@0
|
79 // Ensure we have at least two valid images.
|
Chris@0
|
80 $this->assertGreaterThanOrEqual(2, count($valid_images));
|
Chris@0
|
81
|
Chris@0
|
82 // Create a File entity for the initial image.
|
Chris@0
|
83 $file = File::create([
|
Chris@0
|
84 'uri' => $valid_images[0]->uri,
|
Chris@0
|
85 'uid' => $this->contentAuthorUser->id(),
|
Chris@0
|
86 'status' => FILE_STATUS_PERMANENT,
|
Chris@0
|
87 ]);
|
Chris@0
|
88 $file->save();
|
Chris@0
|
89
|
Chris@0
|
90 // Use the first valid image to create a new Node.
|
Chris@0
|
91 $image_factory = $this->container->get('image.factory');
|
Chris@0
|
92 $image = $image_factory->get($valid_images[0]->uri);
|
Chris@0
|
93 $node = $this->drupalCreateNode([
|
Chris@0
|
94 'type' => 'article',
|
Chris@0
|
95 'title' => t('Test Node'),
|
Chris@0
|
96 $field_name => [
|
Chris@0
|
97 'target_id' => $file->id(),
|
Chris@0
|
98 'alt' => 'Hello world',
|
Chris@0
|
99 'title' => '',
|
Chris@0
|
100 'width' => $image->getWidth(),
|
Chris@0
|
101 'height' => $image->getHeight(),
|
Chris@0
|
102 ],
|
Chris@0
|
103 ]);
|
Chris@0
|
104
|
Chris@0
|
105 // Visit the new Node.
|
Chris@0
|
106 $this->drupalGet('node/' . $node->id());
|
Chris@0
|
107
|
Chris@0
|
108 // Assemble common CSS selectors.
|
Chris@0
|
109 $entity_selector = '[data-quickedit-entity-id="node/' . $node->id() . '"]';
|
Chris@0
|
110 $field_selector = '[data-quickedit-field-id="node/' . $node->id() . '/' . $field_name . '/' . $node->language()->getId() . '/full"]';
|
Chris@0
|
111 $original_image_selector = 'img[src*="' . $valid_images[0]->filename . '"][alt="Hello world"]';
|
Chris@0
|
112 $new_image_selector = 'img[src*="' . $valid_images[1]->filename . '"][alt="New text"]';
|
Chris@0
|
113
|
Chris@0
|
114 // Assert that the initial image is present.
|
Chris@0
|
115 $this->assertSession()->elementExists('css', $entity_selector . ' ' . $field_selector . ' ' . $original_image_selector);
|
Chris@0
|
116
|
Chris@0
|
117 // Wait until Quick Edit loads.
|
Chris@0
|
118 $condition = "jQuery('" . $entity_selector . " .quickedit').length > 0";
|
Chris@0
|
119 $this->assertJsCondition($condition, 10000);
|
Chris@0
|
120
|
Chris@0
|
121 // Initiate Quick Editing.
|
Chris@0
|
122 $this->click('.contextual-toolbar-tab button');
|
Chris@0
|
123 $this->click($entity_selector . ' [data-contextual-id] > button');
|
Chris@0
|
124 $this->click($entity_selector . ' [data-contextual-id] .quickedit > a');
|
Chris@0
|
125 $this->click($field_selector);
|
Chris@0
|
126
|
Chris@0
|
127 // Wait for the field info to load and set new alt text.
|
Chris@0
|
128 $condition = "jQuery('.quickedit-image-field-info').length > 0";
|
Chris@0
|
129 $this->assertJsCondition($condition, 10000);
|
Chris@0
|
130 $input = $this->assertSession()->elementExists('css', '.quickedit-image-field-info input[name="alt"]');
|
Chris@0
|
131 $input->setValue('New text');
|
Chris@0
|
132
|
Chris@0
|
133 // Check that our Dropzone element exists.
|
Chris@0
|
134 $this->assertSession()->elementExists('css', $field_selector . ' .quickedit-image-dropzone');
|
Chris@0
|
135
|
Chris@0
|
136 // Our headless browser can't drag+drop files, but we can mock the event.
|
Chris@0
|
137 // Append a hidden upload element to the DOM.
|
Chris@0
|
138 $script = 'jQuery("<input id=\"quickedit-image-test-input\" type=\"file\" />").appendTo("body")';
|
Chris@0
|
139 $this->getSession()->executeScript($script);
|
Chris@0
|
140
|
Chris@0
|
141 // Find the element, and set its value to our new image.
|
Chris@0
|
142 $input = $this->assertSession()->elementExists('css', '#quickedit-image-test-input');
|
Chris@0
|
143 $filepath = $this->container->get('file_system')->realpath($valid_images[1]->uri);
|
Chris@0
|
144 $input->attachFile($filepath);
|
Chris@0
|
145
|
Chris@0
|
146 // Trigger the upload logic with a mock "drop" event.
|
Chris@0
|
147 $script = 'var e = jQuery.Event("drop");'
|
Chris@0
|
148 . 'e.originalEvent = {dataTransfer: {files: jQuery("#quickedit-image-test-input").get(0).files}};'
|
Chris@0
|
149 . 'e.preventDefault = e.stopPropagation = function () {};'
|
Chris@0
|
150 . 'jQuery(".quickedit-image-dropzone").trigger(e);';
|
Chris@0
|
151 $this->getSession()->executeScript($script);
|
Chris@0
|
152
|
Chris@0
|
153 // Wait for the dropzone element to be removed (i.e. loading is done).
|
Chris@0
|
154 $condition = "jQuery('" . $field_selector . " .quickedit-image-dropzone').length == 0";
|
Chris@0
|
155 $this->assertJsCondition($condition, 20000);
|
Chris@0
|
156
|
Chris@0
|
157 // To prevent 403s on save, we re-set our request (cookie) state.
|
Chris@0
|
158 $this->prepareRequest();
|
Chris@0
|
159
|
Chris@0
|
160 // Save the change.
|
Chris@0
|
161 $this->click('.quickedit-button.action-save');
|
Chris@0
|
162 $this->assertSession()->assertWaitOnAjaxRequest();
|
Chris@0
|
163
|
Chris@0
|
164 // Re-visit the page to make sure the edit worked.
|
Chris@0
|
165 $this->drupalGet('node/' . $node->id());
|
Chris@0
|
166
|
Chris@0
|
167 // Check that the new image appears as expected.
|
Chris@0
|
168 $this->assertSession()->elementNotExists('css', $entity_selector . ' ' . $field_selector . ' ' . $original_image_selector);
|
Chris@0
|
169 $this->assertSession()->elementExists('css', $entity_selector . ' ' . $field_selector . ' ' . $new_image_selector);
|
Chris@0
|
170 }
|
Chris@0
|
171
|
Chris@0
|
172 }
|