<?php

declare(strict_types=1);

namespace Drupal\Tests\node\Functional;

use Drupal\comment\Tests\CommentTestTrait;
use Drupal\Component\Utility\Html;
use Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;

/**
 * Tests node title.
 */
#[Group('node')]
#[RunTestsInSeparateProcesses]
class NodeTitleTest extends NodeTestBase {

  use CommentTestTrait;
  use AssertBreadcrumbTrait;

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

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

  /**
   * A user with permission to bypass access content.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $adminUser;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    $this->drupalPlaceBlock('system_breadcrumb_block');
    $this->drupalPlaceBlock('page_title_block');

    $this->adminUser = $this->drupalCreateUser([
      'administer nodes',
      'create article content',
      'create page content',
      'post comments',
    ]);
    $this->drupalLogin($this->adminUser);
    $this->addDefaultCommentField('node', 'page');
  }

  /**
   * Creates one node and tests if the node title has the correct value.
   */
  public function testNodeTitle(): void {
    // Create "Basic page" content with title.
    // Add the node to the frontpage so we can test if teaser links are
    // clickable.
    $node = $this->drupalCreateNode([
      'title' => 'Test node title',
      'promote' => 1,
    ]);

    // Test <title> tag.
    $this->drupalGet($node->toUrl());
    $this->assertSession()->elementTextEquals('xpath', '//title', 'Test node title | Drupal');

    // Test breadcrumb in comment preview.
    $this->assertBreadcrumb('comment/reply/node/' . $node->id() . '/comment', [
      '' => 'Home',
      'node/' . $node->id() => 'Test node title',
    ]);

    // Verify that the page title includes the node title.
    $this->assertSession()->titleEquals('Add new comment to Test node title | Drupal');

    // Test node title is clickable on teaser list (/node).
    $this->drupalGet('node');
    $this->clickLink($node->label());

    // Test edge case where node title is set to 0.
    $node = $this->drupalCreateNode([
      'title' => 0,
    ]);
    // Test that 0 appears as <title>.
    $this->drupalGet($node->toUrl());
    $this->assertSession()->titleEquals('0 | Drupal');
    // Test that 0 appears in the template <h1>.
    $this->assertSession()->elementTextEquals('xpath', '//h1', '0');

    // Test edge case where node title contains special characters.
    $edge_case_title = 'article\'s "title".';
    $settings = [
      'title' => $edge_case_title,
    ];
    $node = $this->drupalCreateNode($settings);
    // Test that the title appears as <title>. The title will be escaped on the
    // the page.
    $edge_case_title_escaped = Html::escape($edge_case_title);
    $this->drupalGet($node->toUrl());
    $this->assertSession()->responseContains('<title>' . $edge_case_title_escaped . ' | Drupal</title>');

    // Test that the title appears as <title> when reloading the node page.
    $this->drupalGet($node->toUrl());
    $this->assertSession()->responseContains('<title>' . $edge_case_title_escaped . ' | Drupal</title>');

  }

}
