View source  
  <?php
namespace Drupal\Tests\facets\FunctionalJavascript;
use Drupal\facets\Entity\Facet;
class WidgetJSTest extends JsBase {
  
  public function testAddFacet() {
    $this
      ->drupalGet('admin/config/search/facets/add-facet');
    $page = $this
      ->getSession()
      ->getPage();
    
    $page
      ->selectFieldOption('edit-facet-source-id', 'search_api:views_page__search_api_test_view__page_1');
    $this
      ->getSession()
      ->wait(6000, "jQuery('.facet-source-field-wrapper').length > 0");
    $page
      ->selectFieldOption('facet_source_configs[search_api:views_page__search_api_test_view__page_1][field_identifier]', 'type');
    
    $field_value = $this
      ->getSession()
      ->getPage()
      ->findField('edit-name')
      ->getValue();
    $this
      ->assertEquals('Type', $field_value);
  }
  
  public function testLinksShowMoreLess() {
    $facet_storage = \Drupal::entityTypeManager()
      ->getStorage('facets_facet');
    $id = 'owl';
    
    $facet_storage
      ->create([
      'id' => $id,
      'name' => strtoupper($id),
      'url_alias' => $id,
      'facet_source_id' => 'search_api:views_page__search_api_test_view__page_1',
      'field_identifier' => 'type',
      'empty_behavior' => [
        'behavior' => 'none',
      ],
      'weight' => 1,
      'widget' => [
        'type' => 'links',
        'config' => [
          'show_numbers' => TRUE,
          'soft_limit' => 1,
          'soft_limit_settings' => [
            'show_less_label' => 'Show less',
            'show_more_label' => 'Show more',
          ],
        ],
      ],
      'processor_configs' => [
        'url_processor_handler' => [
          'processor_id' => 'url_processor_handler',
          'weights' => [
            'pre_query' => -10,
            'build' => -10,
          ],
          'settings' => [],
        ],
      ],
    ])
      ->save();
    $this
      ->createBlock($id);
    
    $this
      ->drupalGet('search-api-test-fulltext');
    
    $page = $this
      ->getSession()
      ->getPage();
    $block = $page
      ->findById('block-owl-block');
    $block
      ->isVisible();
    
    $this
      ->assertSession()
      ->linkExists('Show more');
    
    $facet = Facet::load('owl');
    $facet
      ->setWidget('links', [
      'show_numbers' => TRUE,
      'soft_limit' => 1,
      'soft_limit_settings' => [
        'show_less_label' => 'Show less',
        'show_more_label' => 'Moar Llamas',
      ],
    ]);
    $facet
      ->save();
    
    $this
      ->drupalGet('search-api-test-fulltext');
    $this
      ->assertSession()
      ->linkNotExists('Show more');
    $this
      ->assertSession()
      ->linkExists('Moar Llamas');
  }
  
  public function testCheckboxWidget() {
    $facet_storage = \Drupal::entityTypeManager()
      ->getStorage('facets_facet');
    $id = 'llama';
    
    $facet_storage
      ->create([
      'id' => $id,
      'name' => strtoupper($id),
      'url_alias' => $id,
      'facet_source_id' => 'search_api:views_page__search_api_test_view__page_1',
      'field_identifier' => 'type',
      'empty_behavior' => [
        'behavior' => 'none',
      ],
      'widget' => [
        'type' => 'checkbox',
        'config' => [
          'show_numbers' => TRUE,
        ],
      ],
      'processor_configs' => [
        'url_processor_handler' => [
          'processor_id' => 'url_processor_handler',
          'weights' => [
            'pre_query' => -10,
            'build' => -10,
          ],
          'settings' => [],
        ],
      ],
    ])
      ->save();
    $this
      ->createBlock($id);
    
    $this
      ->drupalGet('search-api-test-fulltext');
    
    $page = $this
      ->getSession()
      ->getPage();
    $block = $page
      ->findById('block-llama-block');
    $this
      ->assertTrue($block
      ->isVisible());
    
    $this
      ->assertCount(1, $block
      ->findAll('css', 'div.facets-widget-checkbox ul'));
    
    $this
      ->assertCount(1, $block
      ->findAll('css', 'ul.facet-inactive.item-list__checkbox.js-facets-widget.js-facets-checkbox-links'));
    $this
      ->assertCount(1, $block
      ->findAll('css', 'ul[data-drupal-facet-id="llama"]'));
    $this
      ->assertCount(1, $block
      ->findAll('css', 'ul[data-drupal-facet-alias="llama"]'));
    
    $list_items = $block
      ->findAll('css', 'ul li.facet-item');
    $this
      ->assertCount(2, $list_items);
    
    $expected = [
      [
        'item',
        3,
        base_path() . 'search-api-test-fulltext?f%5B0%5D=llama%3Aitem',
        FALSE,
      ],
      [
        'article',
        2,
        base_path() . 'search-api-test-fulltext?f%5B0%5D=llama%3Aarticle',
        FALSE,
      ],
    ];
    $this
      ->assertListItems($expected, $list_items);
    
    $checkbox = $page
      ->findField('item (3)');
    $checkbox
      ->click();
    $current_url = $this
      ->getSession()
      ->getCurrentUrl();
    $this
      ->assertStringContainsString('search-api-test-fulltext?f%5B0%5D=llama%3Aitem', $current_url);
    
    $expected = [
      [
        'item',
        3,
        base_path() . 'search-api-test-fulltext',
        TRUE,
      ],
      [
        'article',
        2,
        base_path() . 'search-api-test-fulltext?f%5B0%5D=llama%3Aarticle',
        FALSE,
      ],
    ];
    $this
      ->assertListItems($expected, $block
      ->findAll('css', 'ul li.facet-item'));
    
    $checkbox = $page
      ->findField('item (3)');
    $checkbox
      ->click();
    $current_url = $this
      ->getSession()
      ->getCurrentUrl();
    $this
      ->assertStringContainsString('search-api-test-fulltext', $current_url);
    $expected = [
      [
        'item',
        3,
        base_path() . 'search-api-test-fulltext?f%5B0%5D=llama%3Aitem',
        FALSE,
      ],
      [
        'article',
        2,
        base_path() . 'search-api-test-fulltext?f%5B0%5D=llama%3Aarticle',
        FALSE,
      ],
    ];
    $this
      ->assertListItems($expected, $block
      ->findAll('css', 'ul li.facet-item'));
  }
  
  protected function assertListItems(array $expected, array $list_items) : void {
    $this
      ->assertCount(count($expected), $list_items);
    foreach ($expected as $key => [
      $keyword,
      $count,
      $uri,
      $selected,
    ]) {
      $list_item = $list_items[$key];
      
      $this
        ->assertTrue($list_item
        ->isVisible());
      
      $item_id = "llama-{$keyword}";
      $this
        ->assertCount(1, $list_item
        ->findAll('css', 'input'));
      $this
        ->assertCount(1, $list_item
        ->findAll('css', "input#{$item_id}[type='checkbox'].facets-checkbox"));
      
      $labels = $list_item
        ->findAll('css', "label[for={$item_id}]");
      $this
        ->assertCount(1, $labels);
      
      $label = reset($labels);
      $expected_text = "<span class=\"facet-item__value\">{$keyword}</span> <span class=\"facet-item__count\">({$count})</span>";
      $this
        ->assertTrue($label
        ->isVisible());
      $this
        ->assertEquals($expected_text, trim(preg_replace('/\\s+/', ' ', $label
        ->getHtml())));
      
      $links = $list_item
        ->findAll('css', 'a');
      $this
        ->assertCount(1, $links);
      $link = reset($links);
      
      $this
        ->assertFalse($link
        ->isVisible());
      
      $this
        ->assertEquals('nofollow', $link
        ->getAttribute('rel'));
      
      $this
        ->assertEquals($item_id, $link
        ->getAttribute('data-drupal-facet-item-id'));
      $this
        ->assertEquals($keyword, $link
        ->getAttribute('data-drupal-facet-item-value'));
      
      $this
        ->assertStringContainsString($expected_text, trim(preg_replace('/\\s+/', ' ', $link
        ->getHtml())));
    }
  }
  
