Verified Commit 46eed9dd authored by godotislate's avatar godotislate
Browse files

test: #3583187 [random test failure] DuplicateContextualLinksTest::testSameContextualLinks

By: amateescu
By: smustgrave
By: godotislate
(cherry picked from commit cf83b856)
parent d05c9c0f
Loading
Loading
Loading
Loading
Loading
+0 −327
Original line number Diff line number Diff line
langcode: en
status: true
dependencies:
  module:
    - node
    - user
id: contextual_recent
label: 'Recent content'
module: node
description: 'Recent content.'
tag: default
base_table: node_field_data
base_field: nid
display:
  default:
    id: default
    display_title: Default
    display_plugin: default
    position: 0
    display_options:
      title: 'Recent content'
      fields:
        title:
          id: title
          table: node_field_data
          field: title
          relationship: none
          group_type: group
          admin_label: ''
          entity_type: node
          entity_field: title
          plugin_id: field
          label: ''
          exclude: false
          alter:
            alter_text: false
            make_link: false
            absolute: false
            word_boundary: false
            ellipsis: false
            strip_tags: false
            trim: false
            html: false
          element_type: ''
          element_class: ''
          element_label_type: ''
          element_label_class: ''
          element_label_colon: false
          element_wrapper_type: ''
          element_wrapper_class: ''
          element_default_classes: true
          empty: ''
          hide_empty: false
          empty_zero: false
          hide_alter_empty: true
          type: string
          settings:
            link_to_entity: true
        changed:
          id: changed
          table: node_field_data
          field: changed
          relationship: none
          group_type: group
          admin_label: ''
          entity_type: node
          entity_field: changed
          plugin_id: field
          label: ''
          exclude: false
          alter:
            alter_text: false
            text: ''
            make_link: false
            path: ''
            absolute: false
            external: false
            replace_spaces: false
            path_case: none
            trim_whitespace: false
            alt: ''
            rel: ''
            link_class: ''
            prefix: ''
            suffix: ''
            target: ''
            nl2br: false
            max_length: 0
            word_boundary: true
            ellipsis: true
            more_link: false
            more_link_text: ''
            more_link_path: ''
            strip_tags: false
            trim: false
            preserve_tags: ''
            html: false
          element_type: ''
          element_class: ''
          element_label_type: ''
          element_label_class: ''
          element_label_colon: false
          element_wrapper_type: ''
          element_wrapper_class: ''
          element_default_classes: true
          empty: ''
          hide_empty: false
          empty_zero: false
          hide_alter_empty: true
          click_sort_column: value
          type: timestamp_ago
          settings: {  }
          group_column: value
          group_columns: {  }
          group_rows: true
          delta_limit: 0
          delta_offset: 0
          delta_reversed: false
          delta_first_last: false
          multi_type: separator
          separator: ', '
          field_api_classes: false
      pager:
        type: some
        options:
          offset: 0
          items_per_page: 10
      exposed_form:
        type: basic
        options:
          submit_button: Apply
          reset_button: false
          reset_button_label: Reset
          exposed_sorts_label: 'Sort by'
          expose_sort_order: true
          sort_asc_label: Asc
          sort_desc_label: Desc
      access:
        type: perm
        options:
          perm: 'access content'
      cache:
        type: tag
        options: {  }
      empty:
        area_text_custom:
          id: area_text_custom
          table: views
          field: area_text_custom
          relationship: none
          group_type: group
          admin_label: ''
          plugin_id: text_custom
          empty: true
          content: 'No content available.'
          tokenize: false
      sorts:
        changed:
          id: changed
          table: node_field_data
          field: changed
          relationship: none
          group_type: group
          admin_label: ''
          entity_type: node
          entity_field: changed
          plugin_id: date
          order: DESC
          expose:
            label: ''
          exposed: false
          granularity: second
      arguments: {  }
      filters:
        status_extra:
          id: status_extra
          table: node_field_data
          field: status_extra
          relationship: none
          group_type: group
          admin_label: ''
          entity_type: node
          plugin_id: node_status
          operator: '='
          value: false
          group: 1
          exposed: false
          expose:
            operator_id: ''
            label: ''
            description: ''
            use_operator: false
            operator: ''
            operator_limit_selection: false
            operator_list: {  }
            identifier: ''
            required: false
            remember: false
            multiple: false
            remember_roles:
              authenticated: authenticated
          is_grouped: false
          group_info:
            label: ''
            description: ''
            identifier: ''
            optional: true
            widget: select
            multiple: false
            remember: false
            default_group: All
            default_group_multiple: {  }
            group_items: {  }
        langcode:
          id: langcode
          table: node_field_data
          field: langcode
          relationship: none
          group_type: group
          admin_label: ''
          entity_type: node
          entity_field: langcode
          plugin_id: language
          operator: in
          value:
            '***LANGUAGE_language_content***': '***LANGUAGE_language_content***'
          group: 1
          exposed: false
          expose:
            operator_id: ''
            label: ''
            description: ''
            use_operator: false
            operator: ''
            operator_limit_selection: false
            operator_list: {  }
            identifier: ''
            required: false
            remember: false
            multiple: false
            remember_roles:
              authenticated: authenticated
            reduce: false
          is_grouped: false
          group_info:
            label: ''
            description: ''
            identifier: ''
            optional: true
            widget: select
            multiple: false
            remember: false
            default_group: All
            default_group_multiple: {  }
            group_items: {  }
      style:
        type: html_list
        options:
          grouping: {  }
          row_class: ''
          default_row_class: true
          type: ul
          wrapper_class: item-list
          class: ''
      row:
        type: fields
      query:
        type: views_query
        options:
          query_comment: ''
          disable_sql_rewrite: false
          distinct: false
          replica: false
          query_tags: {  }
      relationships:
        uid:
          id: uid
          table: node_field_data
          field: uid
          relationship: none
          group_type: group
          admin_label: author
          entity_type: node
          entity_field: uid
          plugin_id: standard
          required: true
      use_more: false
      use_more_always: false
      use_more_text: More
      link_display: '0'
      link_url: ''
      header: {  }
      footer: {  }
      display_extenders: {  }
    cache_metadata:
      max-age: -1
      contexts:
        - 'languages:language_content'
        - 'languages:language_interface'
        - user
        - 'user.node_grants:view'
        - user.permissions
      tags: {  }
  block_1:
    id: block_1
    display_title: Block
    display_plugin: block
    position: 2
    display_options:
      row:
        type: 'entity:node'
        options:
          relationship: none
          view_mode: teaser
      defaults:
        style: false
        row: false
      display_extenders: {  }
    cache_metadata:
      max-age: -1
      contexts:
        - 'languages:language_content'
        - 'languages:language_interface'
        - user
        - 'user.node_grants:view'
        - user.permissions
      tags: {  }
