View source
<?php
namespace Drupal\Tests;
use Drupal\Composer\Plugin\VendorHardening\Config;
use Drupal\Tests\Composer\ComposerIntegrationTrait;
use Symfony\Component\Finder\Finder;
class ComposerIntegrationTest extends UnitTestCase {
use ComposerIntegrationTrait;
public function testComposerLockHash() {
$content_hash = self::getContentHash(file_get_contents($this->root . '/composer.json'));
$lock = json_decode(file_get_contents($this->root . '/composer.lock'), TRUE);
$this
->assertSame($content_hash, $lock['content-hash']);
$core_lock_file_hash = '';
$options = [];
foreach ($lock['packages'] as $package) {
if ($package['name'] === 'drupal/core') {
$core_lock_file_hash = $package['dist']['reference'];
$options = $package['transport-options'] ?? [];
break;
}
}
$core_content_hash = sha1(file_get_contents($this->root . '/core/composer.json') . serialize($options));
$this
->assertSame($core_content_hash, $core_lock_file_hash);
}
public function testComposerTilde($path) {
if (preg_match('#composer/Metapackage/CoreRecommended/composer.json$#', $path)) {
$this
->markTestSkipped("{$path} has tilde");
}
$content = json_decode(file_get_contents($path), TRUE);
$composer_keys = array_intersect([
'require',
'require-dev',
], array_keys($content));
if (empty($composer_keys)) {
$this
->markTestSkipped("{$path} has no keys to test");
}
foreach ($composer_keys as $composer_key) {
foreach ($content[$composer_key] as $dependency => $version) {
if (strpos($dependency, 'symfony/') === 0) {
continue;
}
$this
->assertStringNotContainsString('~', $version, "Dependency {$dependency} in {$path} contains a tilde, use a caret.");
}
}
}
public function providerTestComposerJson() {
$data = [];
$composer_json_finder = $this
->getComposerJsonFinder(realpath(__DIR__ . '/../../../../'));
foreach ($composer_json_finder
->getIterator() as $composer_json) {
$data[$composer_json
->getPathname()] = [
$composer_json
->getPathname(),
];
}
return $data;
}
public function testAllCoreComponentsReplaced() : void {
$components_path = $this->root . '/core/lib/Drupal/Component';
$json = json_decode(file_get_contents($this->root . '/core/composer.json'), FALSE);
$composer_replace_packages = (array) $json->replace;
$components_composer_json_files = [];
$composer_json_finder = new Finder();
$composer_json_finder
->name('composer.json')
->in($components_path)
->ignoreUnreadableDirs();
foreach ($composer_json_finder
->getIterator() as $composer_json) {
$components_composer_json_files[$composer_json
->getPathname()] = [
$composer_json
->getPathname(),
];
}
$this
->assertNotEmpty($components_composer_json_files);
$this
->assertCount(count($composer_replace_packages), $components_composer_json_files);
foreach ($components_composer_json_files as $components_composer_json_file) {
$json = json_decode(file_get_contents(reset($components_composer_json_file)), FALSE);
$component_name = $json->name;
$this
->assertArrayHasKey($component_name, $composer_replace_packages, 'Unable to find ' . $component_name . ' in replace list of composer.json');
}
}
public function providerTestExpectedScaffoldFiles() {
return [
[
'.editorconfig',
'assets/scaffold/files/editorconfig',
'[project-root]',
],
[
'.gitattributes',
'assets/scaffold/files/gitattributes',
'[project-root]',
],
[
'.csslintrc',
'assets/scaffold/files/csslintrc',
],
[
'.eslintignore',
'assets/scaffold/files/eslintignore',
],
[
'.eslintrc.json',
'assets/scaffold/files/eslintrc.json',
],
[
'.ht.router.php',
'assets/scaffold/files/ht.router.php',
],
[
'.htaccess',
'assets/scaffold/files/htaccess',
],
[
'example.gitignore',
'assets/scaffold/files/example.gitignore',
],
[
'index.php',
'assets/scaffold/files/index.php',
],
[
'INSTALL.txt',
'assets/scaffold/files/drupal.INSTALL.txt',
],
[
'README.md',
'assets/scaffold/files/drupal.README.md',
],
[
'robots.txt',
'assets/scaffold/files/robots.txt',
],
[
'update.php',
'assets/scaffold/files/update.php',
],
[
'web.config',
'assets/scaffold/files/web.config',
],
[
'sites/README.txt',
'assets/scaffold/files/sites.README.txt',
],
[
'sites/development.services.yml',
'assets/scaffold/files/development.services.yml',
],
[
'sites/example.settings.local.php',
'assets/scaffold/files/example.settings.local.php',
],
[
'sites/example.sites.php',
'assets/scaffold/files/example.sites.php',
],
[
'sites/default/default.services.yml',
'assets/scaffold/files/default.services.yml',
],
[
'sites/default/default.settings.php',
'assets/scaffold/files/default.settings.php',
],
[
'modules/README.txt',
'assets/scaffold/files/modules.README.txt',
],
[
'profiles/README.txt',
'assets/scaffold/files/profiles.README.txt',
],
[
'themes/README.txt',
'assets/scaffold/files/themes.README.txt',
],
];
}
public function testExpectedScaffoldFiles($destRelPath, $sourceRelPath, $expectedDestination = '[web-root]') {
$json = json_decode(file_get_contents($this->root . '/core/composer.json'));
$scaffold_file_mapping = (array) $json->extra->{'drupal-scaffold'}->{'file-mapping'};
$this
->assertArrayHasKey("{$expectedDestination}/{$destRelPath}", $scaffold_file_mapping);
$this
->assertEquals($sourceRelPath, $scaffold_file_mapping["{$expectedDestination}/{$destRelPath}"]);
$this
->assertFileExists($this->root . '/core/' . $sourceRelPath);
$this
->assertFileExists($this->root . '/' . $destRelPath);
$this
->assertFileEquals($this->root . '/core/' . $sourceRelPath, $this->root . '/' . $destRelPath, 'Scaffold source and destination files must have the same contents.');
}
protected static function getContentHash($composerFileContents) {
$content = json_decode($composerFileContents, true);
$relevantKeys = array(
'name',
'version',
'require',
'require-dev',
'conflict',
'replace',
'provide',
'minimum-stability',
'prefer-stable',
'repositories',
'extra',
);
$relevantContent = array();
foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
$relevantContent[$key] = $content[$key];
}
if (isset($content['config']['platform'])) {
$relevantContent['config']['platform'] = $content['config']['platform'];
}
ksort($relevantContent);
return md5(json_encode($relevantContent));
}
public function testVendorCleanup() : void {
$lock = json_decode(file_get_contents($this->root . '/composer.lock'), TRUE);
$packages = [];
foreach (array_merge($lock['packages'], $lock['packages-dev']) as $package) {
$packages[] = $package['name'];
}
$reflection = new \ReflectionProperty(Config::class, 'defaultConfig');
$reflection
->setAccessible(TRUE);
$config = $reflection
->getValue();
foreach (array_keys($config) as $package) {
$this
->assertContains(strtolower($package), $packages);
}
}
}