Commit 7b0afe89 authored by catch's avatar catch
Browse files

Issue #3364088 by lauriii, tim.plunkett, anup.singh, olli: Ajax state leaking...

Issue #3364088 by lauriii, tim.plunkett, anup.singh, olli: Ajax state leaking to Views destination paths

(cherry picked from commit 710278cc)
parent bbd518ba
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ public function getQueryParameters() {
    $request = $this->requestStack->getCurrentRequest();
    if ($request) {
      return UrlHelper::filterQueryParameters(
        $request->query->all(), ['page']
        $request->query->all(), ['page', 'ajax_page_state']
      );
    }
    return [];
+9 −5
Original line number Diff line number Diff line
@@ -162,17 +162,21 @@ public function ajaxView(Request $request) {
          $this->currentPath->setPath('/' . ltrim($path, '/'), $request);
        }

        // Create a clone of the request object to avoid mutating the request
        // object stored in the request stack.
        $request_clone = clone $request;

        // Add all POST data, because AJAX is sometimes a POST and many things,
        // such as tablesorts, exposed filters and paging assume GET.
        $request_all = $request->request->all();
        $query_all = $request->query->all();
        $request->query->replace($request_all + $query_all);
        $param_union = $request_clone->request->all() + $request_clone->query->all();
        unset($param_union['ajax_page_state']);
        $request_clone->query->replace($param_union);

        // Overwrite the destination.
        // @see the redirect.destination service.
        $origin_destination = $path;
        $origin_destination = $request_clone->getBasePath() . '/' . ltrim($path ?? '/', '/');

        $used_query_parameters = $request->query->all();
        $used_query_parameters = $request_clone->query->all();
        $query = UrlHelper::buildQuery($used_query_parameters);
        if ($query != '') {
          $origin_destination .= '?' . $query;
+1 −1
Original line number Diff line number Diff line
@@ -705,7 +705,7 @@ public function getExposedInput() {

      $this->exposed_input = \Drupal::request()->query->all();
      // unset items that are definitely not our input:
      foreach (['page', 'q'] as $key) {
      foreach (['page', 'q', 'ajax_page_state'] as $key) {
        if (isset($this->exposed_input[$key])) {
          unset($this->exposed_input[$key]);
        }
+3 −0
Original line number Diff line number Diff line
@@ -100,6 +100,9 @@ public function testBasicPagination() {
    $link = $page->findLink('Go to page 3');
    $this->assertNoDuplicateAssetsOnPage();

    // Test that no unwanted parameters are added to the URL.
    $this->assertEquals('?status=All&type=All&langcode=All&items_per_page=5&order=changed&sort=asc&page=2', $link->getAttribute('href'));

    $this->clickLink('Go to page 3');
    $session_assert->assertWaitOnAjaxRequest();
    $rows = $page->findAll('css', 'tbody tr');
+76 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\views\FunctionalJavascript;

use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
use Drupal\Tests\node\Traits\NodeCreationTrait;

/**
 * Tests that the redirects work with Ajax enabled views.
 *
 * @group views
 */
class RedirectAjaxTest extends WebDriverTestBase {

  use ContentTypeCreationTrait;
  use NodeCreationTrait;

  /**
   * {@inheritdoc}
   */
  protected static $modules = ['node', 'views'];

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();

    // Enable AJAX on the /admin/content View.
    \Drupal::configFactory()->getEditable('views.view.content')
      ->set('display.default.display_options.use_ajax', TRUE)
      ->save();

    $this->createContentType(['type' => 'article']);
    $this->createNode(['title' => 'Tiny paws and playful mews, kittens bring joy in every hue', 'type' => 'article']);

    $user = $this->drupalCreateUser([
      'access content overview',
      'administer nodes',
      'bypass node access',
    ]);
    $this->drupalLogin($user);
  }

  /**
   * Ensures that redirects work with ajax.
   */
  public function testRedirectWithAjax() {
    $this->drupalGet('admin/content');
    $original_url = $this->getSession()->getCurrentUrl();

    $this->assertSession()->pageTextContains('Tiny paws and playful mews, kittens bring joy in every hue');

    $this->submitForm(['title' => 'Kittens'], 'Filter');
    $this->assertSession()->assertWaitOnAjaxRequest();

    $this->assertSession()->pageTextContains('Tiny paws and playful mews, kittens bring joy in every hue');
    $this->getSession()->getPage()->find('css', '.dropbutton-toggle button')->click();
    $this->clickLink('Delete');
    $this->assertSession()->assertWaitOnAjaxRequest();

    $this->assertEquals('Are you sure you want to delete the content item Tiny paws and playful mews, kittens bring joy in every hue?', $this->assertSession()->waitForElement('css', '.ui-dialog-title')->getText());
    $this->getSession()->getPage()->find('css', '.ui-dialog-buttonset')->pressButton('Delete');

    $this->assertSession()->pageTextContains('The Article Tiny paws and playful mews, kittens bring joy in every hue has been deleted.');
    $this->assertStringStartsWith($original_url, $this->getSession()->getCurrentUrl());
    $this->assertSession()->responseContains('core/modules/views/css/views.module.css');
  }

}
Loading