'filtered_html', 'name' => 'Filtered HTML', 'weight' => 0, 'filters' => [], ]); $filtered_html_format->save(); // Create a node type. $this->drupalCreateContentType([ 'type' => 'article', 'name' => 'Article', ]); // Set the node type to initially not have revisions. // Testing with revisions will be done later. $node_type = NodeType::load('article'); $node_type->setNewRevision(FALSE); $node_type->save(); // Create one node of the above node type using the above text format. $this->testNode = $this->drupalCreateNode([ 'type' => 'article', 'body' => [ 0 => [ 'value' => '
How are you?
', 'format' => 'filtered_html', ], ], 'revision_log' => $this->randomString(), ]); // Create 2 users, the only difference being the ability to use in-place // editing $basic_permissions = ['access content', 'create article content', 'edit any article content', 'use text format filtered_html', 'access contextual links']; $this->authorUser = $this->drupalCreateUser($basic_permissions); $this->editorUser = $this->drupalCreateUser(array_merge($basic_permissions, ['access in-place editing'])); } /** * Test the loading of Quick Edit when a user doesn't have access to it. */ public function testUserWithoutPermission() { $this->drupalLogin($this->authorUser); $this->drupalGet('node/1'); // Library and in-place editors. $this->assertNoRaw('core/modules/quickedit/js/quickedit.js', 'Quick Edit library not loaded.'); $this->assertNoRaw('core/modules/quickedit/js/editors/formEditor.js', "'form' in-place editor not loaded."); // HTML annotation and title class does not exist for users without // permission to in-place edit. $this->assertNoRaw('data-quickedit-entity-id="node/1"'); $this->assertNoRaw('data-quickedit-field-id="node/1/body/en/full"'); $this->assertNoFieldByXPath('//h1[contains(@class, "js-quickedit-page-title")]'); // Retrieving the metadata should result in an empty 403 response. $post = ['fields[0]' => 'node/1/body/en/full']; $response = $this->drupalPostWithFormat(Url::fromRoute('quickedit.metadata'), 'json', $post); $this->assertIdentical(Json::encode(['message' => "The 'access in-place editing' permission is required."]), $response); $this->assertResponse(403); // Quick Edit's JavaScript would never hit these endpoints if the metadata // was empty as above, but we need to make sure that malicious users aren't // able to use any of the other endpoints either. $post = ['editors[0]' => 'form'] + $this->getAjaxPageStatePostData(); $response = $this->drupalPost('quickedit/attachments', '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]); $message = Json::encode(['message' => "The 'access in-place editing' permission is required."]); $this->assertIdentical($message, $response); $this->assertResponse(403); $post = ['nocssjs' => 'true'] + $this->getAjaxPageStatePostData(); $response = $this->drupalPost('quickedit/form/' . 'node/1/body/en/full', '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]); $this->assertIdentical($message, $response); $this->assertResponse(403); $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]'] = 'Malicious content.
'; $edit['body[0][format]'] = 'filtered_html'; $edit['op'] = t('Save'); $response = $this->drupalPost('quickedit/form/' . 'node/1/body/en/full', '', $edit, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]); $this->assertIdentical($message, $response); $this->assertResponse(403); $post = ['nocssjs' => 'true']; $response = $this->drupalPostWithFormat('quickedit/entity/' . 'node/1', 'json', $post); $this->assertIdentical(Json::encode(['message' => "The 'access in-place editing' permission is required."]), $response); $this->assertResponse(403); } /** * Tests the loading of Quick Edit when a user does have access to it. * * Also ensures lazy loading of in-place editors works. */ public function testUserWithPermission() { $this->drupalLogin($this->editorUser); $this->drupalGet('node/1'); // Library and in-place editors. $settings = $this->getDrupalSettings(); $libraries = explode(',', $settings['ajaxPageState']['libraries']); $this->assertTrue(in_array('quickedit/quickedit', $libraries), 'Quick Edit library loaded.'); $this->assertFalse(in_array('quickedit/quickedit.inPlaceEditor.form', $libraries), "'form' in-place editor not loaded."); // HTML annotation and title class must always exist (to not break the // render cache). $this->assertRaw('data-quickedit-entity-id="node/1"'); $this->assertRaw('data-quickedit-field-id="node/1/body/en/full"'); $this->assertFieldByXPath('//h1[contains(@class, "js-quickedit-page-title")]'); // There should be only one revision so far. $node = Node::load(1); $vids = \Drupal::entityManager()->getStorage('node')->revisionIds($node); $this->assertIdentical(1, count($vids), 'The node has only one revision.'); $original_log = $node->revision_log->value; // Retrieving the metadata should result in a 200 JSON response. $htmlPageDrupalSettings = $this->drupalSettings; $post = ['fields[0]' => 'node/1/body/en/full']; $response = $this->drupalPostWithFormat('quickedit/metadata', 'json', $post); $this->assertResponse(200); $expected = [ 'node/1/body/en/full' => [ 'label' => 'Body', 'access' => TRUE, 'editor' => 'form', ], ]; $this->assertIdentical(Json::decode($response), $expected, 'The metadata HTTP request answers with the correct JSON response.'); // Restore drupalSettings to build the next requests; simpletest wipes them // after a JSON response. $this->drupalSettings = $htmlPageDrupalSettings; // Retrieving the attachments should result in a 200 response, containing: // 1. a settings command with useless metadata: AjaxController is dumb // 2. an insert command that loads the required in-place editors $post = ['editors[0]' => 'form'] + $this->getAjaxPageStatePostData(); $response = $this->drupalPost('quickedit/attachments', '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]); $ajax_commands = Json::decode($response); $this->assertIdentical(2, count($ajax_commands), 'The attachments HTTP request results in two AJAX commands.'); // First command: settings. $this->assertIdentical('settings', $ajax_commands[0]['command'], 'The first AJAX command is a settings command.'); // Second command: insert libraries into DOM. $this->assertIdentical('insert', $ajax_commands[1]['command'], 'The second AJAX command is an append command.'); $this->assertTrue(in_array('quickedit/quickedit.inPlaceEditor.form', explode(',', $ajax_commands[0]['settings']['ajaxPageState']['libraries'])), 'The quickedit.inPlaceEditor.form library is loaded.'); // Retrieving the form for this field should result in a 200 response, // containing only a quickeditFieldForm command. $post = ['nocssjs' => 'true', 'reset' => 'true'] + $this->getAjaxPageStatePostData(); $response = $this->drupalPost('quickedit/form/' . 'node/1/body/en/full', '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]); $this->assertResponse(200); $ajax_commands = Json::decode($response); $this->assertIdentical(1, count($ajax_commands), 'The field form HTTP request results in one AJAX command.'); $this->assertIdentical('quickeditFieldForm', $ajax_commands[0]['command'], 'The first AJAX command is a quickeditFieldForm command.'); $this->assertIdentical('