3 namespace DrupalComposer\DrupalScaffold\Tests;
5 use Composer\Util\Filesystem;
6 use PHPUnit\Framework\TestCase;
9 * Tests composer plugin functionality.
11 class PluginTest extends TestCase {
14 * @var \Composer\Util\Filesystem
31 protected $tmpReleaseTag;
36 public function setUp() {
37 $this->rootDir = realpath(realpath(__DIR__ . '/..'));
39 // Prepare temp directory.
40 $this->fs = new Filesystem();
41 $this->tmpDir = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . 'drupal-scaffold';
42 $this->ensureDirectoryExistsAndClear($this->tmpDir);
44 $this->writeTestReleaseTag();
45 $this->writeComposerJSON();
55 public function tearDown() {
56 $this->fs->removeDirectory($this->tmpDir);
57 $this->git(sprintf('tag -d "%s"', $this->tmpReleaseTag));
61 * Tests a simple composer install without core, but adding core later.
63 public function testComposerInstallAndUpdate() {
64 $exampleScaffoldFile = $this->tmpDir . DIRECTORY_SEPARATOR . 'index.php';
65 $this->assertFileNotExists($exampleScaffoldFile, 'Scaffold file should not be exist.');
66 $this->composer('install --no-dev --prefer-dist');
67 $this->assertFileExists($this->tmpDir . DIRECTORY_SEPARATOR . 'core', 'Drupal core is installed.');
68 $this->assertFileExists($exampleScaffoldFile, 'Scaffold file should be automatically installed.');
69 $this->fs->remove($exampleScaffoldFile);
70 $this->assertFileNotExists($exampleScaffoldFile, 'Scaffold file should not be exist.');
71 $this->composer('drupal:scaffold');
72 $this->assertFileExists($exampleScaffoldFile, 'Scaffold file should be installed by "drupal:scaffold" command.');
74 foreach (['8.0.1', '8.1.x-dev', '8.3.0', '8.5.x-dev'] as $version) {
75 // We touch a scaffold file, so we can check the file was modified after
76 // the scaffold update.
77 touch($exampleScaffoldFile);
78 $mtime_touched = filemtime($exampleScaffoldFile);
79 // Requiring a newer version triggers "composer update".
80 $this->composer('require --update-with-dependencies --prefer-dist --update-no-dev drupal/core:"' . $version . '"');
82 $mtime_after = filemtime($exampleScaffoldFile);
83 $this->assertNotEquals($mtime_after, $mtime_touched, 'Scaffold file was modified by composer update. (' . $version . ')');
87 $this->assertFileExists($this->tmpDir . DIRECTORY_SEPARATOR . '.eslintrc');
88 $this->assertFileNotExists($this->tmpDir . DIRECTORY_SEPARATOR . '.eslintrc.json');
89 $this->assertFileNotExists($this->tmpDir . DIRECTORY_SEPARATOR . '.ht.router.php');
93 // Note we don't clean up .eslintrc file.
94 $this->assertFileExists($this->tmpDir . DIRECTORY_SEPARATOR . '.eslintrc');
95 $this->assertFileExists($this->tmpDir . DIRECTORY_SEPARATOR . '.eslintrc.json');
96 $this->assertFileNotExists($this->tmpDir . DIRECTORY_SEPARATOR . '.ht.router.php');
100 $this->assertFileExists($this->tmpDir . DIRECTORY_SEPARATOR . '.eslintrc');
101 $this->assertFileExists($this->tmpDir . DIRECTORY_SEPARATOR . '.eslintrc.json');
102 $this->assertFileExists($this->tmpDir . DIRECTORY_SEPARATOR . '.ht.router.php');
107 // We touch a scaffold file, so we can check the file was modified by the
109 file_put_contents($exampleScaffoldFile, 1);
110 $this->composer('drupal:scaffold');
111 $this->assertNotEquals(file_get_contents($exampleScaffoldFile), 1, 'Scaffold file was modified by custom command.');
115 * Writes the default composer json to the temp direcoty.
117 protected function writeComposerJSON() {
118 $json = json_encode($this->composerJSONDefaults(), JSON_PRETTY_PRINT);
119 // Write composer.json.
120 file_put_contents($this->tmpDir . '/composer.json', $json);
124 * Writes a tag for the current commit, so we can reference it directly in the
127 protected function writeTestReleaseTag() {
128 // Tag the current state.
129 $this->tmpReleaseTag = '999.0.' . time();
130 $this->git(sprintf('tag -a "%s" -m "%s"', $this->tmpReleaseTag, 'Tag for testing this exact commit'));
134 * Provides the default composer.json data.
138 protected function composerJSONDefaults() {
140 'repositories' => array(
143 'url' => $this->rootDir,
147 'drupal-composer/drupal-scaffold' => $this->tmpReleaseTag,
148 'composer/installers' => '^1.0.20',
149 'drupal/core' => '8.0.0',
151 'minimum-stability' => 'dev',
156 * Wrapper for the composer command.
158 * @param string $command
159 * Composer command name, arguments and/or options.
161 protected function composer($command) {
162 chdir($this->tmpDir);
163 passthru(escapeshellcmd($this->rootDir . '/vendor/bin/composer ' . $command), $exit_code);
164 if ($exit_code !== 0) {
165 throw new \Exception('Composer returned a non-zero exit code');
170 * Wrapper for git command in the root directory.
173 * Git command name, arguments and/or options.
175 protected function git($command) {
176 chdir($this->rootDir);
177 passthru(escapeshellcmd('git ' . $command), $exit_code);
178 if ($exit_code !== 0) {
179 throw new \Exception('Git returned a non-zero exit code');
184 * Makes sure the given directory exists and has no content.
186 * @param string $directory
188 protected function ensureDirectoryExistsAndClear($directory) {
189 if (is_dir($directory)) {
190 $this->fs->removeDirectory($directory);
192 mkdir($directory, 0777, TRUE);