Commit 2871d43e authored by Gábor Hojtsy's avatar Gábor Hojtsy

Issue #2870458 by Lendude, jibran, alexpott, vijaycs85, Wim Leers, dawehner,...

Issue #2870458 by Lendude, jibran, alexpott, vijaycs85, Wim Leers, dawehner, larowlan: Convert web tests to browser tests for quickedit module

(cherry picked from commit a9745363)
parent 192f2267
<?php
namespace Drupal\Tests\quickedit\Functional;
use Drupal\Component\Serialization\Json;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Tests\BrowserTestBase;
/**
* Tests using a custom pipeline with Quick Edit.
*
* @group quickedit
*/
class QuickEditCustomPipelineTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'quickedit',
'quickedit_test',
'node',
];
/**
* Tests that Quick Edit works with custom render pipelines.
*/
public function testCustomPipeline() {
// Create a node type.
$this->drupalCreateContentType([
'type' => 'article',
'name' => 'Article',
]);
$node = $this->createNode(['type' => 'article']);
$editor_user = $this->drupalCreateUser([
'access content',
'create article content',
'edit any article content',
'access in-place editing',
]);
$this->drupalLogin($editor_user);
$custom_render_url = $this->buildUrl('quickedit/form/node/' . $node->id() . '/body/en/quickedit_test-custom-render-data');
$client = $this->getHttpClient();
$post = ['nocssjs' => 'true'];
$response = $client->post($custom_render_url, [
'body' => http_build_query($post),
'query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax'],
'cookies' => $this->getSessionCookies(),
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded',
],
'http_errors' => FALSE,
]);
$this->assertEquals(200, $response->getStatusCode());
$ajax_commands = Json::decode($response->getBody());
// Request editing to render results with the custom render pipeline.
// Prepare form values for submission. drupalPostAJAX() is not suitable for
// handling pages with JSON responses, so we need our own solution here.
$form_tokens_found = preg_match('/\sname="form_token" value="([^"]+)"/', $ajax_commands[0]['data'], $token_match) && preg_match('/\sname="form_build_id" value="([^"]+)"/', $ajax_commands[0]['data'], $build_id_match);
$this->assertTrue($form_tokens_found, 'Form tokens found in output.');
$post = [
'form_id' => 'quickedit_field_form',
'form_token' => $token_match[1],
'form_build_id' => $build_id_match[1],
'body[0][summary]' => '',
'body[0][value]' => '<p>Fine thanks.</p>',
'body[0][format]' => 'filtered_html',
'op' => t('Save'),
];
// Assume there is another field on this page, which doesn't use a custom
// render pipeline, but the default one, and it uses the "full" view mode.
$post += ['other_view_modes[]' => 'full'];
// Submit field form and check response. Should render with the custom
// render pipeline.
$response = $client->post($custom_render_url, [
'body' => http_build_query($post),
'query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax'],
'cookies' => $this->getSessionCookies(),
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded',
],
'http_errors' => FALSE,
]);
$ajax_commands = Json::decode($response->getBody());
$this->assertIdentical(1, count($ajax_commands), 'The field form HTTP request results in one AJAX command.');
$this->assertIdentical('quickeditFieldFormSaved', $ajax_commands[0]['command'], 'The first AJAX command is a quickeditFieldFormSaved command.');
$this->assertTrue(strpos($ajax_commands[0]['data'], 'Fine thanks.'), 'Form value saved and printed back.');
$this->assertTrue(strpos($ajax_commands[0]['data'], '<div class="quickedit-test-wrapper">') !== FALSE, 'Custom render pipeline used to render the value.');
$this->assertIdentical(array_keys($ajax_commands[0]['other_view_modes']), ['full'], 'Field was also rendered in the "full" view mode.');
$this->assertTrue(strpos($ajax_commands[0]['other_view_modes']['full'], 'Fine thanks.'), '"full" version of field contains the form value.');
}
}
<?php
namespace Drupal\Tests\quickedit\Functional;
use Drupal\Component\Serialization\Json;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Tests\BrowserTestBase;
use GuzzleHttp\RequestOptions;
/**
* Tests accessing the Quick Edit endpoints.
*
* @group quickedit
*/
class QuickEditEndPointAccessTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'quickedit',
'node',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalCreateContentType([
'type' => 'article',
'name' => 'Article',
]);
}
/**
* Tests that Quick Edit endpoints are protected from anonymous requests.
*/
public function testEndPointAccess() {
// Quick Edit's JavaScript would never hit these endpoints, but we need to
// make sure that malicious users aren't able to use any of the other
// endpoints either.
$url = $this->buildUrl('/quickedit/attachments');
$post = ['editors[0]' => 'form'];
$this->assertAccessIsBlocked($url, $post);
$node = $this->createNode(['type' => 'article']);
$url = $this->buildUrl('quickedit/form/node/' . $node->id() . '/body/en/full');
$post = ['nocssjs' => 'true'];
$this->assertAccessIsBlocked($url, $post);
$edit = [];
$edit['form_id'] = 'quickedit_field_form';
$edit['form_token'] = 'xIOzMjuc-PULKsRn_KxFn7xzNk5Bx7XKXLfQfw1qOnA';
$edit['form_build_id'] = 'form-kVmovBpyX-SJfTT5kY0pjTV35TV-znor--a64dEnMR8';
$edit['body[0][summary]'] = '';
$edit['body[0][value]'] = '<p>Malicious content.</p>';
$edit['body[0][format]'] = 'filtered_html';
$edit['op'] = t('Save');
$this->assertAccessIsBlocked($url, $edit);
$post = ['nocssjs' => 'true'];
$url = $this->buildUrl('quickedit/entity/node/' . $node->id());
$this->assertAccessIsBlocked($url, $post);
}
/**
* Asserts that access to the passed URL is blocked.
*
* @param string $url
* The URL to check.
* @param array $body
* The payload to send with the request.
*/
protected function assertAccessIsBlocked($url, array $body) {
$client = $this->getHttpClient();
$message = ['message' => "The 'access in-place editing' permission is required."];
$response = $client->post($url, [
RequestOptions::BODY => http_build_query($body),
RequestOptions::QUERY => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax'],
RequestOptions::COOKIES => $this->getSessionCookies(),
RequestOptions::HEADERS => [
'Accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded',
],
RequestOptions::HTTP_ERRORS => FALSE,
]);
$this->assertEquals(403, $response->getStatusCode());
$response_message = Json::decode($response->getBody());
$this->assertSame($message, $response_message);
}
}
<?php
namespace Drupal\quickedit\Tests;
namespace Drupal\Tests\quickedit\FunctionalJavascript;
use Drupal\Component\Serialization\Json;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\simpletest\WebTestBase;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;
use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
/**
......@@ -16,16 +15,21 @@
*
* @group quickedit
*/
class QuickEditAutocompleteTermTest extends WebTestBase {
class QuickEditAutocompleteTermTest extends WebDriverTestBase {
use EntityReferenceTestTrait;
use ContextualLinkClickTrait;
/**
* Modules to enable.
*
* @var array
* {@inheritdoc}
*/
public static $modules = ['node', 'taxonomy', 'quickedit'];
public static $modules = [
'node',
'taxonomy',
'quickedit',
'contextual',
'ckeditor',
];
/**
* Stores the node used for the tests.
......@@ -69,13 +73,15 @@ class QuickEditAutocompleteTermTest extends WebTestBase {
*/
protected $editorUser;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalCreateContentType([
'type' => 'article',
]);
// Create the vocabulary for the tag field.
$this->vocabulary = Vocabulary::create([
'name' => 'quickedit testing tags',
'vid' => 'quickedit_testing_tags',
......@@ -120,82 +126,65 @@ protected function setUp() {
$node[$this->fieldName][]['target_id'] = $this->term2->id();
$this->node = $this->drupalCreateNode($node);
$this->editorUser = $this->drupalCreateUser(['access content', 'create article content', 'edit any article content', 'access in-place editing']);
$this->editorUser = $this->drupalCreateUser([
'access content',
'create article content',
'edit any article content',
'administer nodes',
'access contextual links',
'access in-place editing',
]);
}
/**
* Tests Quick Edit autocomplete term behavior.
*/
public function testAutocompleteQuickEdit() {
$this->drupalLogin($this->editorUser);
$page = $this->getSession()->getPage();
$assert = $this->assertSession();
$quickedit_uri = 'quickedit/form/node/' . $this->node->id() . '/' . $this->fieldName . '/' . $this->node->language()->getId() . '/full';
$post = ['nocssjs' => 'true'] + $this->getAjaxPageStatePostData();
$response = $this->drupalPost($quickedit_uri, '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]);
$ajax_commands = Json::decode($response);
// Prepare form values for submission. drupalPostAJAX() is not suitable for
// handling pages with JSON responses, so we need our own solution here.
$form_tokens_found = preg_match('/\sname="form_token" value="([^"]+)"/', $ajax_commands[0]['data'], $token_match) && preg_match('/\sname="form_build_id" value="([^"]+)"/', $ajax_commands[0]['data'], $build_id_match);
$this->assertTrue($form_tokens_found, 'Form tokens found in output.');
if ($form_tokens_found) {
$post = [
'form_id' => 'quickedit_field_form',
'form_token' => $token_match[1],
'form_build_id' => $build_id_match[1],
$this->fieldName . '[target_id]' => implode(', ', [$this->term1->getName(), 'new term', $this->term2->getName()]),
'op' => t('Save'),
];
// Submit field form and check response. Should render back all the terms.
$response = $this->drupalPost($quickedit_uri, '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]);
$this->assertResponse(200);
$ajax_commands = Json::decode($response);
$this->setRawContent($ajax_commands[0]['data']);
$this->assertLink($this->term1->getName());
$this->assertLink($this->term2->getName());
$this->assertText('new term');
$this->assertNoLink('new term');
// Load the form again, which should now get it back from
// PrivateTempStore.
$quickedit_uri = 'quickedit/form/node/' . $this->node->id() . '/' . $this->fieldName . '/' . $this->node->language()->getId() . '/full';
$post = ['nocssjs' => 'true'] + $this->getAjaxPageStatePostData();
$response = $this->drupalPost($quickedit_uri, '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]);
$ajax_commands = Json::decode($response);
// The AjaxResponse's first command is an InsertCommand which contains
// the form to edit the taxonomy term field, it should contain all three
// taxonomy terms, including the one that has just been newly created and
// which is not yet stored.
$this->setRawContent($ajax_commands[0]['data']);
$expected = [
$this->term1->getName() . ' (' . $this->term1->id() . ')',
'new term',
$this->term2->getName() . ' (' . $this->term2->id() . ')',
];
$this->assertFieldByName($this->fieldName . '[target_id]', implode(', ', $expected));
// Save the entity.
$post = ['nocssjs' => 'true'];
$response = $this->drupalPostWithFormat('quickedit/entity/node/' . $this->node->id(), 'json', $post);
$this->assertResponse(200);
// The full node display should now link to all entities, with the new
// one created in the database as well.
$this->drupalGet('node/' . $this->node->id());
$this->assertLink($this->term1->getName());
$this->assertLink($this->term2->getName());
$this->assertLink('new term');
}
$this->drupalLogin($this->editorUser);
$this->drupalGet('node/' . $this->node->id());
// Wait "Quick edit" button for node.
$assert->waitForElement('css', '[data-quickedit-entity-id="node/' . $this->node->id() . '"] .contextual .quickedit');
// Click by "Quick edit".
$this->clickContextualLink('[data-quickedit-entity-id="node/' . $this->node->id() . '"]', 'Quick edit');
// Switch to body field.
$page->find('css', '[data-quickedit-field-id="node/' . $this->node->id() . '/' . $this->fieldName . '/' . $this->node->language()->getId() . '/full"]')->click();
// Open Quick Edit.
$quickedit_field_locator = '[name="field_quickedit_testing_tags[target_id]"]';
$tag_field = $assert->waitForElementVisible('css', $quickedit_field_locator);
$tag_field->focus();
$tags = $tag_field->getValue();
// Check existing terms.
$this->assertTrue(strpos($tags, $this->term1->label()) !== FALSE);
$this->assertTrue(strpos($tags, $this->term2->label()) !== FALSE);
// Add new term.
$new_tag = $this->randomMachineName();
$tags .= ', ' . $new_tag;
$assert->waitForElementVisible('css', $quickedit_field_locator)->setValue($tags);
$assert->waitOnAutocomplete();
// Wait and click by "Save" button after body field was changed.
$assert->waitForElementVisible('css', '.quickedit-toolgroup.ops [type="submit"][aria-hidden="false"]')->click();
$assert->waitOnAutocomplete();
// Reload the page and check new term.
$this->drupalGet('node/' . $this->node->id());
$link = $assert->waitForLink($new_tag);
$this->assertNotEmpty($link);
}
/**
* Returns a new term with random name and description in $this->vocabulary.
*
* @return \Drupal\taxonomy\TermInterface
* @return \Drupal\Core\Entity\EntityInterface|\Drupal\taxonomy\Entity\Term
* The created taxonomy term.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
protected function createTerm() {
$filter_formats = filter_formats();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment