View source  
  <?php
namespace Drupal\Tests\link_class\Functional;
use Drupal\field\Entity\FieldConfig;
use Drupal\link\LinkItemInterface;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Tests\BrowserTestBase;
class LinkClassWidgetTest extends BrowserTestBase {
  
  public static $modules = [
    'entity_test',
    'link',
    'node',
    'field',
    'field_ui',
    'link_class',
  ];
  
  protected $fieldStorage;
  
  protected $field;
  
  protected $formDisplay;
  
  protected $viewDisplay;
  
  protected $node;
  
  protected $strictConfigSchema = FALSE;
  
  protected function setUp() {
    parent::setUp();
    $this
      ->drupalCreateContentType([
      'type' => 'article',
    ]);
    $this
      ->drupalLogin($this
      ->drupalCreateUser([
      'view test entity',
      'administer content types',
      'administer node fields',
      'administer node form display',
      'administer node display',
      'administer nodes',
      'edit any article content',
    ]));
  }
  
  public function testLinkClassWidget() {
    $field_name = mb_strtolower($this
      ->randomMachineName());
    
    $this->fieldStorage = FieldStorageConfig::create([
      'field_name' => $field_name,
      'entity_type' => 'node',
      'type' => 'link',
    ]);
    $this->fieldStorage
      ->save();
    $this->field = FieldConfig::create([
      'field_storage' => $this->fieldStorage,
      'bundle' => 'article',
      'label' => 'Link',
      'settings' => [
        'title' => DRUPAL_REQUIRED,
        'link_type' => LinkItemInterface::LINK_GENERIC,
      ],
    ]);
    $this->field
      ->save();
    $this
      ->setFormDisplay('node.article.default', 'node', 'article', $field_name, 'link_class_field_widget', []);
    $this
      ->setViewDisplay('node.article.default', 'node', 'article', $field_name, 'link', []);
    $bundle_path = 'admin/structure/types/manage/article';
    $this
      ->drupalGet($bundle_path . '/form-display');
    $this
      ->assertFieldByXPath('//table[@id="field-display-overview"]//tr[@id="' . $field_name . '"]/td[1]', 'Link', 'Field appears in the Manage form display page.');
    $this
      ->assertSession()
      ->fieldValueEquals('fields[' . $field_name . '][type]', 'link_class_field_widget');
    
    $this
      ->assertRaw('Mode: Users can set a class manually');
    
    $this
      ->drupalGet($bundle_path . '/display');
    $this
      ->assertSession()
      ->fieldValueEquals('fields[' . $field_name . '][type]', 'link');
    
    $this
      ->drupalGet('node/add/article');
    $this
      ->assertFieldByName("{$field_name}[0][uri]", '');
    $this
      ->assertFieldByName("{$field_name}[0][title]", '');
    $this
      ->assertFieldByName("{$field_name}[0][options][attributes][class]", '');
    
    $field_path = "admin/structure/types/manage/article/fields/node.article.{$field_name}";
    $field_edit = [
      'default_value_input[' . $field_name . '][0][uri]' => 'http://www.mysite.fr',
      'default_value_input[' . $field_name . '][0][title]' => 'My secondary button',
      'default_value_input[' . $field_name . '][0][options][attributes][class]' => 'btn btn-secondary',
    ];
    $this
      ->drupalPostForm($field_path, $field_edit, 'Save settings');
    
    $this
      ->drupalGet('node/add/article');
    $this
      ->assertRaw('http://www.mysite.fr');
    $this
      ->assertRaw('My secondary button');
    $this
      ->assertRaw('btn btn-secondary');
    
    $title = 'Article 1';
    $values = [
      'type' => 'article',
      'title' => $title,
      'status' => 1,
      'body' => [
        'value' => 'Content body for ' . $title,
      ],
    ];
    $this->node = $this
      ->drupalCreateNode($values);
    $this
      ->drupalGet("node/{$this->node->id()}");
    $this
      ->assertRaw('Article 1');
    
    $edit = [
      $field_name . '[0][uri]' => 'http://www.example.com',
      $field_name . '[0][title]' => 'My button',
      $field_name . '[0][options][attributes][class]' => 'button1',
    ];
    $this
      ->drupalPostForm("/node/{$this->node->id()}/edit", $edit, 'Save');
    $this
      ->drupalGet("node/{$this->node->id()}");
    $this
      ->assertRaw('<a href="http://www.example.com" class="button1">My button</a>');
    
    $settings = [
      'link_class_mode' => 'force_class',
      'link_class_force' => 'btn btn-default',
    ];
    $this
      ->setFormDisplay('node.article.default', 'node', 'article', $field_name, 'link_class_field_widget', $settings);
    $this
      ->drupalGet($bundle_path . '/form-display');
    $this
      ->assertRaw('Mode: Class are automatically added');
    $this
      ->assertRaw('Class(es) added: btn btn-default');
    
    $this
      ->drupalGet("node/{$this->node->id()}/edit");
    $this
      ->assertNoField($field_name . '[0][options][attributes][class');
    $edit = [
      $field_name . '[0][uri]' => 'http://www.example.com',
      $field_name . '[0][title]' => 'My button',
    ];
    $this
      ->drupalPostForm("/node/{$this->node->id()}/edit", $edit, 'Save');
    $this
      ->assertRaw('<a href="http://www.example.com" class="btn btn-default">My button</a>');
    
    $settings = [
      'link_class_mode' => 'select_class',
      'link_class_select' => 'btn btn-default|Default button' . PHP_EOL . 'btn btn-primary|Primary button' . PHP_EOL . 'btn btn-secondary|Secondary button',
    ];
    $this
      ->setFormDisplay('node.article.default', 'node', 'article', $field_name, 'link_class_field_widget', $settings);
    $this
      ->drupalGet($bundle_path . '/form-display');
    $this
      ->assertRaw(t('Mode: Let users select a class from a list'));
    $this
      ->assertRaw(t('Class(es) available: btn btn-default, btn btn-primary, btn btn-secondary'));
    
    $this
      ->drupalGet("node/{$this->node->id()}/edit");
    $this
      ->assertField($field_name . '[0][options][attributes][class]');
    $this
      ->assertOption("edit-{$field_name}-0-options-attributes-class", 'btn btn-default');
    $this
      ->assertOption("edit-{$field_name}-0-options-attributes-class", 'btn btn-primary');
    $this
      ->assertOption("edit-{$field_name}-0-options-attributes-class", 'btn btn-secondary');
    $this
      ->assertOptionByText("edit-{$field_name}-0-options-attributes-class", 'Default button');
    $this
      ->assertOptionByText("edit-{$field_name}-0-options-attributes-class", 'Primary button');
    $this
      ->assertOptionByText("edit-{$field_name}-0-options-attributes-class", 'Secondary button');
    $edit = [
      $field_name . '[0][uri]' => 'http://www.example.com',
      $field_name . '[0][title]' => 'My button',
      $field_name . '[0][options][attributes][class]' => 'btn btn-primary',
    ];
    $this
      ->drupalPostForm("/node/{$this->node->id()}/edit", $edit, 'Save');
    $this
      ->assertRaw('<a href="http://www.example.com" class="btn btn-primary">My button</a>');
    $this
      ->drupalGet("node/{$this->node->id()}/edit");
    $this
      ->assertOptionSelected("edit-{$field_name}-0-options-attributes-class", 'btn btn-primary');
  }
  
