Chris@0: drupalCreateContentType(['type' => 'article', 'name' => 'Article']); Chris@0: Chris@0: // Log in as a content author who can use Quick Edit and edit Articles. Chris@0: $this->contentAuthorUser = $this->drupalCreateUser([ Chris@0: 'access contextual links', Chris@0: 'access toolbar', Chris@0: 'access in-place editing', Chris@0: 'access content', Chris@0: 'create article content', Chris@0: 'edit any article content', Chris@0: 'delete any article content', Chris@0: ]); Chris@0: $this->drupalLogin($this->contentAuthorUser); Chris@0: } Chris@0: Chris@0: /** Chris@17: * Test that quick editor works correctly with images. Chris@17: * Chris@17: * @covers ::isCompatible Chris@17: * @covers ::getAttachments Chris@0: */ Chris@17: public function testImageInPlaceEditor() { Chris@0: // Create a field with a basic filetype restriction. Chris@0: $field_name = strtolower($this->randomMachineName()); Chris@0: $field_settings = [ Chris@0: 'file_extensions' => 'png', Chris@0: ]; Chris@0: $formatter_settings = [ Chris@0: 'image_style' => 'large', Chris@0: 'image_link' => '', Chris@0: ]; Chris@0: $this->createImageField($field_name, 'article', [], $field_settings, [], $formatter_settings); Chris@0: Chris@0: // Find images that match our field settings. Chris@0: $valid_images = []; Chris@0: foreach ($this->getTestFiles('image') as $image) { Chris@0: // This regex is taken from file_validate_extensions(). Chris@0: $regex = '/\.(' . preg_replace('/ +/', '|', preg_quote($field_settings['file_extensions'])) . ')$/i'; Chris@0: if (preg_match($regex, $image->filename)) { Chris@0: $valid_images[] = $image; Chris@0: } Chris@0: } Chris@0: Chris@0: // Ensure we have at least two valid images. Chris@0: $this->assertGreaterThanOrEqual(2, count($valid_images)); Chris@0: Chris@0: // Create a File entity for the initial image. Chris@0: $file = File::create([ Chris@0: 'uri' => $valid_images[0]->uri, Chris@0: 'uid' => $this->contentAuthorUser->id(), Chris@0: 'status' => FILE_STATUS_PERMANENT, Chris@0: ]); Chris@0: $file->save(); Chris@0: Chris@0: // Use the first valid image to create a new Node. Chris@0: $image_factory = $this->container->get('image.factory'); Chris@0: $image = $image_factory->get($valid_images[0]->uri); Chris@0: $node = $this->drupalCreateNode([ Chris@0: 'type' => 'article', Chris@0: 'title' => t('Test Node'), Chris@0: $field_name => [ Chris@0: 'target_id' => $file->id(), Chris@0: 'alt' => 'Hello world', Chris@0: 'title' => '', Chris@0: 'width' => $image->getWidth(), Chris@0: 'height' => $image->getHeight(), Chris@0: ], Chris@0: ]); Chris@0: Chris@0: // Visit the new Node. Chris@0: $this->drupalGet('node/' . $node->id()); Chris@0: Chris@0: // Assemble common CSS selectors. Chris@0: $entity_selector = '[data-quickedit-entity-id="node/' . $node->id() . '"]'; Chris@0: $field_selector = '[data-quickedit-field-id="node/' . $node->id() . '/' . $field_name . '/' . $node->language()->getId() . '/full"]'; Chris@0: $original_image_selector = 'img[src*="' . $valid_images[0]->filename . '"][alt="Hello world"]'; Chris@0: $new_image_selector = 'img[src*="' . $valid_images[1]->filename . '"][alt="New text"]'; Chris@0: Chris@0: // Assert that the initial image is present. Chris@0: $this->assertSession()->elementExists('css', $entity_selector . ' ' . $field_selector . ' ' . $original_image_selector); Chris@0: Chris@17: // Initial state. Chris@17: $this->awaitQuickEditForEntity('node', 1); Chris@17: $this->assertEntityInstanceStates([ Chris@17: 'node/1[0]' => 'closed', Chris@17: ]); Chris@17: $this->assertEntityInstanceFieldStates('node', 1, 0, [ Chris@17: 'node/1/title/en/full' => 'inactive', Chris@17: 'node/1/uid/en/full' => 'inactive', Chris@17: 'node/1/created/en/full' => 'inactive', Chris@17: 'node/1/body/en/full' => 'inactive', Chris@17: 'node/1/' . $field_name . '/en/full' => 'inactive', Chris@17: ]); Chris@0: Chris@17: // Start in-place editing of the article node. Chris@17: $this->startQuickEditViaToolbar('node', 1, 0); Chris@17: $this->assertEntityInstanceStates([ Chris@17: 'node/1[0]' => 'opened', Chris@17: ]); Chris@17: $this->assertQuickEditEntityToolbar((string) $node->label(), NULL); Chris@17: $this->assertEntityInstanceFieldStates('node', 1, 0, [ Chris@17: 'node/1/title/en/full' => 'candidate', Chris@17: 'node/1/uid/en/full' => 'candidate', Chris@17: 'node/1/created/en/full' => 'candidate', Chris@17: 'node/1/body/en/full' => 'candidate', Chris@17: 'node/1/' . $field_name . '/en/full' => 'candidate', Chris@17: ]); Chris@17: Chris@17: // Click the image field. Chris@0: $this->click($field_selector); Chris@17: $this->awaitImageEditor(); Chris@17: $this->assertSession()->elementExists('css', $field_selector . ' .quickedit-image-dropzone'); Chris@17: $this->assertEntityInstanceFieldStates('node', 1, 0, [ Chris@17: 'node/1/title/en/full' => 'candidate', Chris@17: 'node/1/uid/en/full' => 'candidate', Chris@17: 'node/1/created/en/full' => 'candidate', Chris@17: 'node/1/body/en/full' => 'candidate', Chris@17: 'node/1/' . $field_name . '/en/full' => 'active', Chris@17: ]); Chris@0: Chris@17: // Type new 'alt' text. Chris@17: $this->typeInImageEditorAltTextInput('New text'); Chris@17: $this->assertEntityInstanceFieldStates('node', 1, 0, [ Chris@17: 'node/1/title/en/full' => 'candidate', Chris@17: 'node/1/uid/en/full' => 'candidate', Chris@17: 'node/1/created/en/full' => 'candidate', Chris@17: 'node/1/body/en/full' => 'candidate', Chris@17: 'node/1/' . $field_name . '/en/full' => 'changed', Chris@17: ]); Chris@0: Chris@17: // Drag and drop an image. Chris@17: $this->dropImageOnImageEditor($valid_images[1]->uri); Chris@0: Chris@0: // To prevent 403s on save, we re-set our request (cookie) state. Chris@0: $this->prepareRequest(); Chris@0: Chris@17: // Click 'Save'. Chris@17: $this->saveQuickEdit(); Chris@17: $this->assertEntityInstanceStates([ Chris@17: 'node/1[0]' => 'committing', Chris@17: ]); Chris@17: $this->assertEntityInstanceFieldStates('node', 1, 0, [ Chris@17: 'node/1/title/en/full' => 'candidate', Chris@17: 'node/1/uid/en/full' => 'candidate', Chris@17: 'node/1/created/en/full' => 'candidate', Chris@17: 'node/1/body/en/full' => 'candidate', Chris@17: 'node/1/' . $field_name . '/en/full' => 'saving', Chris@17: ]); Chris@17: $this->assertEntityInstanceFieldMarkup('node', 1, 0, [ Chris@17: 'node/1/' . $field_name . '/en/full' => '.quickedit-changed', Chris@17: ]); Chris@17: Chris@17: // Wait for the saving of the image field to complete. Chris@17: $this->assertJsCondition("Drupal.quickedit.collections.entities.get('node/1[0]').get('state') === 'closed'"); Chris@17: $this->assertEntityInstanceStates([ Chris@17: 'node/1[0]' => 'closed', Chris@17: ]); Chris@0: Chris@0: // Re-visit the page to make sure the edit worked. Chris@0: $this->drupalGet('node/' . $node->id()); Chris@0: Chris@0: // Check that the new image appears as expected. Chris@0: $this->assertSession()->elementNotExists('css', $entity_selector . ' ' . $field_selector . ' ' . $original_image_selector); Chris@0: $this->assertSession()->elementExists('css', $entity_selector . ' ' . $field_selector . ' ' . $new_image_selector); Chris@0: } Chris@0: Chris@0: }