g2-8.x-1.x-dev/tests/src/Kernel/WOTDTest.php

tests/src/Kernel/WOTDTest.php
<?php

declare(strict_types=1);

namespace Drupal\Tests\g2\Kernel;

use Drupal\Core\Block\BlockManagerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\RfcLogLevel;
use Drupal\Core\State\StateInterface;
use Drupal\Core\Url;
use Drupal\g2\G2;
use Drupal\g2\Plugin\Block\WotdBlock;
use Drupal\g2\TestLogger;
use Drupal\g2\WOTD;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\NodeInterface;
use Drupal\Tests\node\Traits\NodeCreationTrait;

/**
 * Tests for the WOTD service.
 *
 * @group G2
 */
class WOTDTest extends KernelTestBase {

  use NodeCreationTrait {
    createNode as drupalCreateNode;
  }

  /**
   * The title of the WOTD node.
   */
  const TITLE_WOTD = 'WOTD';

  const MODULES = [
    // Needed for routing.
    'system',
    // Service node_preview (proxied) needs user.private_tempstore.
    'user',
    // Needed by text.module.
    'field',
    'filter',
    // Needed by node module.
    'text',
    // Needed by g2.module.
    'node',
    'path_alias',
    'taxonomy',
    'views',
    'g2',
  ];

  /**
   * The modules to enable for the test.
   *
   * @var string[]
   */
  protected static $modules = self::MODULES;

  /**
   * The config.factory service.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected ConfigFactoryInterface $config;

  /**
   * The entity_type.manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected EntityTypeManagerInterface $etm;

  /**
   * The core plugin.manager.block service.
   *
   * @var \Drupal\Core\Block\BlockManagerInterface
   */
  protected BlockManagerInterface $pmBlock;

  /**
   * The core state service.
   *
   * @var \Drupal\Core\State\StateInterface
   */
  protected StateInterface $state;

  /**
   * The test logger, not the logger.channel.g2 service.
   *
   * @var \Drupal\g2\TestLogger
   */
  protected TestLogger $testLogger;

  /**
   * The g2.wotd service.
   *
   * @var \Drupal\g2\WOTD
   */
  protected WOTD $wotd;

  /**
   * {@inheritdoc}
   */
  protected function setUp(): void {
    parent::setUp();
    $this->installEntitySchema('node');
    $this->installEntitySchema('path_alias');
    $this->installEntitySchema('user');
    $this->installSchema('node', []);
    $this->installConfig(static::MODULES);

    // @see https://www.drupal.org/node/2605684
    $this->container->get('router.builder')->rebuild();

    $this->config = $this->container->get(G2::SVC_CONF);
    $this->etm = $this->container->get(G2::SVC_ETM);
    $this->pmBlock = $this->container->get(G2::SVC_PM_BLOCK);
    $this->state = $this->container->get(G2::SVC_STATE);
    $this->wotd = $this->container->get(G2::SVC_WOTD);

    $this->testLogger = $this->container->get(G2::SVC_TEST_LOGGER);
    /** @var \Drupal\Core\Logger\LoggerChannelInterface $logger */
    $logger = $this->container->get(G2::SVC_LOGGER);
    $logger->addLogger($this->testLogger);
  }

  /**
   * Data provider for testGet().
   *
   * @return array<string,array{boolean,boolean,string}>
   *   Cf. test.
   */
  public static function providerGet(): array {
    return [
      'not stored' => [FALSE, TRUE, ''],
      'stored' => [TRUE, FALSE, static::TITLE_WOTD],
    ];
  }