  protected function setFormDisplay($form_display_id, $entity_type, $bundle, $field_name, $widget_id, array $settings, $mode = 'default') {
    
    $this->formDisplay = EntityFormDisplay::load($form_display_id);
    if (!$this->formDisplay) {
      EntityFormDisplay::create([
        'targetEntityType' => $entity_type,
        'bundle' => $bundle,
        'mode' => $mode,
        'status' => TRUE,
      ])
        ->save();
      $this->formDisplay = EntityFormDisplay::load($form_display_id);
    }
    if ($this->formDisplay instanceof EntityFormDisplayInterface) {
      $this->formDisplay
        ->setComponent($field_name, [
        'type' => $widget_id,
        'settings' => $settings,
      ])
        ->save();
    }
  }
  
  protected function setViewDisplay($form_display_id, $entity_type, $bundle, $field_name, $formatter_id, array $settings, $mode = 'default') {
    
    $this->viewDisplay = EntityViewDisplay::load($form_display_id);
    if (!$this->viewDisplay) {
      EntityViewDisplay::create([
        'targetEntityType' => $entity_type,
        'bundle' => $bundle,
        'mode' => $mode,
        'status' => TRUE,
      ])
        ->save();
      $this->viewDisplay = EntityViewDisplay::load($form_display_id);
    }
    if ($this->viewDisplay instanceof EntityViewDisplayInterface) {
      $this->viewDisplay
        ->setComponent($field_name, [
        'type' => $formatter_id,
        'settings' => $settings,
      ])
        ->save();
    }
  }
}