Verified Commit f18d77fe authored by Dave Long's avatar Dave Long
Browse files

test: #3577840 Consolidate test methods in GenerateThemeTest

By: catch
By: smustgrave
(cherry picked from commit 3a2d8705b21a1bfeabd6505132d0f6dac2519a4a)
parent 0883f86a
Loading
Loading
Loading
Loading
Loading
+126 −55
Original line number Diff line number Diff line
@@ -30,6 +30,16 @@ class GenerateThemeTest extends QuickStartTestBase {
   */
  protected $php;

  /**
   * The unaltered starterkit.info.yml contents.
   */
  protected array $originalInfo;

  /**
   * The location of the starter kit .info.yml file.
   */
  protected string $starterKitInfoYamlLocation;

  /**
   * {@inheritdoc}
   */
@@ -44,6 +54,8 @@ protected function setUp(): void {
    $this->copyCodebase();
    $this->executeCommand('COMPOSER_DISCARD_CHANGES=true composer install --no-dev --no-interaction');
    chdir($this->getWorkingPath());
    $this->starterKitInfoYamlLocation = $this->getWorkspaceDirectory() . '/core/themes/starterkit_theme/starterkit_theme.info.yml';
    $this->originalInfo = yaml::decode(file_get_contents($this->starterKitInfoYamlLocation));
  }

  /**
@@ -189,16 +201,39 @@ private function assertThemeExists(string $theme_path_relative): array {
  }

  /**
   * Tests the generate-theme command.
   * Delete the generated theme.
   */
  protected function deleteGeneratedTheme(string $theme_name): void {
    $this->fileUnmanagedDeleteRecursive('themes/' . $theme_name);
  }

  /**
   * Set a version in the .info.yml.
   */
  public function test(): void {
  protected function setVersion(string $version): void {
    // Do not rely on \Drupal::VERSION: change the version to a concrete version
    // number, to simulate using a tagged core release.
    $starterkit_info_yml = $this->getWorkspaceDirectory() . '/core/themes/starterkit_theme/starterkit_theme.info.yml';
    $info = Yaml::decode(file_get_contents($starterkit_info_yml));
    $info['version'] = '9.4.0';
    file_put_contents($starterkit_info_yml, Yaml::encode($info));
    $info = $this->originalInfo;
    $info['version'] = $version;
    file_put_contents($this->starterKitInfoYamlLocation, Yaml::encode($info));
  }

  /**
   * Tests the generate-theme command.
   */
  public function testGenerateTheme(): void {
    $this->doTestGenerateTheme();
    $this->deleteGeneratedTheme('test_custom_theme');
    $this->doTestGeneratingFromAnotherTheme();
    $this->deleteGeneratedTheme('test_custom_theme');
    $this->doTestDevSnapshot();
    $this->deleteGeneratedTheme('test_custom_theme');
    $this->doTestContribStarterkit();
    $this->deleteGeneratedTheme('test_custom_theme');
  }

  protected function doTestGenerateTheme(): void {
    $this->setVersion('9.4.0');
    $process = $this->generateThemeFromStarterkit();
    $result = $process->run();
    $this->assertStringContainsString('Theme generated successfully to themes/test_custom_theme', trim($process->getOutput()), $process->getErrorOutput());
@@ -239,13 +274,8 @@ public function test(): void {
  /**
   * Tests generating a theme from another Starterkit enabled theme.
   */
  public function testGeneratingFromAnotherTheme(): void {
    // Do not rely on \Drupal::VERSION: change the version to a concrete version
    // number, to simulate using a tagged core release.
    $starterkit_info_yml = $this->getWorkspaceDirectory() . '/core/themes/starterkit_theme/starterkit_theme.info.yml';
    $info = Yaml::decode(file_get_contents($starterkit_info_yml));
    $info['version'] = '9.4.0';
    file_put_contents($starterkit_info_yml, Yaml::encode($info));
  protected function doTestGeneratingFromAnotherTheme(): void {
    $this->setVersion('9.4.0');

    $process = $this->generateThemeFromStarterkit();
    $exit_code = $process->run();
@@ -278,18 +308,14 @@ public function testGeneratingFromAnotherTheme(): void {
    // Confirm new .theme file.
    $dot_theme_file = $this->getWorkspaceDirectory() . '/themes/generated_from_another_theme/src/Hook/GeneratedFromAnotherThemeHooks.php';
    $this->assertStringContainsString('public function preprocessImageWidget(array &$variables): void {', file_get_contents($dot_theme_file));
    $this->deleteGeneratedTheme('generated_from_another_theme');
  }

  /**
   * Tests the generate-theme command on a dev snapshot of Drupal core.
   */
  public function testDevSnapshot(): void {
    // Do not rely on \Drupal::VERSION: change the version to a development
    // snapshot version number, to simulate using a branch snapshot of core.
    $starterkit_info_yml = $this->getWorkspaceDirectory() . '/core/themes/starterkit_theme/starterkit_theme.info.yml';
    $info = Yaml::decode(file_get_contents($starterkit_info_yml));
    $info['version'] = '9.4.0-dev';
    file_put_contents($starterkit_info_yml, Yaml::encode($info));
  protected function doTestDevSnapshot(): void {
    $this->setVersion('9.4.0-dev');

    $process = $this->generateThemeFromStarterkit();
    $result = $process->run();
@@ -306,13 +332,8 @@ public function testDevSnapshot(): void {
  /**
   * Tests the generate-theme command on a theme with a release version number.
   */
  public function testContribStarterkit(): void {
    // Change the version to a concrete version number, to simulate using a
    // contrib theme as the starterkit.
    $starterkit_info_yml = $this->getWorkspaceDirectory() . '/core/themes/starterkit_theme/starterkit_theme.info.yml';
    $info = Yaml::decode(file_get_contents($starterkit_info_yml));
    $info['version'] = '1.20';
    file_put_contents($starterkit_info_yml, Yaml::encode($info));
  protected function doTestContribStarterkit(): void {
    $this->setVersion('1.20');

    $process = $this->generateThemeFromStarterkit();
    $result = $process->run();
@@ -419,10 +440,41 @@ public function testCustomStarterkit(): void {
    self::assertEquals('starterkit_theme:unknown-version', $info['generator']);
  }

  public function testDeleteDirectory(): void {
    $this->writeStarterkitConfig([
      'ignore' => [
        '/src/*',
        '/starterkit_theme.starterkit.yml',
      ],
    ]);

    $tester = $this->runCommand(
      [
        'machine-name' => 'test_custom_theme',
        '--name' => 'Test custom starterkit theme',
        '--description' => 'Custom theme generated from a starterkit theme',
      ]
    );

    $tester->assertCommandIsSuccessful($tester->getErrorOutput());
    $this->assertThemeExists('themes/test_custom_theme');
    $theme_path_absolute = $this->getWorkspaceDirectory() . '/themes/test_custom_theme';
    self::assertDirectoryExists($theme_path_absolute);
    self::assertFileDoesNotExist($theme_path_absolute . '/src/StarterKit.php');
  }

  public function testInvalidThemesAndWarnings(): void {
    $this->doTestThemeDoesNotExist();
    $this->doTestStarterKitFlag();
    $this->doTestNoEditMissingFilesWarning();
    $this->doTestNoRenameMissingFilesWarning();
    $this->doTestNoRename();
  }

  /**
   * Tests themes that do not exist return an error.
   */
  public function testThemeDoesNotExist(): void {
  protected function doTestThemeDoesNotExist(): void {
    $install_command = [
      $this->php,
      'core/scripts/drupal',
@@ -443,7 +495,7 @@ public function testThemeDoesNotExist(): void {
  /**
   * Tests that only themes with `starterkit` flag can be used.
   */
  public function testStarterKitFlag(): void {
  protected function doTestStarterKitFlag(): void {
    // Explicitly not a starter theme.
    $install_command = [
      $this->php,
@@ -479,34 +531,12 @@ public function testStarterKitFlag(): void {
    $this->assertSame(1, $result);
  }

  public function testDeleteDirectory(): void {
    $this->writeStarterkitConfig([
      'ignore' => [
        '/src/*',
        '/starterkit_theme.starterkit.yml',
      ],
    ]);

    $tester = $this->runCommand(
      [
        'machine-name' => 'test_custom_theme',
        '--name' => 'Test custom starterkit theme',
        '--description' => 'Custom theme generated from a starterkit theme',
      ]
    );

    $tester->assertCommandIsSuccessful($tester->getErrorOutput());
    $this->assertThemeExists('themes/test_custom_theme');
    $theme_path_absolute = $this->getWorkspaceDirectory() . '/themes/test_custom_theme';
    self::assertDirectoryExists($theme_path_absolute);
    self::assertFileDoesNotExist($theme_path_absolute . '/src/StarterKit.php');
  }

  public function testNoEditMissingFilesWarning(): void {
  protected function doTestNoEditMissingFilesWarning(): void {
    $this->writeStarterkitConfig([
      'no_edit' => [
        '/js/starterkit_theme.js',
      ],
      'no_rename' => NULL,
    ]);

    $tester = $this->runCommand(
@@ -523,11 +553,12 @@ public function testNoEditMissingFilesWarning(): void {
    self::assertDirectoryDoesNotExist($theme_path_absolute);
  }

  public function testNoRenameMissingFilesWarning(): void {
  protected function doTestNoRenameMissingFilesWarning(): void {
    $this->writeStarterkitConfig([
      'no_rename' => [
        '/js/starterkit_theme.js',
      ],
      'no_edit' => NULL,
    ]);

    $tester = $this->runCommand(
@@ -544,13 +575,14 @@ public function testNoRenameMissingFilesWarning(): void {
    self::assertDirectoryDoesNotExist($theme_path_absolute);
  }

  public function testNoRename(): void {
  protected function doTestNoRename(): void {
    $this->writeStarterkitConfig([
      'no_rename' => [
        'js/starterkit_theme.js',
        '**/js/*.js',
        'js/**/*.js',
      ],
      'no_edit' => NULL,
    ]);

    mkdir($this->getWorkspaceDirectory() . '/core/themes/starterkit_theme/js');
@@ -763,4 +795,43 @@ private function runCommand(array $input): CommandTester {
    return $tester;
  }

  /**
   * Deletes all files and directories in the specified path recursively.
   *
   * Note this method has no dependencies on Drupal core to ensure that the
   * test site can be torn down even if something in the test site is broken.
   *
   * @param string $path
   *   A string containing either a URI or a file or directory path.
   * @param callable $callback
   *   (optional) Callback function to run on each file prior to deleting it and
   *   on each directory prior to traversing it. For example, can be used to
   *   modify permissions.
   *
   * @return bool
   *   TRUE for success or if path does not exist, FALSE in the event of an
   *   error.
   *
   * @see \Drupal\Core\File\FileSystemInterface::deleteRecursive()
   */
  protected function fileUnmanagedDeleteRecursive($path, $callback = NULL): bool {
    if (isset($callback)) {
      call_user_func($callback, $path);
    }
    if (is_dir($path)) {
      $dir = dir($path);
      while (($entry = $dir->read()) !== FALSE) {
        if ($entry == '.' || $entry == '..') {
          continue;
        }
        $entry_path = $path . '/' . $entry;
        $this->fileUnmanagedDeleteRecursive($entry_path, $callback);
      }
      $dir->close();

      return rmdir($path);
    }
    return unlink($path);
  }

}