class ComposerHookTest

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. 8.9.x core/tests/Drupal/Tests/Composer/Plugin/Scaffold/Functional/ComposerHookTest.php \Drupal\Tests\Composer\Plugin\Scaffold\Functional\ComposerHookTest
  3. 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 27

Namespace

Drupal\Tests\Composer\Plugin\Scaffold\Functional
View source
class ComposerHookTest extends BuildTestBase {
    use ExecTrait;
    use AssertUtilsTrait;
    
    /**
     * 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() : void {
        parent::setUp();
        $this->fileSystem = new Filesystem();
        $this->fixtures = new Fixtures();
        $this->fixtures
            ->createIsolatedComposerCacheDir();
        $this->fixturesDir = $this->fixtures
            ->tmpDir($this->name());
        $replacements = [
            'SYMLINK' => 'false',
            'PROJECT_ROOT' => $this->fixtures
                ->projectRoot(),
        ];
        $this->fixtures
            ->cloneFixtureProjects($this->fixturesDir, $replacements);
    }
    
    /**
     * {@inheritdoc}
     */
    protected function tearDown() : void {
        // Remove any temporary directories et. al. that were created.
        $this->fixtures
            ->tearDown();
        parent::tearDown();
    }
    
    /**
     * Tests to see if scaffold operation runs at the correct times.
     */
    public function testComposerHooks() : void {
        $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/drupal-assets-fixture:dev-main fixtures/scaffold-override-fixture:dev-main", $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->assertFileDoesNotExist($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->assertFileDoesNotExist($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->assertFileDoesNotExist($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');
    }
    
    /**
     * Tests to see if scaffold messages are omitted when running scaffold twice.
     */
    public function testScaffoldMessagesDoNotPrintTwice() : void {
        $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);
    }
    
    /**
     * Tests to see if scaffold events are dispatched and picked up by the plugin.
     */
    public function testScaffoldEvents() : void {
        $topLevelProjectDir = 'scaffold-events-fixture';
        $sut = $this->fixturesDir . '/' . $topLevelProjectDir;
        $output = $this->mustExec("composer install --no-ansi", $sut);
        $this->assertStringContainsString('Hello preDrupalScaffoldCmd', $output);
        $this->assertStringContainsString('Hello postDrupalScaffoldCmd', $output);
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
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.
BuildTestBase::$commandProcess private property The most recent command process.
BuildTestBase::$destroyBuild protected property Default to destroying build artifacts after a test finishes.
BuildTestBase::$hostName private static property Our native host name, used by PHP when it starts up the server.
BuildTestBase::$hostPort private property Port that will be tested.
BuildTestBase::$mink private property The Mink session manager.
BuildTestBase::$phpFinder private property The PHP executable finder.
BuildTestBase::$portLocks private property A list of ports used by the test.
BuildTestBase::$serverDocroot private property The docroot for the server process.
BuildTestBase::$serverProcess private property The process that's running the HTTP server.
BuildTestBase::$workspaceDir private property The working directory where this test will manipulate files.
BuildTestBase::assertCommandExitCode public function Asserts that the last command returned the specified exit code.
BuildTestBase::assertCommandOutputContains public function Assert that text is present in the output of the most recent command.
BuildTestBase::assertCommandSuccessful public function Asserts that the last command ran without error.
BuildTestBase::assertDrupalVisit public function Helper function to assert that the last visit was a Drupal site.
BuildTestBase::assertErrorOutputContains public function Assert that text is present in the error output of the most recent command.
BuildTestBase::assertErrorOutputNotContains public function Assert text is not present in the error output of the most recent command.
BuildTestBase::checkPortIsAvailable protected function Checks whether a port is available.
BuildTestBase::copyCodebase public function Copy the current working codebase into a workspace.
BuildTestBase::executeCommand public function Run a command.
BuildTestBase::findAvailablePort protected function Discover an available port number.
BuildTestBase::getCodebaseFinder public function Get a default Finder object for a Drupal codebase.
BuildTestBase::getComposerRoot public function Gets the path to the Composer root directory.
BuildTestBase::getDrupalRoot public function Get the root path of this Drupal codebase.
BuildTestBase::getDrupalRootStatic public static function Get the root path of this Drupal codebase.
BuildTestBase::getMink public function Get the Mink instance.
BuildTestBase::getPortNumber protected function Get the port number for requests.
BuildTestBase::getWorkingPath protected function Get the working directory within the workspace, creating if necessary.
BuildTestBase::getWorkingPathDrupalRoot public function Gets the working path for Drupal core.
BuildTestBase::getWorkspaceDirectory public function Full path to the workspace where this test can build.
BuildTestBase::getWorkspaceDrupalRoot public function Gets the path to Drupal root in the workspace directory.
BuildTestBase::initMink protected function Set up the Mink session manager.
BuildTestBase::instantiateServer protected function Do the work of making a server process.
BuildTestBase::standUpServer protected function Makes a local test server using PHP's internal HTTP server.
BuildTestBase::stopServer protected function Stop the HTTP server, zero out all necessary variables.
BuildTestBase::visit public function Visit a URI on the HTTP server.
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 Overrides BuildTestBase::setUp
ComposerHookTest::tearDown protected function Overrides BuildTestBase::tearDown
ComposerHookTest::testComposerHooks public function Tests to see if scaffold operation runs at the correct times.
ComposerHookTest::testScaffoldEvents public function Tests to see if scaffold events are dispatched and picked up by the plugin.
ComposerHookTest::testScaffoldMessagesDoNotPrintTwice public function Tests to see if scaffold messages are omitted when running scaffold twice.
ExecTrait::mustExec protected function Runs an arbitrary command.
RequiresComposerTrait::requiresComposer public static function

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.