  /**
   * Test WOTD::get.
   *
   * @dataProvider providerGet
   */
  public function testGet(
    bool $isWOTDStored,
    bool $expectNull,
    string $expectedTitle,
  ): void {
    // Setup: content.
    $wotd = $this->drupalCreateNode([
      'title' => static::TITLE_WOTD,
      'type' => G2::BUNDLE,
    ]);

    // Setup: config.
    $conf = $this->config->getEditable(G2::CONFIG_NAME);
    if ($isWOTDStored) {
      $conf->set(G2::VARWOTDENTRY, $wotd->id());
    }
    else {
      $conf->clear(G2::VARWOTDENTRY);
    }
    $conf->save();

    // Perform test.
    try {
      $actual = $this->wotd->get();
    }
    catch (\Exception $e) {
      $this->fail(sprintf("Unexpected exception: %s", $e));
    }
    if ($expectNull) {
      if (!is_null($actual)) {
        $this->fail(sprintf('Expected no WOTD but got "%s"', $actual->label()));
      }
      return;
    }
    $actualTitle = ($actual instanceof NodeInterface)
      ? $actual->label()
      : '';
    $this->assertEquals($expectedTitle, $actualTitle);
  }

  /**
   * Data provider for testIsAutoChangeEnabled.
   *
   * @return array<string,array{?boolean,boolean}>
   *   Cf. test.
   */
  public static function providerIsAutoChangeEnabled(): array {
    return [
      "disabled" => [TRUE, TRUE],
      "enabled" => [FALSE, FALSE],
      "not set" => [NULL, FALSE],
    ];
  }

  /**
   * Test WOTD::isAutoChangeEnabled.
   *
   * @param bool|null $input
   *   Input if any.
   * @param bool $expected
   *   Expected auto-change to be enabled.
   *
   * @throws \Exception
   *
   * @dataProvider providerIsAutoChangeEnabled
   */
  public function testIsAutoChangeEnabled(?bool $input, bool $expected): void {
    $config = $this->config->getEditable(G2::CONFIG_NAME);
    if (!isset($input)) {
      $config->clear(G2::VARWOTDAUTOCHANGE);
    }
    else {
      $config->set(G2::VARWOTDAUTOCHANGE, $input);
    }
    $config->save();
    $actual = $this->wotd->isAutoChangeEnabled();
    $this->assertEquals($expected, $actual);
  }

  /**
   * Data provider for testAutochange.
   *
   * @return array<string,array{string[],boolean,\DateTimeImmutable,boolean,string}>
   *   Cf. test.
   */
  public static function providerAutoChange(): array {
    $now = \DateTimeImmutable::createFromFormat('U', (string) (time() - 86400));
    self::assertInstanceOf(\DateTimeImmutable::class, $now);
    $yesterday = $now->sub(new \DateInterval("P1D"));
    assert($yesterday instanceof \DateTimeImmutable);
    return [
      'happy' => [
        [
          RandomTest::TITLE_FOO,
          RandomTest::TITLE_WOTD,
        ],
        TRUE,
        $yesterday,
        FALSE,
        RandomTest::TITLE_FOO,
      ],
      'sad no node available' => [
        [RandomTest::TITLE_WOTD],
        TRUE,
        $yesterday,
        TRUE,
        '',
      ],
    ];
  }

  /**
   * Test WOTD::autoChange.
   *
   * @param string[] $nodesToCreate
   *   The titles for the nodes to create.
   * @param bool $isEntrySet
   *   Set the WOTD entry or not.
   * @param \DateTimeImmutable $entryDate
   *   Timestamp for the entry if set.
   * @param bool $expectError
   *   Expect an error.
   * @param string $expectedTitle
   *   Expected title.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Exception
   *
   * @dataProvider providerAutoChange
   */
  public function testAutochange(
    array $nodesToCreate,
    bool $isEntrySet,
    \DateTimeImmutable $entryDate,
    bool $expectError,
    string $expectedTitle,
  ): void {
    $nodesByTitle = [];
    foreach ($nodesToCreate as $title) {
      $nodesByTitle[$title] = $this->drupalCreateNode([
        'title' => $title,
        'type' => G2::BUNDLE,
      ]);
    }
    $this->assertNotEmpty($nodesByTitle[RandomTest::TITLE_WOTD]);
    if ($isEntrySet) {
      $this->assertNotEmpty($entryDate);
      $this->config
        ->getEditable(G2::CONFIG_NAME)
        ->set(G2::VARWOTDENTRY, $nodesByTitle[RandomTest::TITLE_WOTD]->id())
        ->save();
      $this->state->set(G2::VARWOTDDATE, $entryDate->format(WOTD::DATE_STORAGE_FORMAT));
    }

    $this->wotd->autoChange();

    $errorCount = $this->testLogger->countByLevel(RfcLogLevel::ERROR);
    if ($expectError) {
      $this->assertEquals(1, $errorCount);
      return;
    }
    $this->assertEquals(0, $errorCount);

    if (!$expectedTitle) {
      return;
    }
    $actualNid = $this->config
      ->get(G2::CONFIG_NAME)
      ->get(G2::VARWOTDENTRY);
    $this->assertNotEmpty($actualNid);
    $actualNode = $this->etm
      ->getStorage(G2::TYPE)
      ->load($actualNid);
    $this->assertNotEmpty($actualNode);
    $actualTitle = $actualNode->label();
    $this->assertEquals($expectedTitle, $actualTitle);
  }

