You are here

class ComposerHookTest in Drupal 8

Same name and namespace in other branches
  1. 9 core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ComposerHookTest.php \Drupal\Tests\Composer\Plugin\Scaffold\Functional\ComposerHookTest
  2. 10 core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ComposerHookTest.php \Drupal\Tests\Composer\Plugin\Scaffold\Functional\ComposerHookTest

Tests Composer Hooks that run scaffold operations.

The purpose of this test file is to exercise all of the different Composer commands that invoke scaffold operations, and ensure that files are scaffolded when they should be.

Note that this test file uses `exec` to run Composer for a pure functional test. Other functional test files invoke Composer commands directly via the Composer Application object, in order to get more accurate test coverage information.

@group Scaffold

Hierarchy

Expanded class hierarchy of ComposerHookTest

File

core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ComposerHookTest.php, line 26

Namespace

Drupal\Tests\Composer\Plugin\Scaffold\Functional
View source
class ComposerHookTest extends TestCase {
  use ExecTrait;
  use AssertUtilsTrait;
  use PhpunitCompatibilityTrait;

  /**
   * Directory to perform the tests in.
   *
   * @var string
   */
  protected $fixturesDir;

  /**
   * The Symfony FileSystem component.
   *
   * @var \Symfony\Component\Filesystem\Filesystem
   */
  protected $fileSystem;