  public function testDropdownWidget() {
    $facet_storage = \Drupal::entityTypeManager()
      ->getStorage('facets_facet');
    $id = 'llama';
    
    $facet_storage
      ->create([
      'id' => $id,
      'name' => strtoupper($id),
      'url_alias' => $id,
      'facet_source_id' => 'search_api:views_page__search_api_test_view__page_1',
      'field_identifier' => 'type',
      'empty_behavior' => [
        'behavior' => 'none',
      ],
      'show_only_one_result' => TRUE,
      'widget' => [
        'type' => 'dropdown',
        'config' => [
          'show_numbers' => TRUE,
          'default_option_label' => '- All -',
        ],
      ],
      'processor_configs' => [
        'url_processor_handler' => [
          'processor_id' => 'url_processor_handler',
          'weights' => [
            'pre_query' => -10,
            'build' => -10,
          ],
          'settings' => [],
        ],
      ],
    ])
      ->save();
    $this
      ->createBlock($id);
    
    $this
      ->drupalGet('search-api-test-fulltext');
    
    $page = $this
      ->getSession()
      ->getPage();
    $block = $page
      ->findById('block-llama-block');
    $this
      ->assertTrue($block
      ->isVisible());
    
    $this
      ->assertCount(1, $block
      ->findAll('css', 'select'));
    
    $this
      ->assertCount(1, $block
      ->findAll('css', 'div.facets-widget-dropdown select'));
    
    $this
      ->assertCount(1, $block
      ->findAll('css', 'select.facet-inactive.item-list__dropdown.facets-dropdown.js-facets-widget.js-facets-dropdown'));
    $this
      ->assertCount(1, $block
      ->findAll('css', 'select[data-drupal-facet-id="llama"]'));
    $this
      ->assertCount(1, $block
      ->findAll('css', 'select[data-drupal-facet-alias="llama"]'));
    
    $this
      ->assertCount(1, $block
      ->findAll('css', 'select[aria-labelledby="facet_llama_label"]'));
    $this
      ->assertCount(1, $block
      ->findAll('css', 'label#facet_llama_label'));
    $this
      ->assertEquals('Facet LLAMA', $block
      ->find('css', 'label')
      ->getHtml());
    
    $dropdown = $block
      ->find('css', 'select');
    $this
      ->assertTrue($dropdown
      ->isVisible());
    
    $options = $dropdown
      ->findAll('css', 'option');
    $expected = [
      
      [
        '- All -',
        '',
        TRUE,
      ],
      
      [
        ' item (3)',
        base_path() . 'search-api-test-fulltext?f%5B0%5D=llama%3Aitem',
        FALSE,
      ],
      
      [
        ' article (2)',
        base_path() . 'search-api-test-fulltext?f%5B0%5D=llama%3Aarticle',
        FALSE,
      ],
    ];
    $this
      ->assertSelectOptions($expected, $options);
    
    $dropdown
      ->selectOption('item (3)');
    $this
      ->getSession()
      ->wait(6000, "window.location.search != ''");
    $current_url = $this
      ->getSession()
      ->getCurrentUrl();
    $this
      ->assertStringContainsString('search-api-test-fulltext?f%5B0%5D=llama%3Aitem', $current_url);
    
    $dropdown = $block
      ->find('css', 'select');
    $this
      ->assertTrue($dropdown
      ->isVisible());
    $options = $dropdown
      ->findAll('css', 'option');
    $expected = [
      
      [
        '- All -',
        base_path() . 'search-api-test-fulltext',
        FALSE,
      ],
      
      [
        ' item (3)',
        base_path() . 'search-api-test-fulltext',
        TRUE,
      ],
      
      [
        ' article (2)',
        base_path() . 'search-api-test-fulltext?f%5B0%5D=llama%3Aarticle',
        FALSE,
      ],
    ];
    $this
      ->assertSelectOptions($expected, $options);
  }
  
  protected function assertSelectOptions(array $expected, array $options) : void {
    $this
      ->assertCount(count($expected), $options);
    foreach ($expected as $key => [
      $text,
      $value,
      $selected,
    ]) {
      $option = $options[$key];
      
      $this
        ->assertEquals($text, preg_replace('/\\s+/', ' ', $option
        ->getText()));
      $this
        ->assertEquals($value, $option
        ->getValue());
      $this
        ->assertEquals($selected, $option
        ->isSelected());
    }
  }
}