Newer
Older

Adam G-H
committed
<?php
namespace Drupal\Tests\package_manager\Kernel;
use Drupal\Tests\package_manager\Traits\FixtureUtilityTrait;
use PHPUnit\Framework\AssertionFailedError;
use Symfony\Component\Filesystem\Filesystem;

Adam G-H
committed
/**
* @coversDefaultClass \Drupal\Tests\package_manager\Traits\FixtureUtilityTrait
*
* @group package_manager
*/
class FixtureUtilityTraitTest extends PackageManagerKernelTestBase {
use FixtureUtilityTrait;
/**
* The root directory of the virtual project.
*
* @var string
*/
private string $dir;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->dir = $this->container->get('package_manager.path_locator')
->getProjectRoot();
$this->addPackage($this->dir, [
'name' => 'my/package',

Ted Bowman
committed
'type' => 'library',
]);

Adam G-H
committed
$this->addPackage($this->dir, [
'name' => 'my/dev-package',
'version' => '2.1.0',

Ted Bowman
committed
'type' => 'library',
'install_path' => '../relative/path',
],
TRUE,
);

Adam G-H
committed
}
/**
* @covers ::addPackage
*/
public function testAddPackage(): void {
// Packages cannot be added without a name.
try {
$this->addPackage($this->dir, ['type' => 'unknown']);
$this->fail('Adding an anonymous package should raise an error.');
}
catch (AssertionFailedError $e) {
$this->assertSame("Failed asserting that an array has the key 'name'.", $e->getMessage());
}

Ted Bowman
committed
// Packages cannot be added without a type.
try {
$this->addPackage($this->dir, ['name' => 'unknown']);
$this->fail('Adding an package without a type should raise an error.');
}
catch (AssertionFailedError $e) {
$this->assertSame("Failed asserting that an array has the key 'type'.", $e->getMessage());
}

Adam G-H
committed
// We should not be able to add an existing package.
try {

Ted Bowman
committed
$this->addPackage($this->dir, [
'name' => 'my/package',
'type' => 'library',
]);

Adam G-H
committed
$this->fail('Trying to add an existing package should raise an error.');
}
catch (AssertionFailedError $e) {
$this->assertStringContainsString("Expected package 'my/package' to not be installed, but it was.", $e->getMessage());
}
// We should not be able to add a package with an absolute installation
// path.
try {
$this->addPackage($this->dir, [
'name' => 'absolute/path',
'install_path' => '/absolute/path',

Ted Bowman
committed
'type' => 'library',
]);
$this->fail('Add package should have failed.');
}
catch (AssertionFailedError $e) {
$this->assertSame('Failed asserting that \'/absolute/path\' starts with "../".', $e->getMessage());
}
$installed_json_expected_packages = [

Adam G-H
committed
'my/package' => [
'name' => 'my/package',

Ted Bowman
committed
'type' => 'library',

Adam G-H
committed
],
'my/dev-package' => [
'name' => 'my/dev-package',
'version' => '2.1.0',

Ted Bowman
committed
'type' => 'library',

Adam G-H
committed
],
];
$installed_php_expected_packages = $installed_json_expected_packages;

Adam G-H
committed
[$installed_json, $installed_php] = $this->getData();
$installed_json['packages'] = array_intersect_key($installed_json['packages'], $installed_json_expected_packages);
$this->assertSame($installed_json_expected_packages, $installed_json['packages']);

Adam G-H
committed
$this->assertContains('my/dev-package', $installed_json['dev-package-names']);
$this->assertNotContains('my/package', $installed_json['dev-package-names']);
// In installed.php, the relative installation path of my/dev-package should
// have been prefixed with the __DIR__ constant, which should be interpreted
// when installed.php is loaded by the PHP runtime.
$installed_php_expected_packages['my/dev-package']['install_path'] = "$this->dir/vendor/composer/../relative/path";

Kunal Sachdev
committed
$installed_php_expected_packages = [
'drupal/core' => [
'name' => 'drupal/core',
'version' => '9.8.0',
'type' => 'drupal-core',
],
'drupal/core-recommended' => [
'name' => 'drupal/core-recommended',
'version' => '9.8.0',
'type' => 'drupal-core',
],
'drupal/core-dev' => [
'name' => 'drupal/core-dev',
'version' => '9.8.0',

Kunal Sachdev
committed
'type' => 'drupal-core',
],
] + $installed_php_expected_packages;
$this->assertSame($installed_php_expected_packages, $installed_php);

Adam G-H
committed
}
/**
* @covers ::modifyPackage
*/
public function testModifyPackage(): void {
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
$fs = (new Filesystem());
// Assert ::modifyPackage() works with a package in an existing fixture not
// created by ::addPackage().
$existing_fixture = __DIR__ . '/../../fixtures/FixtureUtilityTraitTest/existing_correct_fixture';
$temp_fixture = $this->siteDirectory . $this->randomMachineName('42');
$fs->mirror($existing_fixture, $temp_fixture);
$decode_installed_json = function () use ($temp_fixture) {
return json_decode(file_get_contents($temp_fixture . '/vendor/composer/installed.json'), TRUE, 512, JSON_THROW_ON_ERROR);
};
$original_installed_json = $decode_installed_json();
$this->assertIsArray($original_installed_json);
$this->modifyPackage(
$temp_fixture,
'the-org/the-package',
['install_path' => '../../a_new_path'],
);
$this->assertSame($original_installed_json, $decode_installed_json());
// Assert that ::modifyPackage() throws an error if a package exists in the
// 'installed.json' file but not the 'installed.php' file. We cannot test
// this with the trait functions because they cannot produce this starting
// point.
$existing_incorrect_fixture = __DIR__ . '/../../fixtures/FixtureUtilityTraitTest/missing_installed_php';
$temp_fixture = $this->siteDirectory . $this->randomMachineName('42');
$fs->mirror($existing_incorrect_fixture, $temp_fixture);
try {
$this->modifyPackage(
$temp_fixture,
'the-org/the-package',
['install_path' => '../../a_new_path'],
);
$this->fail('Modifying a non-existent package should raise an error.');
}
catch (AssertionFailedError $e) {
$this->assertStringContainsString("Failed asserting that an array has the key 'the-org/the-package'.", $e->getMessage());
}

Adam G-H
committed
// We should not be able to modify a non-existent package.
try {
$this->modifyPackage($this->dir, 'junk/drawer', ['type' => 'library']);
$this->fail('Modifying a non-existent package should raise an error.');
}
catch (AssertionFailedError $e) {
$this->assertStringContainsString("Expected package 'junk/drawer' to be installed, but it wasn't.", $e->getMessage());
}
// Add a key to an existing package.
$this->modifyPackage($this->dir, 'my/package', ['type' => 'metapackage']);
// Change a key in an existing package.
$this->modifyPackage($this->dir, 'my/dev-package', ['version' => '3.2.1']);
// Move an existing package to dev requirements.
$this->addPackage($this->dir, [
'name' => 'my/other-package',
'type' => 'library',
]);
$install_json_expected_packages = [

Adam G-H
committed
'my/package' => [
'name' => 'my/package',
'type' => 'metapackage',
],
'my/dev-package' => [
'name' => 'my/dev-package',
'version' => '3.2.1',

Ted Bowman
committed
'type' => 'library',

Adam G-H
committed
],
'my/other-package' => [
'name' => 'my/other-package',
'type' => 'library',
],
];
$installed_php_expected_packages = $install_json_expected_packages;
$installed_php_expected_packages['my/dev-package']['install_path'] = "$this->dir/vendor/composer/../relative/path";

Adam G-H
committed
[$installed_json, $installed_php] = $this->getData();
$installed_json['packages'] = array_intersect_key($installed_json['packages'], $install_json_expected_packages);
$this->assertSame($install_json_expected_packages, $installed_json['packages']);

Adam G-H
committed
$this->assertContains('my/dev-package', $installed_json['dev-package-names']);
$this->assertNotContains('my/other-package', $installed_json['dev-package-names']);

Adam G-H
committed
$this->assertNotContains('my/package', $installed_json['dev-package-names']);

Kunal Sachdev
committed
$installed_php_expected_packages = [
'drupal/core' => [
'name' => 'drupal/core',
'version' => '9.8.0',
'type' => 'drupal-core',
],
'drupal/core-recommended' => [
'name' => 'drupal/core-recommended',
'version' => '9.8.0',
'type' => 'drupal-core',
],
'drupal/core-dev' => [
'name' => 'drupal/core-dev',
'version' => '9.8.0',

Kunal Sachdev
committed
'type' => 'drupal-core',
],
] + $installed_php_expected_packages;
// @see ::testAddPackage()
$this->assertSame($installed_php_expected_packages, $installed_php);

Adam G-H
committed
}
/**
* @covers ::removePackage
*/
public function testRemovePackage(): void {
// We should not be able to remove a package that's not installed.
try {
$this->removePackage($this->dir, 'junk/drawer');
$this->fail('Removing a non-existent package should raise an error.');
}
catch (AssertionFailedError $e) {
$this->assertStringContainsString("Expected package 'junk/drawer' to be installed, but it wasn't.", $e->getMessage());
}
$this->removePackage($this->dir, 'my/package');
$this->removePackage($this->dir, 'my/dev-package');
foreach (['json', 'php'] as $extension) {
$file = "$this->dir/vendor/composer/installed.$extension";
$contents = file_get_contents($file);
$this->assertStringNotContainsString('my/package', $contents, "'my/package' not found in $file");
$this->assertStringNotContainsString('my/dev-package', $contents, "'my/dev-package' not found in $file");

Adam G-H
committed
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
}
}
/**
* Returns the data from installed.php and installed.json.
*
* @return array[]
* An array of two arrays. The first array will be the contents of
* installed.json, with the `packages` array keyed by package name. The
* second array will be the `versions` array from installed.php.
*/
private function getData(): array {
$installed_json = file_get_contents("$this->dir/vendor/composer/installed.json");
$installed_json = json_decode($installed_json, TRUE, 512, JSON_THROW_ON_ERROR);
$keyed_packages = [];
foreach ($installed_json['packages'] as $package) {
$keyed_packages[$package['name']] = $package;
}
$installed_json['packages'] = $keyed_packages;
$installed_php = require "$this->dir/vendor/composer/installed.php";
return [
$installed_json,
$installed_php['versions'],
];
}
}