Commit 362c6c0b authored by Andreas Hennings's avatar Andreas Hennings Committed by Andras Szilagyi
Browse files

Issue #3280015 by donquixote: Failing tests due to urlencode

parent 385bbe19
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\search_api\Entity\Index;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\facets\Functional\BlockTestTrait;
use Drupal\Tests\facets_form\Traits\FacetUrlTestTrait;
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
use Drupal\Tests\node\Traits\NodeCreationTrait;

@@ -20,6 +21,7 @@ class DateRangeIntegrationTest extends BrowserTestBase {

  use BlockTestTrait;
  use ContentTypeCreationTrait;
  use FacetUrlTestTrait;
  use NodeCreationTrait;

  /**
@@ -81,7 +83,7 @@ class DateRangeIntegrationTest extends BrowserTestBase {
    // Test greater or equals operator.
    $page->fillField('edit-authored-on-from-date', '2021-08-16');
    $form->pressButton('Search');
    $assert->addressEquals('test?f[0]=authored_on%3A2021-08-16~');
    $this->assertCurrentUrl('test', ['f' => ['authored_on:2021-08-16~']]);
    $assert->elementsCount('css', '.views-row', 1);
    $assert->pageTextNotContains('Llama');
    $assert->pageTextContains('Emu');
@@ -89,7 +91,7 @@ class DateRangeIntegrationTest extends BrowserTestBase {
    $page->fillField('edit-authored-on-from-date', '');
    $page->fillField('edit-authored-on-to-date', '2021-08-16');
    $form->pressButton('Search');
    $assert->addressEquals('test?f[0]=authored_on%3A~2021-08-16');
    $this->assertCurrentUrl('test', ['f' => ['authored_on:~2021-08-16']]);
    $assert->elementsCount('css', '.views-row', 1);
    $assert->pageTextContains('Llama');
    $assert->pageTextNotContains('Emu');
@@ -97,7 +99,7 @@ class DateRangeIntegrationTest extends BrowserTestBase {
    $page->fillField('edit-authored-on-from-date', '2021-08-16');
    $page->fillField('edit-authored-on-to-date', '2021-08-17');
    $form->pressButton('Search');
    $assert->addressEquals('test?f[0]=authored_on%3A2021-08-16~2021-08-17');
    $this->assertCurrentUrl('test', ['f' => ['authored_on:2021-08-16~2021-08-17']]);
    $assert->elementsCount('css', '.views-row', 1);
    $assert->pageTextNotContains('Llama');
    $assert->pageTextContains('Emu');
+24 −42
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ use Drupal\facets\Entity\Facet;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\facets\Functional\BlockTestTrait;
use Drupal\Tests\facets\Functional\ExampleContentTrait;
use Drupal\Tests\facets_form\Traits\FacetUrlTestTrait;

/**
 * Test the facets form.
@@ -18,6 +19,7 @@ class IntegrationTest extends BrowserTestBase {

  use ExampleContentTrait;
  use BlockTestTrait;
  use FacetUrlTestTrait;

  /**
   * {@inheritdoc}
@@ -81,12 +83,14 @@ class IntegrationTest extends BrowserTestBase {
    // The form submits and filters the results.
    $page->selectFieldOption('llama[]', 'article');
    $assert->buttonExists('Apply', $form)->press();
    $this->assertCurrentUrl('search-api-test-fulltext?f[0]=llama:article');
    $this->assertCurrentUrl('search-api-test-fulltext', ['f' => ['llama:article']]);
    $assert->elementsCount('css', '.views-row', 2);

    $page->selectFieldOption('llama[]', 'item');
    $assert->buttonExists('Apply', $form)->press();
    $this->assertCurrentUrl('search-api-test-fulltext?f[0]=llama:item');
    $this->assertCurrentUrl('search-api-test-fulltext', ['f' => ['llama:item']]);
    $assert->elementsCount('css', '.views-row', 3);

    $page->clickLink('Reset');
    $this->assertCurrentUrl('search-api-test-fulltext');
    $assert->elementsCount('css', '.views-row', 5);
@@ -104,23 +108,37 @@ class IntegrationTest extends BrowserTestBase {
    // Check form submit without any filter.
    $form->pressButton('Apply');
    // Check query string preservation when submitting with no filter changes.
    $this->assertCurrentUrl('search-api-test-fulltext?foo=bar&baz[]=qux&baz[]=quux');
    $this->assertCurrentUrl('search-api-test-fulltext', [
      'foo' => 'bar',
      'baz' => ['qux', 'quux'],
    ]);
    $form->checkField('item');
    $form->pressButton('Apply');
    // Check query string preservation after submitting with filter changes.
    $this->assertCurrentUrl('search-api-test-fulltext?baz[]=qux&baz[]=quux&f[0]=llama:item&foo=bar');
    $this->assertCurrentUrl('search-api-test-fulltext', [
      'foo' => 'bar',
      'baz' => ['qux', 'quux'],
      'f' => ['llama:item'],
    ]);
    $assert->checkboxChecked('item', $form);
    $assert->elementsCount('css', '.views-row', 3);
    $form->checkField('article');
    $form->pressButton('Apply');
    // Check query string preservation after submitting with filter changes.
    $this->assertCurrentUrl('search-api-test-fulltext?foo=bar&baz[]=qux&baz[]=quux&f[0]=llama:article&f[1]=llama:item');
    $this->assertCurrentUrl('search-api-test-fulltext', [
      'foo' => 'bar',
      'baz' => ['qux', 'quux'],
      'f' => ['llama:article', 'llama:item'],
    ]);
    $assert->checkboxChecked('item', $form);
    $assert->checkboxChecked('article', $form);
    $assert->elementsCount('css', '.views-row', 5);
    // Check query string preservation after resetting the filters.
    $page->clickLink('Reset');
    $this->assertCurrentUrl('search-api-test-fulltext?baz[]=qux&baz[]=quux&foo=bar');
    $this->assertCurrentUrl('search-api-test-fulltext', [
      'foo' => 'bar',
      'baz' => ['qux', 'quux'],
    ]);

    // Change configured facets.
    $this->createFacet('Alpaca', 'alpaca');
@@ -141,40 +159,4 @@ class IntegrationTest extends BrowserTestBase {
    $assert->elementNotExists('css', 'select#edit-emu--2', $form);
  }

  /**
   * Asserts that the current URL matches the expected one, including the query.
   *
   * Note that \Behat\Mink\WebAssert::addressEquals() strips out the query
   * string, comparing only the path and the fragment. But, in the scope of this
   * test, we need to also compare the query strings.
   *
   * @param \Drupal\Core\Url|string $expected_url
   *   The expected URL.
   *
   * @see \Behat\Mink\WebAssert::addressEquals()
   */
  protected function assertCurrentUrl(string $expected_url): void {
    // Check first the path & the fragment.
    $this->assertSession()->addressEquals($expected_url);
    // Compare also the query strings as arrays but allow different order.
    $expected_query = $this->normalizeQueryString($expected_url);
    $actual_query = $this->normalizeQueryString($this->getSession()->getCurrentUrl());
    $this->assertEquals($expected_query, $actual_query);
  }

  /**
   * Normalizes a given URL query string to an array.
   *
   * @param string $url
   *   The URL.
   *
   * @return array
   *   The array representation of the query string.
   */
  protected function normalizeQueryString(string $url): array {
    $query_string = (string) parse_url($url, PHP_URL_QUERY);
    parse_str($query_string, $query_array);
    return $query_array;
  }

}
+22 −9
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ use Drupal\facets\Entity\Facet;
use Drupal\search_api\Item\Field;
use Drupal\taxonomy\Entity\Term;
use Drupal\Tests\facets\Functional\FacetsTestBase;
use Drupal\Tests\facets_form\Traits\FacetUrlTestTrait;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait;