  /**
   * Data provider for testPreprocessFeedIcon().
   *
   * @return array<string,mixed>
   *   Test cases.
   */
  public static function providerPreprocessFeedIcon(): array {
    global $base_url;
    $tests = [
      'all empty' => [[], FALSE, FALSE, FALSE],
      'external string URL' => [
        ['url' => 'https://example.com'], FALSE, FALSE, FALSE,
      ],
      'internal string URL, invalid' => [
        ['url' => "{$base_url}/invalid"], FALSE, FALSE, FALSE,
      ],
      'internal string URL, unrouted' => [
        ['url' => "{$base_url}/robots.txt"], FALSE, FALSE, FALSE,
      ],
      'internal string URL, other route' => [
        ['url' => "{$base_url}/node"], FALSE, FALSE, FALSE,
      ],
      'internal string URL, WOTD feed' => [
        ['url' => '/g2/feed/wotd'], FALSE, TRUE, TRUE,
      ],
      'URL object, unrouted' => [
        ['url' => 'base:robots.txt'], TRUE, FALSE, FALSE,
      ],
      'URL object, WOTD feed' => [
        ['url' => G2::ROUTE_FEED_WOTD], TRUE, TRUE, TRUE,
      ],
    ];
    return $tests;
  }

  /**
   * Preprocesses the feed icon link based on the given input variables.
   *
   * @param array<string,mixed> $variables
   *   The relevant sub-array of $variables on input.
   * @param bool $asURL
   *   Does test need to generate a URL from the URL string?
   * @param bool $expectAttributes
   *   Must the test expect an "attributes" key in $variables?
   * @param bool $expectedClass
   *   Must the test expect the WOTDBlock::ICON_CLASS in the class attributes?
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   *
   * @dataProvider providerPreprocessFeedIcon
   */
  public function testPreprocessFeedIcon(array $variables, bool $asURL, bool $expectAttributes, bool $expectedClass): void {
    /** @var \Drupal\g2\Plugin\Block\WotdBlock $block */
    $block = $this->pmBlock->createInstance(G2::DELTA_WOTD);
    if ($asURL) {
      $uri = $variables['url'] ?? '';
      $this->assertIsString($uri);
      if (str_starts_with($uri, 'base:')) {
        $url = Url::fromUri($uri);
      }
      else {
        $url = Url::fromRoute($uri);
      }
      $variables['url'] = $url;
    }
    $block->preprocessFeedIcon($variables);
    if (!$expectAttributes) {
      $this->assertArrayNotHasKey('attributes', $variables);
      return;
    }
    $this->assertArrayHasKey('attributes', $variables);
    $attributes = $variables['attributes'];
    $this->assertArrayHasKey('class', $attributes);
    $classes = $attributes['class'];
    $this->assertIsArray($classes);
    $this->assertEquals($expectedClass,
      in_array(WotdBlock::ICON_CLASS, $classes));
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc