diff --git a/tests/fixtures/project_staged_validation/new_project_added/active/vendor/composer/installed.json b/tests/fixtures/project_staged_validation/new_project_added/active.installed.json similarity index 74% rename from tests/fixtures/project_staged_validation/new_project_added/active/vendor/composer/installed.json rename to tests/fixtures/project_staged_validation/new_project_added/active.installed.json index df420decb6b9afd2f34b48172f32c736e2cec1f6..56d81ccad175d109123acfc364f7240c77a897ab 100644 --- a/tests/fixtures/project_staged_validation/new_project_added/active/vendor/composer/installed.json +++ b/tests/fixtures/project_staged_validation/new_project_added/active.installed.json @@ -1,4 +1,9 @@ { + "_readme": [ + "This file simuluates a list of packages installed in the active directory of a virtual project.", + "It will be compared against staged.installed.json.", + "See \\Drupal\\Tests\\automatic_updates\\Kernel\\ReadinessValidation\\StagedProjectsValidatorTest::testErrors()" + ], "packages": [ { "name": "drupal/core", diff --git a/tests/fixtures/project_staged_validation/new_project_added/active/composer.json b/tests/fixtures/project_staged_validation/new_project_added/active/composer.json deleted file mode 100644 index 0967ef424bce6791893e9a57bb952f80fd536e93..0000000000000000000000000000000000000000 --- a/tests/fixtures/project_staged_validation/new_project_added/active/composer.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/tests/fixtures/project_staged_validation/new_project_added/staged/vendor/composer/installed.json b/tests/fixtures/project_staged_validation/new_project_added/staged.installed.json similarity index 80% rename from tests/fixtures/project_staged_validation/new_project_added/staged/vendor/composer/installed.json rename to tests/fixtures/project_staged_validation/new_project_added/staged.installed.json index db60c8425c0a5a33340c7436d494b62e3c2a7059..b0c0c6d63ef6dd498e15898fbdbabb92a9ee89c0 100644 --- a/tests/fixtures/project_staged_validation/new_project_added/staged/vendor/composer/installed.json +++ b/tests/fixtures/project_staged_validation/new_project_added/staged.installed.json @@ -1,4 +1,9 @@ { + "_readme": [ + "This file simuluates a list of packages installed in a virtual staging area.", + "It will be compared against active.installed.json.", + "See \\Drupal\\Tests\\automatic_updates\\Kernel\\ReadinessValidation\\StagedProjectsValidatorTest::testErrors()" + ], "packages": [ { "name": "drupal/core", diff --git a/tests/fixtures/project_staged_validation/new_project_added/staged/composer.json b/tests/fixtures/project_staged_validation/new_project_added/staged/composer.json deleted file mode 100644 index 0967ef424bce6791893e9a57bb952f80fd536e93..0000000000000000000000000000000000000000 --- a/tests/fixtures/project_staged_validation/new_project_added/staged/composer.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/tests/fixtures/project_staged_validation/no_errors/active/vendor/composer/installed.json b/tests/fixtures/project_staged_validation/no_errors/active.installed.json similarity index 81% rename from tests/fixtures/project_staged_validation/no_errors/active/vendor/composer/installed.json rename to tests/fixtures/project_staged_validation/no_errors/active.installed.json index cc5be9cb71d644d6cf9e7735f865a287a4853c59..65a8de94c62077e2e1d222508e1ba496bf21985a 100644 --- a/tests/fixtures/project_staged_validation/no_errors/active/vendor/composer/installed.json +++ b/tests/fixtures/project_staged_validation/no_errors/active.installed.json @@ -1,4 +1,9 @@ { + "_readme": [ + "This file simuluates a list of packages installed in the active directory of a virtual project.", + "It will be compared against staged.installed.json.", + "See \\Drupal\\Tests\\automatic_updates\\Kernel\\ReadinessValidation\\StagedProjectsValidatorTest::testErrors()" + ], "packages": [ { "name": "drupal/core", diff --git a/tests/fixtures/project_staged_validation/no_errors/active/composer.json b/tests/fixtures/project_staged_validation/no_errors/active/composer.json deleted file mode 100644 index 0967ef424bce6791893e9a57bb952f80fd536e93..0000000000000000000000000000000000000000 --- a/tests/fixtures/project_staged_validation/no_errors/active/composer.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/tests/fixtures/project_staged_validation/no_errors/composer.json b/tests/fixtures/project_staged_validation/no_errors/composer.json deleted file mode 100644 index 0967ef424bce6791893e9a57bb952f80fd536e93..0000000000000000000000000000000000000000 --- a/tests/fixtures/project_staged_validation/no_errors/composer.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/tests/fixtures/project_staged_validation/no_errors/staged/vendor/composer/installed.json b/tests/fixtures/project_staged_validation/no_errors/staged.installed.json similarity index 82% rename from tests/fixtures/project_staged_validation/no_errors/staged/vendor/composer/installed.json rename to tests/fixtures/project_staged_validation/no_errors/staged.installed.json index e7061278bd8b42cd337d4457ea5d612f690ef23b..f3955584890fdd369df5f31f3c053ed933f957b1 100644 --- a/tests/fixtures/project_staged_validation/no_errors/staged/vendor/composer/installed.json +++ b/tests/fixtures/project_staged_validation/no_errors/staged.installed.json @@ -1,4 +1,9 @@ { + "_readme": [ + "This file simuluates a list of packages installed in a virtual staging area.", + "It will be compared against active.installed.json.", + "See \\Drupal\\Tests\\automatic_updates\\Kernel\\ReadinessValidation\\StagedProjectsValidatorTest::testErrors()" + ], "packages": [ { "name": "drupal/core", diff --git a/tests/fixtures/project_staged_validation/no_errors/staged/composer.json b/tests/fixtures/project_staged_validation/no_errors/staged/composer.json deleted file mode 100644 index 0967ef424bce6791893e9a57bb952f80fd536e93..0000000000000000000000000000000000000000 --- a/tests/fixtures/project_staged_validation/no_errors/staged/composer.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/tests/fixtures/project_staged_validation/project_removed/active/vendor/composer/installed.json b/tests/fixtures/project_staged_validation/project_removed/active.installed.json similarity index 78% rename from tests/fixtures/project_staged_validation/project_removed/active/vendor/composer/installed.json rename to tests/fixtures/project_staged_validation/project_removed/active.installed.json index ecede582dfe97f47dc980d770cc023715eb8c966..4ec3e126c98e65c244581bef9342073c7c112bad 100644 --- a/tests/fixtures/project_staged_validation/project_removed/active/vendor/composer/installed.json +++ b/tests/fixtures/project_staged_validation/project_removed/active.installed.json @@ -1,4 +1,9 @@ { + "_readme": [ + "This file simuluates a list of packages installed in the active directory of a virtual project.", + "It will be compared against staged.installed.json.", + "See \\Drupal\\Tests\\automatic_updates\\Kernel\\ReadinessValidation\\StagedProjectsValidatorTest::testErrors()" + ], "packages": [ { "name": "drupal/core", diff --git a/tests/fixtures/project_staged_validation/project_removed/active/composer.json b/tests/fixtures/project_staged_validation/project_removed/active/composer.json deleted file mode 100644 index 0967ef424bce6791893e9a57bb952f80fd536e93..0000000000000000000000000000000000000000 --- a/tests/fixtures/project_staged_validation/project_removed/active/composer.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/tests/fixtures/project_staged_validation/project_removed/staged/vendor/composer/installed.json b/tests/fixtures/project_staged_validation/project_removed/staged.installed.json similarity index 59% rename from tests/fixtures/project_staged_validation/project_removed/staged/vendor/composer/installed.json rename to tests/fixtures/project_staged_validation/project_removed/staged.installed.json index d9247b6a62bd0a285f787cbc06aa5b2728e5fa7d..100c033c343aa2a5f9ee23433fe14f14249f3cd1 100644 --- a/tests/fixtures/project_staged_validation/project_removed/staged/vendor/composer/installed.json +++ b/tests/fixtures/project_staged_validation/project_removed/staged.installed.json @@ -1,4 +1,9 @@ { + "_readme": [ + "This file simuluates a list of packages installed in a virtual staging area.", + "It will be compared against active.installed.json.", + "See \\Drupal\\Tests\\automatic_updates\\Kernel\\ReadinessValidation\\StagedProjectsValidatorTest::testErrors()" + ], "packages": [ { "name": "drupal/core", diff --git a/tests/fixtures/project_staged_validation/project_removed/staged/composer.json b/tests/fixtures/project_staged_validation/project_removed/staged/composer.json deleted file mode 100644 index 0967ef424bce6791893e9a57bb952f80fd536e93..0000000000000000000000000000000000000000 --- a/tests/fixtures/project_staged_validation/project_removed/staged/composer.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/tests/fixtures/project_staged_validation/version_changed/active/vendor/composer/installed.json b/tests/fixtures/project_staged_validation/version_changed/active.installed.json similarity index 74% rename from tests/fixtures/project_staged_validation/version_changed/active/vendor/composer/installed.json rename to tests/fixtures/project_staged_validation/version_changed/active.installed.json index da5feae3bc3e1721a115b0d927596b6cad798a4c..e7bb050139058310bfaaa0e0966bfc3f82b2eff7 100644 --- a/tests/fixtures/project_staged_validation/version_changed/active/vendor/composer/installed.json +++ b/tests/fixtures/project_staged_validation/version_changed/active.installed.json @@ -1,4 +1,9 @@ { + "_readme": [ + "This file simuluates a list of packages installed in the active directory of a virtual project.", + "It will be compared against staged.installed.json.", + "See \\Drupal\\Tests\\automatic_updates\\Kernel\\ReadinessValidation\\StagedProjectsValidatorTest::testErrors()" + ], "packages": [ { "name": "drupal/core", diff --git a/tests/fixtures/project_staged_validation/version_changed/active/composer.json b/tests/fixtures/project_staged_validation/version_changed/active/composer.json deleted file mode 100644 index 0967ef424bce6791893e9a57bb952f80fd536e93..0000000000000000000000000000000000000000 --- a/tests/fixtures/project_staged_validation/version_changed/active/composer.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/tests/fixtures/project_staged_validation/version_changed/staged/vendor/composer/installed.json b/tests/fixtures/project_staged_validation/version_changed/staged.installed.json similarity index 75% rename from tests/fixtures/project_staged_validation/version_changed/staged/vendor/composer/installed.json rename to tests/fixtures/project_staged_validation/version_changed/staged.installed.json index d35464c3cd1b74a3415fd99045e4850e7bd4b178..62a4b1dc724a18e77b05a36fec5a84b3366edf57 100644 --- a/tests/fixtures/project_staged_validation/version_changed/staged/vendor/composer/installed.json +++ b/tests/fixtures/project_staged_validation/version_changed/staged.installed.json @@ -1,4 +1,9 @@ { + "_readme": [ + "This file simuluates a list of packages installed in a virtual staging area.", + "It will be compared against active.installed.json.", + "See \\Drupal\\Tests\\automatic_updates\\Kernel\\ReadinessValidation\\StagedProjectsValidatorTest::testErrors()" + ], "packages": [ { "name": "drupal/core", diff --git a/tests/fixtures/project_staged_validation/version_changed/staged/composer.json b/tests/fixtures/project_staged_validation/version_changed/staged/composer.json deleted file mode 100644 index 0967ef424bce6791893e9a57bb952f80fd536e93..0000000000000000000000000000000000000000 --- a/tests/fixtures/project_staged_validation/version_changed/staged/composer.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php b/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php index 1ea2231aa6500739436726e2a95d2912b62ffd87..8ff6271c6f2b75025753d6c3b8a5d9bccc4dc2b5 100644 --- a/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php +++ b/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php @@ -4,9 +4,8 @@ namespace Drupal\Tests\automatic_updates\Kernel\ReadinessValidation; use Drupal\package_manager\Event\PreApplyEvent; use Drupal\package_manager\Exception\StageValidationException; +use Drupal\package_manager\ValidationResult; use Drupal\Tests\automatic_updates\Kernel\AutomaticUpdatesKernelTestBase; -use org\bovigo\vfs\vfsStream; -use Symfony\Component\Filesystem\Filesystem; /** * @covers \Drupal\automatic_updates\Validator\StagedProjectsValidator @@ -20,131 +19,100 @@ class StagedProjectsValidatorTest extends AutomaticUpdatesKernelTestBase { */ protected static $modules = ['automatic_updates']; + /** + * The active directory in the virtual file system. + * + * @var string + */ + private $activeDir; + /** * {@inheritdoc} */ protected function setUp(): void { - // This test deals with fake sites that don't necessarily have lock files, - // so disable lock file validation. - $this->disableValidators[] = 'package_manager.validator.lock_file'; parent::setUp(); + + $this->createTestProject(); + $this->activeDir = $this->container->get('package_manager.path_locator') + ->getProjectRoot(); } /** - * Runs the validator under test against an arbitrary pair of directories. - * - * @param string $active_dir - * The active directory to validate. - * @param string $stage_dir - * The stage directory to validate. + * Asserts a set of validation results when staged changes are applied. * - * @return \Drupal\package_manager\ValidationResult[] - * The validation results. + * @param \Drupal\package_manager\ValidationResult[] $expected_results + * The expected validation results. */ - private function validate(string $active_dir, string $stage_dir): array { - $this->mockPathLocator($active_dir, $active_dir); - - $stage_dir_exists = is_dir($stage_dir); - if ($stage_dir_exists) { - // If we are testing a fixture with existing stage directory then we - // need to use a virtual file system directory, so we can create a - // subdirectory using the stage ID after it is created below. - $stage_vfs_dir = vfsStream::newDirectory('au_stage'); - $this->vfsRoot->addChild($stage_vfs_dir); - static::$testStagingRoot = $stage_vfs_dir->url(); - } - else { - // If we are testing non-existent staging directory we can use the path - // directly. - static::$testStagingRoot = $stage_dir; - } - + private function validate(array $expected_results): void { + /** @var \Drupal\automatic_updates\Updater $updater */ $updater = $this->container->get('automatic_updates.updater'); - $stage_id = $updater->begin(['drupal' => '9.8.2']); - if ($stage_dir_exists) { - // Copy the fixture's staging directory into a subdirectory using the - // stage ID as the directory name. - $sub_directory = vfsStream::newDirectory($stage_id); - $stage_vfs_dir->addChild($sub_directory); - (new Filesystem())->mirror($stage_dir, $sub_directory->url()); - } + $updater->begin(['drupal' => '9.8.2']); + $updater->stage(); - // The staged projects validator only runs before staged updates are - // applied. Since the active and stage directories may not exist, we don't - // want to invoke the other stages of the update because they may raise - // errors that are outside of the scope of what we're testing here. try { $updater->apply(); - return []; + $this->assertEmpty($expected_results); } catch (StageValidationException $e) { - return $e->getResults(); + $this->assertValidationResultsEqual($expected_results, $e->getResults()); } } /** - * Tests that if an exception is thrown, the event will absorb it. + * Tests that exceptions are turned into validation errors. */ public function testEventConsumesExceptionResults(): void { - // Prepare a fake site in the virtual file system which contains valid - // Composer data. - $fixture = __DIR__ . '/../../../fixtures/fake-site'; - copy("$fixture/composer.json", 'public://composer.json'); - mkdir('public://vendor/composer', 0777, TRUE); - copy("$fixture/vendor/composer/installed.json", 'public://vendor/composer/installed.json'); - - $event_dispatcher = $this->container->get('event_dispatcher'); - // Disable the disk space validator, since it doesn't work with vfsStream, - // and the Git directory excluder, since it won't deal with this tiny - // virtual file system correctly. - $disable_subscribers = array_map([$this->container, 'get'], [ - 'package_manager.validator.disk_space', - 'package_manager.git_excluder', - ]); - array_walk($disable_subscribers, [$event_dispatcher, 'removeSubscriber']); - // Just before the staged changes are applied, delete the composer.json file // to trigger an error. This uses the highest possible priority to guarantee // it runs before any other subscribers. - $listener = function () { - unlink('public://composer.json'); + $listener = function (): void { + unlink("$this->activeDir/composer.json"); }; - $event_dispatcher->addListener(PreApplyEvent::class, $listener, PHP_INT_MAX); + $this->container->get('event_dispatcher') + ->addListener(PreApplyEvent::class, $listener, PHP_INT_MAX); - $results = $this->validate('public://', '/fake/stage/dir'); - $this->assertCount(1, $results); - $messages = reset($results)->getMessages(); - $this->assertCount(1, $messages); - $this->assertStringContainsString('Composer could not find the config file: public:///composer.json', (string) reset($messages)); + $result = ValidationResult::createError([ + "Composer could not find the config file: $this->activeDir/composer.json\n", + ]); + $this->validate([$result]); } /** - * Tests validations errors. + * Tests validation errors, or lack thereof. * * @param string $fixtures_dir - * The fixtures directory that provides the active and staged composer.lock - * files. - * @param string $expected_summary - * The expected error summary. + * A directory containing `active.installed.json` and + * `staged.installed.json` files. These will be used as the virtual + * project's active and staged `vendor/composer/installed.json` files, + * respectively. + * @param string|null $expected_summary + * The expected error summary, or NULL if no errors are expected. * @param string[] $expected_messages - * The expected error messages. + * The expected error messages, if any. * * @dataProvider providerErrors */ - public function testErrors(string $fixtures_dir, string $expected_summary, array $expected_messages): void { - $this->assertNotEmpty($fixtures_dir); - $this->assertDirectoryExists($fixtures_dir); - - $results = $this->validate("$fixtures_dir/active", "$fixtures_dir/staged"); - $this->assertCount(1, $results); - $result = array_pop($results); - $this->assertSame($expected_summary, (string) $result->getSummary()); - $actual_messages = $result->getMessages(); - $this->assertCount(count($expected_messages), $actual_messages); - foreach ($expected_messages as $message) { - $actual_message = array_shift($actual_messages); - $this->assertSame($message, (string) $actual_message); + public function testErrors(string $fixtures_dir, ?string $expected_summary, array $expected_messages): void { + $this->assertFileIsReadable("$fixtures_dir/active.installed.json"); + $this->assertFileIsReadable("$fixtures_dir/staged.installed.json"); + + copy("$fixtures_dir/active.installed.json", "$this->activeDir/vendor/composer/installed.json"); + + // Before any other pre-apply listener runs, replaced the staged + // `vendor/composer/installed.json` with the fixture's + // `staged.installed.json`. + $listener = function (PreApplyEvent $event) use ($fixtures_dir): void { + copy("$fixtures_dir/staged.installed.json", $event->getStage()->getStageDirectory() . "/vendor/composer/installed.json"); + }; + $this->container->get('event_dispatcher') + ->addListener(PreApplyEvent::class, $listener, PHP_INT_MAX); + + $expected_results = []; + if ($expected_messages) { + // @codingStandardsIgnoreLine + $expected_results[] = ValidationResult::createError($expected_messages, t($expected_summary)); } + $this->validate($expected_results); } /** @@ -154,7 +122,7 @@ class StagedProjectsValidatorTest extends AutomaticUpdatesKernelTestBase { * Test cases for testErrors(). */ public function providerErrors(): array { - $fixtures_folder = realpath(__DIR__ . '/../../../fixtures/project_staged_validation'); + $fixtures_folder = __DIR__ . '/../../../fixtures/project_staged_validation'; return [ 'new_project_added' => [ "$fixtures_folder/new_project_added", @@ -180,17 +148,12 @@ class StagedProjectsValidatorTest extends AutomaticUpdatesKernelTestBase { "module 'drupal/dev-test_module' from 1.3.0 to 1.3.1.", ], ], + 'no_errors' => [ + "$fixtures_folder/no_errors", + NULL, + [], + ], ]; } - /** - * Tests validation when there are no errors. - */ - public function testNoErrors(): void { - $fixtures_dir = realpath(__DIR__ . '/../../../fixtures/project_staged_validation/no_errors'); - $results = $this->validate("$fixtures_dir/active", "$fixtures_dir/staged"); - $this->assertIsArray($results); - $this->assertEmpty($results); - } - }