  /**
   * The Fixtures object.
   *
   * @var \Drupal\Tests\Composer\Plugin\Scaffold\Fixtures
   */
  protected $fixtures;

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    $this->fileSystem = new Filesystem();
    $this->fixtures = new Fixtures();
    $this->fixtures
      ->createIsolatedComposerCacheDir();
    $this->fixturesDir = $this->fixtures
      ->tmpDir($this
      ->getName());
    $replacements = [
      'SYMLINK' => 'false',
      'PROJECT_ROOT' => $this->fixtures
        ->projectRoot(),
    ];
    $this->fixtures
      ->cloneFixtureProjects($this->fixturesDir, $replacements);
  }

  /**
   * {@inheritdoc}
   */
  protected function tearDown() {

    // Remove any temporary directories et. al. that were created.
    $this->fixtures
      ->tearDown();
  }

  /**
   * Test to see if scaffold operation runs at the correct times.
   */
  public function testComposerHooks() {
    $topLevelProjectDir = 'composer-hooks-fixture';
    $sut = $this->fixturesDir . '/' . $topLevelProjectDir;

    // First test: run composer install. This is the same as composer update
    // since there is no lock file. Ensure that scaffold operation ran.
    $this
      ->mustExec("composer install --no-ansi", $sut);
    $this
      ->assertScaffoldedFile($sut . '/sites/default/default.settings.php', FALSE, 'Test version of default.settings.php from drupal/core');

    // Run composer required to add in the scaffold-override-fixture. This
    // project is "allowed" in our main fixture project, but not required.
    // We expect that requiring this library should re-scaffold, resulting
    // in a changed default.settings.php file.
    $stdout = $this
      ->mustExec("composer require --no-ansi --no-interaction fixtures/scaffold-override-fixture:dev-master", $sut);
    $this
      ->assertScaffoldedFile($sut . '/sites/default/default.settings.php', FALSE, 'scaffolded from the scaffold-override-fixture');

    // Make sure that the appropriate notice informing us that scaffolding
    // is allowed was printed.
    $this
      ->assertStringContainsString('Package fixtures/scaffold-override-fixture has scaffold operations, and is already allowed in the root-level composer.json file.', $stdout);

    // Delete one scaffold file, just for test purposes, then run
    // 'composer update' and see if the scaffold file is replaced.
    @unlink($sut . '/sites/default/default.settings.php');
    $this
      ->assertFileNotExists($sut . '/sites/default/default.settings.php');
    $this
      ->mustExec("composer update --no-ansi", $sut);
    $this
      ->assertScaffoldedFile($sut . '/sites/default/default.settings.php', FALSE, 'scaffolded from the scaffold-override-fixture');

    // Delete the same test scaffold file again, then run
    // 'composer drupal:scaffold' and see if the scaffold file is
    // re-scaffolded.
    @unlink($sut . '/sites/default/default.settings.php');
    $this
      ->assertFileNotExists($sut . '/sites/default/default.settings.php');
    $this
      ->mustExec("composer install --no-ansi", $sut);
    $this
      ->assertScaffoldedFile($sut . '/sites/default/default.settings.php', FALSE, 'scaffolded from the scaffold-override-fixture');

    // Delete the same test scaffold file yet again, then run
    // 'composer install' and see if the scaffold file is re-scaffolded.
    @unlink($sut . '/sites/default/default.settings.php');
    $this
      ->assertFileNotExists($sut . '/sites/default/default.settings.php');
    $this
      ->mustExec("composer drupal:scaffold --no-ansi", $sut);
    $this
      ->assertScaffoldedFile($sut . '/sites/default/default.settings.php', FALSE, 'scaffolded from the scaffold-override-fixture');

    // Run 'composer create-project' to create a new test project called
    // 'create-project-test', which is a copy of 'fixtures/drupal-drupal'.
    $sut = $this->fixturesDir . '/create-project-test';
    $filesystem = new Filesystem();
    $filesystem
      ->remove($sut);
    $stdout = $this
      ->mustExec("composer create-project --repository=packages.json fixtures/drupal-drupal {$sut}", $this->fixturesDir, [
      'COMPOSER_MIRROR_PATH_REPOS' => 1,
    ]);
    $this
      ->assertDirectoryExists($sut);
    $this
      ->assertStringContainsString('Scaffolding files for fixtures/drupal-drupal', $stdout);
    $this
      ->assertScaffoldedFile($sut . '/index.php', FALSE, 'Test version of index.php from drupal/core');
    $topLevelProjectDir = 'composer-hooks-nothing-allowed-fixture';
    $sut = $this->fixturesDir . '/' . $topLevelProjectDir;

    // Run composer install on an empty project.
    $this
      ->mustExec("composer install --no-ansi", $sut);

    // Require a project that is not allowed to scaffold and confirm that we
    // get a warning, and it does not scaffold.
    $stdout = $this
      ->mustExec("composer require --no-ansi --no-interaction fixtures/scaffold-override-fixture:dev-master", $sut);
    $this
      ->assertFileNotExists($sut . '/sites/default/default.settings.php');
    $this
      ->assertStringContainsString("Not scaffolding files for fixtures/scaffold-override-fixture, because it is not listed in the element 'extra.drupal-scaffold.allowed-packages' in the root-level composer.json file.", $stdout);
  }

  /**
   * Test to see if scaffold messages are omitted when running scaffold twice.
   */
  public function testScaffoldMessagesDoNotPrintTwice() {
    $topLevelProjectDir = 'drupal-drupal';
    $sut = $this->fixturesDir . '/' . $topLevelProjectDir;

    // First test: run composer install. This is the same as composer update
    // since there is no lock file. Ensure that scaffold operation ran.
    $stdout = $this
      ->mustExec("composer install --no-ansi", $sut);
    $this
      ->assertStringContainsString('- Copy [web-root]/index.php from assets/index.php', $stdout);
    $this
      ->assertStringContainsString('- Copy [web-root]/update.php from assets/update.php', $stdout);

    // Run scaffold operation again. It should not print anything.
    $stdout = $this
      ->mustExec("composer scaffold --no-ansi", $sut);
    $this
      ->assertEquals('', $stdout);

    // Delete a file and run it again. It should re-scaffold the removed file.
    unlink("{$sut}/index.php");
    $stdout = $this
      ->mustExec("composer scaffold --no-ansi", $sut);
    $this
      ->assertStringContainsString('- Copy [web-root]/index.php from assets/index.php', $stdout);
    $this
      ->assertStringNotContainsString('- Copy [web-root]/update.php from assets/update.php', $stdout);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AssertUtilsTrait::assertScaffoldedFile protected function Asserts that a given file exists and is/is not a symlink.
AssertUtilsTrait::assertScaffoldedFileDoesNotContain protected function Asserts that a file does not exist or exists and does not contain a value.
ComposerHookTest::$fileSystem protected property The Symfony FileSystem component.
ComposerHookTest::$fixtures protected property The Fixtures object.
ComposerHookTest::$fixturesDir protected property Directory to perform the tests in.
ComposerHookTest::setUp protected function
ComposerHookTest::tearDown protected function
ComposerHookTest::testComposerHooks public function Test to see if scaffold operation runs at the correct times.
ComposerHookTest::testScaffoldMessagesDoNotPrintTwice public function Test to see if scaffold messages are omitted when running scaffold twice.
ExecTrait::mustExec protected function Runs an arbitrary command.
PhpunitCompatibilityTrait::getMock Deprecated public function Returns a mock object for the specified class using the available method.
PhpunitCompatibilityTrait::setExpectedException Deprecated public function Compatibility layer for PHPUnit 6 to support PHPUnit 4 code.