@@ -21,6 +22,7 @@ use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait;
class SortingFacetIntegrationTest extends FacetsTestBase {

  use EntityReferenceTestTrait;
  use FacetUrlTestTrait;
  use TaxonomyTestTrait;

  /**
@@ -174,6 +176,9 @@ class SortingFacetIntegrationTest extends FacetsTestBase {
    $this->drupalGet('search-api-test-fulltext');
    $form->checkField('Parent 2');
    $form->pressButton('Search');
    $this->assertCurrentUrl('search-api-test-fulltext', [
      'f' => ['hierarchical_facet:' . $this->parents['Parent 2']->id()],
    ]);
    $this->responseContentHasOrder([
      'Parent 1', 'Child 1',
      'Child 2', 'Parent 2',
@@ -198,10 +203,12 @@ class SortingFacetIntegrationTest extends FacetsTestBase {
    $this->submitForm($edit, 'Save');
    $this->drupalGet('search-api-test-fulltext');
    $form = $assert->elementExists('css', 'form#facets-form');
    $form->checkField($this->parents['Parent 2']->id());
    $form->checkField('Parent 2');
    $form->pressButton('Search');
    $assert->addressEquals('search-api-test-fulltext?f[0]=hierarchical_facet:' . $this->parents['Parent 2']->id());
    $assert->checkboxChecked($this->parents['Parent 2']->id());
    $this->assertCurrentUrl('search-api-test-fulltext', [
      'f' => ['hierarchical_facet:' . $this->parents['Parent 2']->id()],
    ]);
    $assert->checkboxChecked('Parent 2');
    $assert->elementsCount('css', '.views-row', 1);
    $this->responseContentHasOrder([
      'Parent 1', 'Child 1',
@@ -224,10 +231,12 @@ class SortingFacetIntegrationTest extends FacetsTestBase {
    $this->drupalGet($this->facetEditPage);
    $this->submitForm($edit, 'Save');
    $this->drupalGet('search-api-test-fulltext');
    $form->checkField($this->parents['Parent 1']->id());
    $form->uncheckField($this->parents['Parent 2']->id());
    $form->checkField('Parent 1');
    $form->uncheckField('Parent 2');
    $form->pressButton('Search');
    $assert->addressEquals('search-api-test-fulltext?f[0]=hierarchical_facet:2&f[1]=hierarchical_facet:1');
    $this->assertCurrentUrl('search-api-test-fulltext', [
      'f' => ['hierarchical_facet:' . $this->parents['Parent 1']->id()],
    ]);
    $assert->elementsCount('css', '.views-row', 1);
    $this->responseContentHasOrder([
      'Parent 1', 'Child 1',
@@ -235,7 +244,7 @@ class SortingFacetIntegrationTest extends FacetsTestBase {
      'Child 3', 'Child 4',
    ]);
    $page->clickLink('Clear filters');
    $assert->addressNotEquals('f[0]=hierarchical_facet');
    $this->assertCurrentUrl('search-api-test-fulltext');
    $assert->elementsCount('css', '.views-row', 6);
  }

@@ -359,7 +368,9 @@ class SortingFacetIntegrationTest extends FacetsTestBase {
    $form = $assert->elementExists('css', 'form#facets-form');
    $form->selectFieldOption('hierarchical_facet[]', 'Parent 2');
    $form->pressButton('Search');
    $assert->addressEquals('search-api-test-fulltext?f[0]=hierarchical_facet:' . $this->parents['Parent 2']->id());
    $this->assertCurrentUrl('search-api-test-fulltext', [
      'f' => ['hierarchical_facet:' . $this->parents['Parent 2']->id()],
    ]);
    $assert->elementsCount('css', '.views-row', 1);
    $this->responseContentHasOrder([
      'Parent 1', '- Child 1',
@@ -384,7 +395,9 @@ class SortingFacetIntegrationTest extends FacetsTestBase {
    $this->drupalGet('search-api-test-fulltext');
    $form->selectFieldOption('hierarchical_facet[]', 'Parent 1');
    $form->pressButton('Search');
    $assert->addressEquals('search-api-test-fulltext?f[0]=hierarchical_facet:2&f[1]=hierarchical_facet:1');
    $this->assertCurrentUrl('search-api-test-fulltext', [
      'f' => ['hierarchical_facet:' . $this->parents['Parent 1']->id()],
    ]);
    $assert->elementsCount('css', '.views-row', 1);
    $this->responseContentHasOrder([
      'Parent 1', '- Child 1',
+74 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\Tests\facets_form\Traits;

use Symfony\Component\Yaml\Yaml;

/**
 * Helper methods to test urls with facet filters.
 */
trait FacetUrlTestTrait {

  /**
   * Asserts that the current URL matches the expected one, including the query.
   *
   * We use this instead of \Behat\Mink\WebAssert::addressEquals() because:
   * - In Drupal < 9.3, WebAssert::addressEquals() ignores the query string.
   *   This would make most of the assertions useless.
   *   See https://www.drupal.org/node/3164686.
   * - Since Drupal 9.3, WebAssert::addressEquals() ignores the query string, if
   *   the expected url does not have one.
   * - The diff output from WebAssert::addressEquals() is harder to read than
   *   ours, because the url is a single line and contains noise from urlencode.
   * - Low-level string operations are more predictable than \Drupal\core\Url.
   *
   * @param string $path
   *   The expected url path.
   *   If the path contains a query part, it will be merged with $query.
   * @param array $query
   *   Expected url query.
   *
   * @see \Behat\Mink\WebAssert::addressEquals()
   */
  protected function assertCurrentUrl(string $path, array $query = []): void {
    $current_uri = str_replace(
      $this->baseUrl . '/',
      '',
      $this->getSession()->getCurrentUrl(),
    );
    $this->assertSame(
      $this->formatUrlForDiff($path, $query),
      $this->formatUrlForDiff($current_uri),
    );
  }

  /**
   * Produces a diff-friendly string from a url.
   *
   * @param string $uri
   *   Uri or path.
   *   If the uri contains a query part, it will be merged with $query.
   * @param array $query
   *   (optional) Url query parameters.
   *
   * @return string
   *   A diff-friendly string.
   */
  protected function formatUrlForDiff(string $uri, array $query = []): string {
    $parts = parse_url($uri);
    if (isset($parts['query'])) {
      parse_str($parts['query'], $uri_query);
      // Merge query from $uri with the query from $query.
      $query = $uri_query + $query;
    }
    if ($query) {
      // Use array query to get a multi-line diff.
      $parts['query'] = $query;
    }
    // Use yaml to make the diff more readable.
    return Yaml::dump($parts, 10, 2);
  }

}
+2 −2
Original line number Diff line number Diff line
@@ -29,8 +29,8 @@ trait FacetsFormWidgetTestTrait {
  protected function getResults(FacetInterface $facet, array $data, array $active = []): array {
    $results = [];
    foreach ($data as $value => $children) {
      $display_value = str_replace(['1', '2', '3'], ['One', 'Two', 'Three'], $value);
      $count = (int) str_replace('.', '', $value);
      $display_value = str_replace(['1', '2', '3'], ['One', 'Two', 'Three'], (string) $value);
      $count = (int) str_replace('.', '', (string) $value);
      $result = new Result($facet, $value, $display_value, $count);
      $result->setUrl(Url::fromUri("http://example.com/{$value}"));
      if (in_array($value, $active)) {