<?php

declare(strict_types=1);

namespace Drupal\Tests\Core\Test;

use Drupal\Core\Database\Database;
use Drupal\Core\Test\TestSetupTrait;
use Drupal\Tests\DrupalTestCaseTrait;
use Drupal\Tests\UnitTestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\PreserveGlobalState;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;

/**
 * Tests the TestSetupTrait trait.
 *
 * Run in a separate process as this test involves Database statics and
 * environment variables.
 */
#[CoversClass(TestSetupTrait::class)]
#[Group('Testing')]
#[PreserveGlobalState(FALSE)]
#[RunTestsInSeparateProcesses]
class TestSetupTraitTest extends UnitTestCase {

  /**
   * Tests the SIMPLETEST_DB environment variable is used.
   */
  public function testChangeDatabasePrefix(): void {
    $root = dirname(__FILE__, 7);
    putenv('SIMPLETEST_DB=pgsql://user:pass@127.0.0.1/db');
    $connection_info = Database::convertDbUrlToConnectionInfo('mysql://user:pass@localhost/db');
    Database::addConnectionInfo('default', 'default', $connection_info);
    $this->assertEquals('mysql', Database::getConnectionInfo()['default']['driver']);
    $this->assertEquals('localhost', Database::getConnectionInfo()['default']['host']);

    // Create a mock for testing the trait and set a few properties that are
    // used to avoid unnecessary set up.
    $test_setup = new class() {

      use DrupalTestCaseTrait;
      use TestSetupTrait;

      /**
       * Returns the test class name.
       *
       * @return string
       *   The test class name.
       */
      public function name(): string {
        return 'test';
      }

    };

    $reflection = new \ReflectionClass($test_setup);
    $reflection->getProperty('databasePrefix')->setValue($test_setup, 'testDbPrefix');
    $reflection->getProperty('root')->setValue($test_setup, $root);

    $method = new \ReflectionMethod(get_class($test_setup), 'changeDatabasePrefix');
    $method->invoke($test_setup);

    // Ensure that SIMPLETEST_DB defines the default database connection after
    // calling \Drupal\Core\Test\TestSetupTrait::changeDatabasePrefix().
    $this->assertEquals('pgsql', Database::getConnectionInfo()['default']['driver']);
    $this->assertEquals('127.0.0.1', Database::getConnectionInfo()['default']['host']);
  }

}