+7 −0
Original line number Diff line number Diff line
@@ -4,3 +4,10 @@ contextual_test:
    _controller: '\Drupal\contextual_test\Controller\TestController::render'
  requirements:
    _access: 'TRUE'

contextual_test.duplicate_links:
  path: '/contextual-tests/duplicate-links'
  defaults:
    _controller: '\Drupal\contextual_test\Controller\TestController::duplicateContextualLinks'
  requirements:
    _access: 'TRUE'
+35 −1
Original line number Diff line number Diff line
@@ -4,10 +4,20 @@

namespace Drupal\contextual_test\Controller;

use Drupal\contextual\ContextualLinksSerializer;
use Drupal\Core\DependencyInjection\AutowireTrait;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;

/**
 * Test controller to provide a callback for the contextual link.
 */
class TestController {
class TestController implements ContainerInjectionInterface {

  use AutowireTrait;

  public function __construct(
    protected readonly ContextualLinksSerializer $serializer,
  ) {}

  /**
   * Callback for the contextual link.
@@ -22,4 +32,28 @@ public function render() {
    ];
  }

  /**
   * Renders two regions with the same contextual links.
   */
  public function duplicateContextualLinks(): array {
    $contextual_id = $this->serializer->linksToId([
      'contextual_test' => ['route_parameters' => []],
    ]);
    $build = [];
    foreach (['first', 'second'] as $id) {
      $build[$id] = [
        '#type' => 'inline_template',
        '#template' => '<div id="region-{{ id }}" class="contextual-region">{{ placeholder }}Region {{ id }}</div>',
        '#context' => [
          'id' => $id,
          'placeholder' => [
            '#type' => 'contextual_links_placeholder',
            '#id' => $contextual_id,
          ],
        ],
      ];
    }
    return $build;
  }

}
+18 −22
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;

/**
 * Tests the UI for correct contextual links.
 * Tests that duplicate contextual links are initialized independently.
 */
#[Group('contextual')]
#[RunTestsInSeparateProcesses]
@@ -19,11 +19,6 @@ class DuplicateContextualLinksTest extends WebDriverTestBase {
   * {@inheritdoc}
   */
  protected static $modules = [
    'block',
    'contextual',
    'node',
    'views',
    'views_ui',
    'contextual_test',
  ];

@@ -33,29 +28,30 @@ class DuplicateContextualLinksTest extends WebDriverTestBase {
  protected $defaultTheme = 'stark';

  /**
   * Tests the contextual links with same id.
   * Tests that duplicate contextual links each get their own model view.
   */
  public function testSameContextualLinks(): void {
    $this->drupalPlaceBlock('views_block:contextual_recent-block_1', ['id' => 'first']);
    $this->drupalPlaceBlock('views_block:contextual_recent-block_1', ['id' => 'second']);
    $this->drupalCreateContentType(['type' => 'page']);
    $this->drupalCreateNode();
    $this->drupalLogin($this->drupalCreateUser([
      'access content',
      'access contextual links',
      'administer nodes',
      'administer blocks',
      'administer views',
      'edit any page content',
    ]));
    // Ensure same contextual links work correct with fresh and cached page.

    // Ensure same contextual links work correctly with fresh and cached page.
    $contextual_id = '[data-contextual-id^="contextual_test"]';
    foreach (['fresh', 'cached'] as $state) {
      $this->drupalGet('user');
      $contextual_id = '[data-contextual-id^="node:node=1"]';
      $this->drupalGet('contextual-tests/duplicate-links');
      $this->assertJsCondition("(typeof jQuery !== 'undefined' && jQuery('[data-contextual-id]:empty').length === 0)");
      $this->getSession()->executeScript("jQuery('#block-first $contextual_id .trigger').trigger('click');");
      $contextual_links = $this->assertSession()->waitForElementVisible('css', "#block-first $contextual_id .contextual-links");
      $this->assertTrue($contextual_links->isVisible(), "Contextual links are visible with $state page.");
      // Click each duplicate contextual trigger and verify only that region's
      // links open. If the cached path doesn't isolate duplicates, toggling
      // one opens both.
      foreach (['first', 'second'] as $id) {
        $other = $id === 'first' ? 'second' : 'first';
        $this->getSession()->executeScript("jQuery('#region-$id $contextual_id .trigger').trigger('click');");
        $this->assertNotNull($this->assertSession()->waitForElementVisible('css', "#region-$id $contextual_id .contextual-links"), "Contextual links in region-$id should open ($state page).");
        $this->assertFalse($this->getSession()->getPage()->find('css', "#region-$other $contextual_id .contextual-links")->isVisible(), "Contextual links in region-$other must NOT open when only region-$id was toggled ($state page).");
        // Close it again for the next iteration.
        $this->getSession()->executeScript("jQuery('#region-$id $contextual_id .trigger').trigger('click');");
        $this->assertSession()->waitForElementRemoved('css', "#region-$id $contextual_id .contextual.open");
      }
    }
  }