From ee69dd0a1a8dc893e931918bc4aefb692e175c08 Mon Sep 17 00:00:00 2001 From: Alex Skrypnyk Date: Mon, 1 Sep 2025 20:42:05 +1000 Subject: [PATCH 1/2] [#1882] Added support for DrupalCMS. --- .gitignore | 5 +- .../src/Prompts/Handlers/AbstractHandler.php | 2 +- .../src/Prompts/Handlers/HandlerInterface.php | 4 +- .../src/Prompts/Handlers/Internal.php | 2 +- .../src/Prompts/Handlers/Profile.php | 71 +++++++++++++------ .../src/Prompts/Handlers/Starter.php | 58 ++++++++++++--- .../src/Prompts/Handlers/Webroot.php | 13 +--- .../installer/src/Prompts/PromptManager.php | 49 ++++++++++--- .../Fixtures/install/_baseline/.gitignore | 5 +- .../Fixtures/install/_baseline/composer.json | 3 + .../Fixtures/install/_baseline/phpmd.xml | 1 + .../tests/behat/features/search.feature | 30 ++++---- .../install/search_api.index.content.yml | 13 ++-- .../config/install/views.view.search.yml | 44 ++++++++++-- .../install/hosting_acquia/.gitignore | 7 +- .../install/hosting_acquia/composer.json | 5 +- .../install/search_api.index.content.yml | 13 ++-- .../config/install/views.view.search.yml | 44 ++++++++++-- .../Fixtures/install/hosting_acquia/phpmd.xml | 3 +- .../install/search_api.index.content.yml | 13 ++-- .../config/install/views.view.search.yml | 44 ++++++++++-- .../install/starter_demo_db/.ignorecontent | 1 + .../install/starter_drupal_cms_profile/.env | 27 +++++++ .../starter_drupal_cms_profile/composer.json | 52 ++++++++++++++ .../install/starter_drupal_profile/.env | 18 +++++ .../Fixtures/install/theme_absent/phpmd.xml | 2 +- .../tools_groups_no_be_tests/.gitignore | 2 +- .../.gitignore | 2 +- .../install/tools_no_phpunit/.gitignore | 2 +- .../tools_no_phpunit_circleci/.gitignore | 2 +- .../Fixtures/install/tools_none/.gitignore | 2 +- .../Handlers/StarterInstallTest.php | 37 ++++++++++ .../AbstractPromptManagerTestCase.php | 2 +- .../Handlers/StarterPromptManagerTest.php | 17 +++-- .vortex/tests/bats/_helper.bash | 2 +- .../workflow.install.profile_drupalcms.bats | 40 +++++++++++ .vortex/tests/test.workflow.sh | 2 + composer.json | 3 + phpmd.xml | 1 + tests/behat/features/search.feature | 30 ++++---- .../install/search_api.index.content.yml | 13 ++-- .../config/install/views.view.search.yml | 44 ++++++++++-- 42 files changed, 579 insertions(+), 151 deletions(-) create mode 100644 .vortex/installer/tests/Fixtures/install/starter_demo_db/.ignorecontent create mode 100644 .vortex/installer/tests/Fixtures/install/starter_drupal_cms_profile/.env create mode 100644 .vortex/installer/tests/Fixtures/install/starter_drupal_cms_profile/composer.json create mode 100644 .vortex/installer/tests/Fixtures/install/starter_drupal_profile/.env create mode 100644 .vortex/installer/tests/Functional/Handlers/StarterInstallTest.php create mode 100644 .vortex/tests/bats/e2e/workflow.install.profile_drupalcms.bats diff --git a/.gitignore b/.gitignore index e1f6d4186..028a60b37 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,7 @@ web/sites/default/* # Preserve default settings files to use them in Functional test. !web/sites/default/default.settings.php !web/sites/default/default.services.yml -# Whitelist Drupal Scaffold files. @see https://github.com/drupal-composer/drupal-scaffold#limitation +# Allow Drupal Scaffold files. @see https://github.com/drupal-composer/drupal-scaffold#limitation !web/.editorconfig !web/.eslintignore !web/.gitattributes @@ -41,6 +41,9 @@ web/sites/default/* !web/robots.txt !web/update.php +# Ignore all recipes by default. Custom recipes should be added explicitly. +recipes/* + #;< VORTEX_DEV #; Ignore these files in Vortex itself, but do not ignore in consumer site. /composer.lock diff --git a/.vortex/installer/src/Prompts/Handlers/AbstractHandler.php b/.vortex/installer/src/Prompts/Handlers/AbstractHandler.php index 21f570bb9..dd2ebef5b 100644 --- a/.vortex/installer/src/Prompts/Handlers/AbstractHandler.php +++ b/.vortex/installer/src/Prompts/Handlers/AbstractHandler.php @@ -134,7 +134,7 @@ public function resolvedValue(array $responses): null|string|bool|array { /** * {@inheritdoc} */ - public function resolvedMessage(array $responses): ?string { + public function resolvedMessage(array $responses, mixed $resolved): ?string { return NULL; } diff --git a/.vortex/installer/src/Prompts/Handlers/HandlerInterface.php b/.vortex/installer/src/Prompts/Handlers/HandlerInterface.php index 561dff709..cc4f4dcd9 100644 --- a/.vortex/installer/src/Prompts/Handlers/HandlerInterface.php +++ b/.vortex/installer/src/Prompts/Handlers/HandlerInterface.php @@ -146,11 +146,13 @@ public function resolvedValue(array $responses): null|string|bool|array; * * @param array $responses * Current form responses for context-aware message generation. + * @param mixed $resolved + * The resolved value from resolvedValue(). * * @return string|null * The message to display, or null if no message needed. */ - public function resolvedMessage(array $responses): ?string; + public function resolvedMessage(array $responses, mixed $resolved): ?string; /** * Set the responses. diff --git a/.vortex/installer/src/Prompts/Handlers/Internal.php b/.vortex/installer/src/Prompts/Handlers/Internal.php index f42b4078b..56e271d81 100644 --- a/.vortex/installer/src/Prompts/Handlers/Internal.php +++ b/.vortex/installer/src/Prompts/Handlers/Internal.php @@ -124,7 +124,7 @@ protected function processDemoMode(array $responses, string $dir): void { $is_demo = $this->config->get(Config::IS_DEMO); if (is_null($is_demo)) { - if ($responses[Starter::id()] !== Starter::DRUPAL_LOAD_DATABASE_DEMO) { + if ($responses[Starter::id()] !== Starter::LOAD_DATABASE_DEMO) { $is_demo = FALSE; } // Check if it should be enabled based on the provision type and database diff --git a/.vortex/installer/src/Prompts/Handlers/Profile.php b/.vortex/installer/src/Prompts/Handlers/Profile.php index 76cf3471c..f9d06e2bf 100644 --- a/.vortex/installer/src/Prompts/Handlers/Profile.php +++ b/.vortex/installer/src/Prompts/Handlers/Profile.php @@ -73,32 +73,29 @@ public function discover(): null|string|bool|array { /** * {@inheritdoc} */ - public function process(): void { - $v = $this->getResponseAsString(); + public function resolvedValue(array $responses): null|string|bool|array { + $discovered = $this->discover(); - // If user selected 'custom', use the ProfileCustom response instead. - if ($v === self::CUSTOM && isset($this->responses['profile_custom'])) { - $v = $this->responses['profile_custom']; + if (!is_null($discovered)) { + return $discovered; } - $t = $this->tmpDir; - $w = $this->webroot; - - File::replaceContentInFile($t . '/.env', '/DRUPAL_PROFILE=.*/', 'DRUPAL_PROFILE=' . $v); + if (($responses[Starter::id()] ?? '') === Starter::INSTALL_PROFILE_DRUPALCMS) { + return Starter::INSTALL_PROFILE_DRUPALCMS_PATH; + } - if (in_array($v, [self::STANDARD, self::MINIMAL, self::DEMO_UMAMI])) { - File::rmdir(sprintf('%s/%s/profiles/your_site_profile', $t, $w)); - File::rmdir(sprintf('%s/%s/profiles/custom/your_site_profile', $t, $w)); + return NULL; + } - File::replaceContentAsync([ - '/profiles/your_site_profile,' => '', - '/profiles/custom/your_site_profile,' => '', - ]); - } - else { - File::replaceContentAsync('your_site_profile', $v); - File::renameInDir($t, 'your_site_profile', $v); + /** + * {@inheritdoc} + */ + public function resolvedMessage(array $responses, mixed $resolved): ?string { + if (is_string($resolved)) { + return sprintf('Profile will be set to "%s".', $resolved); } + + return NULL; } /** @@ -131,4 +128,38 @@ public function discoverName(): null|string|bool|array { return str_replace(['.info.yml', '.info'], '', basename($path)); } + /** + * {@inheritdoc} + */ + public function process(): void { + $v = $this->getResponseAsString(); + + // If user selected 'custom', use the ProfileCustom response instead. + if ($v === self::CUSTOM && isset($this->responses[ProfileCustom::id()])) { + $v = $this->responses[ProfileCustom::id()]; + } + + $t = $this->tmpDir; + $w = $this->webroot; + + File::replaceContentInFile($t . '/.env', '/DRUPAL_PROFILE=.*/', 'DRUPAL_PROFILE=' . $v); + + // Assume that profiles provided as a path are contrib profiles. + $is_contrib_profile = str_contains($v, DIRECTORY_SEPARATOR); + + if (in_array($v, [self::STANDARD, self::MINIMAL, self::DEMO_UMAMI]) || $is_contrib_profile) { + File::rmdir(sprintf('%s/%s/profiles/your_site_profile', $t, $w)); + File::rmdir(sprintf('%s/%s/profiles/custom/your_site_profile', $t, $w)); + + File::replaceContentAsync([ + '/profiles/your_site_profile,' => '', + '/profiles/custom/your_site_profile,' => '', + ]); + } + else { + File::replaceContentAsync('your_site_profile', $v); + File::renameInDir($t, 'your_site_profile', $v); + } + } + } diff --git a/.vortex/installer/src/Prompts/Handlers/Starter.php b/.vortex/installer/src/Prompts/Handlers/Starter.php index b649fa55f..b5ac121ec 100644 --- a/.vortex/installer/src/Prompts/Handlers/Starter.php +++ b/.vortex/installer/src/Prompts/Handlers/Starter.php @@ -4,13 +4,18 @@ namespace DrevOps\VortexInstaller\Prompts\Handlers; +use DrevOps\VortexInstaller\Utils\JsonManipulator; use DrevOps\VortexInstaller\Utils\Tui; class Starter extends AbstractHandler { - const DRUPAL_LOAD_DATABASE_DEMO = 'demodb'; + const INSTALL_PROFILE_CORE = 'install_profile_core'; - const DRUPAL_INSTALL_PROFILE = 'drupal_profile'; + const INSTALL_PROFILE_DRUPALCMS = 'install_profile_drupalcms'; + + const LOAD_DATABASE_DEMO = 'load_demodb'; + + const INSTALL_PROFILE_DRUPALCMS_PATH = '../recipes/drupal_cms_starter'; /** * {@inheritdoc} @@ -25,8 +30,12 @@ public function label(): string { public static function description(array $responses): ?string { $label1 = Tui::bold('Drupal, installed from profile'); $label11 = Tui::underscore('populating a fresh database'); - $label2 = Tui::bold('Drupal, loaded from the demo database'); - $label21 = Tui::underscore('loading an existing demo database'); + + $label2 = Tui::bold('Drupal CMS, installed from profile'); + $label21 = Tui::underscore('populating a fresh database'); + + $label3 = Tui::bold('Drupal, loaded from the demo database'); + $label31 = Tui::underscore('loading an existing demo database'); return << 'Drupal, installed from profile', - self::DRUPAL_LOAD_DATABASE_DEMO => 'Drupal, loaded from the demo database', + self::INSTALL_PROFILE_CORE => 'Drupal, installed from profile', + self::INSTALL_PROFILE_DRUPALCMS => 'Drupal CMS, installed from profile', + self::LOAD_DATABASE_DEMO => 'Drupal, loaded from the demo database', ]; } @@ -62,7 +76,7 @@ public function options(array $responses): ?array { * {@inheritdoc} */ public function default(array $responses): null|string|bool|array { - return self::DRUPAL_LOAD_DATABASE_DEMO; + return self::LOAD_DATABASE_DEMO; } /** @@ -76,7 +90,29 @@ public function discover(): null|string|bool|array { * {@inheritdoc} */ public function process(): void { - // @todo Implement. + if ($this->response == self::INSTALL_PROFILE_DRUPALCMS) { + $cj = JsonManipulator::fromFile($this->tmpDir . '/composer.json'); + + $cj->addLink('require', 'drupal/cms', '^1.0', TRUE); + $cj->addLink('require', 'wikimedia/composer-merge-plugin', '^2.1', TRUE); + $cj->addLink('require', 'symfony/http-client', '^6.4 || ^7.0', TRUE); + + $cj->addConfigSetting('allow-plugins.drupal/core-project-message', TRUE); + $cj->addConfigSetting('allow-plugins.wikimedia/composer-merge-plugin', TRUE); + + $cj->addProperty('extra.merge-plugin.ignore-duplicates', FALSE); + $cj->addProperty('extra.merge-plugin.merge-false', TRUE); + $cj->addProperty('extra.merge-plugin.merge-extra', FALSE); + $cj->addProperty('extra.merge-plugin.merge-extra-deep', FALSE); + $cj->addProperty('extra.merge-plugin.merge-replace', TRUE); + $cj->addProperty('extra.merge-plugin.merge-scripts', FALSE); + $cj->addProperty('extra.merge-plugin.recurse', TRUE); + $cj->addProperty('extra.merge-plugin.replace', TRUE); + $cj->addProperty('extra.merge-plugin.require', ['vendor/drupal/cms/composer.json']); + + $c = $cj->getContents(); + file_put_contents($this->tmpDir . '/composer.json', $c); + } } /** @@ -89,12 +125,12 @@ public function postInstall(): ?string { $output = ''; - if ($this->response == self::DRUPAL_LOAD_DATABASE_DEMO) { + if ($this->response == self::LOAD_DATABASE_DEMO) { $output .= 'Build project locally:' . PHP_EOL; $output .= ' ahoy build' . PHP_EOL; $output .= PHP_EOL; } - elseif ($this->response == self::DRUPAL_INSTALL_PROFILE) { + elseif ($this->response == self::INSTALL_PROFILE_CORE || $this->response == self::INSTALL_PROFILE_DRUPALCMS) { $output .= 'Build project locally:' . PHP_EOL; $output .= ' VORTEX_PROVISION_TYPE=profile ahoy build' . PHP_EOL; $output .= PHP_EOL; diff --git a/.vortex/installer/src/Prompts/Handlers/Webroot.php b/.vortex/installer/src/Prompts/Handlers/Webroot.php index 1c350288b..8ff4d6020 100644 --- a/.vortex/installer/src/Prompts/Handlers/Webroot.php +++ b/.vortex/installer/src/Prompts/Handlers/Webroot.php @@ -112,16 +112,9 @@ public function resolvedValue(array $responses): null|string|bool|array { /** * {@inheritdoc} */ - public function resolvedMessage(array $responses): ?string { - if ( - isset($responses[HostingProvider::id()]) && - $responses[HostingProvider::id()] !== HostingProvider::OTHER - ) { - $webroot = $this->default($responses); - if (is_array($webroot)) { - throw new \InvalidArgumentException('Web root must be a string, got: ' . gettype($webroot)); - } - return sprintf('Web root will be set to "%s".', (string) $webroot); + public function resolvedMessage(array $responses, mixed $resolved): ?string { + if (is_string($resolved)) { + return sprintf('Web root will be set to "%s".', $resolved); } return NULL; diff --git a/.vortex/installer/src/Prompts/PromptManager.php b/.vortex/installer/src/Prompts/PromptManager.php index 077796654..17143656c 100644 --- a/.vortex/installer/src/Prompts/PromptManager.php +++ b/.vortex/installer/src/Prompts/PromptManager.php @@ -125,7 +125,9 @@ public function runPrompts(): void { ->intro('Drupal') ->add(fn($r, $pr, $n): int|string => select(...$this->args(Starter::class, NULL, $r)), Starter::id()) ->add( - fn($r, $pr, $n): int|string => select(...$this->args(Profile::class)), + function (array $r, $pr, $n): string { + return $this->resolveOrPrompt(Profile::id(), $r, fn(): int|string => select(...$this->args(Profile::class))); + }, Profile::id() ) ->addIf( @@ -147,17 +149,8 @@ public function runPrompts(): void { ->intro('Hosting') ->add(fn($r, $pr, $n): int|string => select(...$this->args(HostingProvider::class)), HostingProvider::id()) ->add( - // @todo Move into centralised resolver within this class. function (array $r, $pr, $n): string { - $handler = $this->handlers[Webroot::id()]; - $resolved = $handler->resolvedValue($r); - if (is_string($resolved)) { - info($handler->resolvedMessage($r)); - return $resolved; - } - else { - return text(...$this->args(Webroot::class, NULL, $r)); - } + return $this->resolveOrPrompt(Webroot::id(), $r, fn(): string => text(...$this->args(Webroot::class, NULL, $r))); }, Webroot::id() ) @@ -567,4 +560,38 @@ private function args(string $handler_class, mixed $default_override = NULL, arr return array_filter($args, fn($value): bool => $value !== NULL); } + /** + * Resolve a value via handler or prompt the user. + * + * This method is used to resolve a value via a handler's resolvedValue() + * method. If the value is not resolved, it will prompt the user using the + * provided prompt callable. + * + * @param string $handler_id + * The handler ID. + * @param array $r + * Current form responses for context-aware methods. + * @param callable $prompt + * The prompt callable to use if the value is not resolved. + * + * @return string + * The resolved value. + */ + protected function resolveOrPrompt(string $handler_id, array $r, callable $prompt): string { + $handler = $this->handlers[$handler_id]; + $resolved = $handler->resolvedValue($r); + + if (is_string($resolved)) { + $message = $handler->resolvedMessage($r, $resolved); + + if ($message) { + info($message); + } + + return $resolved; + } + + return (string) $prompt(); + } + } diff --git a/.vortex/installer/tests/Fixtures/install/_baseline/.gitignore b/.vortex/installer/tests/Fixtures/install/_baseline/.gitignore index 608401332..4b1fcfa38 100644 --- a/.vortex/installer/tests/Fixtures/install/_baseline/.gitignore +++ b/.vortex/installer/tests/Fixtures/install/_baseline/.gitignore @@ -29,7 +29,7 @@ web/sites/default/* # Preserve default settings files to use them in Functional test. !web/sites/default/default.settings.php !web/sites/default/default.services.yml -# Whitelist Drupal Scaffold files. @see https://github.com/drupal-composer/drupal-scaffold#limitation +# Allow Drupal Scaffold files. @see https://github.com/drupal-composer/drupal-scaffold#limitation !web/.editorconfig !web/.eslintignore !web/.gitattributes @@ -39,6 +39,9 @@ web/sites/default/* !web/robots.txt !web/update.php +# Ignore all recipes by default. Custom recipes should be added explicitly. +recipes/* + # Ignore dependencies cache files. /vendor /node_modules diff --git a/.vortex/installer/tests/Fixtures/install/_baseline/composer.json b/.vortex/installer/tests/Fixtures/install/_baseline/composer.json index f5bd966a0..0572cafb7 100644 --- a/.vortex/installer/tests/Fixtures/install/_baseline/composer.json +++ b/.vortex/installer/tests/Fixtures/install/_baseline/composer.json @@ -130,6 +130,9 @@ "web/profiles/contrib/{$name}": [ "type:drupal-profile" ], + "recipes/{$name}": [ + "type:drupal-recipe" + ], "web/themes/contrib/{$name}": [ "type:drupal-theme" ], diff --git a/.vortex/installer/tests/Fixtures/install/_baseline/phpmd.xml b/.vortex/installer/tests/Fixtures/install/_baseline/phpmd.xml index 88f4ea258..74aa28c2a 100644 --- a/.vortex/installer/tests/Fixtures/install/_baseline/phpmd.xml +++ b/.vortex/installer/tests/Fixtures/install/_baseline/phpmd.xml @@ -14,6 +14,7 @@ */web/modules/contrib/* */web/themes/contrib/* */web/sites/* + */recipes/* */scripts/* */tests/*Test.php diff --git a/.vortex/installer/tests/Fixtures/install/_baseline/tests/behat/features/search.feature b/.vortex/installer/tests/Fixtures/install/_baseline/tests/behat/features/search.feature index 8e7aa9994..dadff2697 100644 --- a/.vortex/installer/tests/Fixtures/install/_baseline/tests/behat/features/search.feature +++ b/.vortex/installer/tests/Fixtures/install/_baseline/tests/behat/features/search.feature @@ -8,26 +8,26 @@ Feature: Search API @api Scenario: User searches for Page content Given page content: - | title | body | status | - | [TEST] Test page 1 | test content uniquestring | 1 | - | [TEST] Test page 2 | test content otheruniquestring | 1 | - And I add the "page" content with the title "[TEST] Test page 1" to the search index - And I add the "page" content with the title "[TEST] Test page 2" to the search index - And I run search indexing for 2 items - And I visit "/search" + | title | status | moderation_state | + | [TEST] Test page uniquestring | 1 | published | + | [TEST] Test page otheruniquestring | 1 | published | + | [TEST] Test page thirduniquestring | 0 | draft | + And I add the "page" content with the title "[TEST] Test page uniquestring" to the search index + And I add the "page" content with the title "[TEST] Test page otheruniquestring" to the search index + And I add the "page" content with the title "[TEST] Test page thirduniquestring" to the search index + And I run search indexing for 3 items And I wait for 5 seconds + And I visit "/search" And save screenshot When I fill in "search_api_fulltext" with "[TEST]" And I press "Apply" - Then I should see "[TEST] Test page 1" in the ".view-content" element - And I should see "test content uniquestring" in the ".view-content" element - And I should see "[TEST] Test page 2" in the ".view-content" element - And I should see "test content otheruniquestring" in the ".view-content" element + Then I should see "[TEST] Test page uniquestring" in the ".view-content" element + And I should see "[TEST] Test page otheruniquestring" in the ".view-content" element + And I should not see "[TEST] Test page thirduniquestring" in the ".view-content" element When I fill in "search_api_fulltext" with "otheruniquestring" And I press "Apply" - Then I should not see "[TEST] Test page 1" in the ".view-content" element - And I should not see "test content uniquestring" in the ".view-content" element - And I should see "[TEST] Test page 2" in the ".view-content" element - And I should see "test content otheruniquestring" in the ".view-content" element + Then I should not see "[TEST] Test page uniquestring" in the ".view-content" element + And I should see "[TEST] Test page otheruniquestring" in the ".view-content" element + And I should not see "[TEST] Test page thirduniquestring" in the ".view-content" element diff --git a/.vortex/installer/tests/Fixtures/install/_baseline/web/modules/custom/sw_search/config/install/search_api.index.content.yml b/.vortex/installer/tests/Fixtures/install/_baseline/web/modules/custom/sw_search/config/install/search_api.index.content.yml index a5ada20e1..f4929115f 100644 --- a/.vortex/installer/tests/Fixtures/install/_baseline/web/modules/custom/sw_search/config/install/search_api.index.content.yml +++ b/.vortex/installer/tests/Fixtures/install/_baseline/web/modules/custom/sw_search/config/install/search_api.index.content.yml @@ -2,7 +2,6 @@ langcode: en status: true dependencies: config: - - field.storage.node.body - search_api.server.solr module: - node @@ -59,14 +58,14 @@ name: Content description: '' read_only: false field_settings: - processed: - label: 'Body » Processed text' + status: + label: Published datasource_id: 'entity:node' - property_path: 'body:processed' - type: 'solr_text_custom:ngram' + property_path: status + type: boolean dependencies: - config: - - field.storage.node.body + module: + - node title: label: Title datasource_id: 'entity:node' diff --git a/.vortex/installer/tests/Fixtures/install/_baseline/web/modules/custom/sw_search/config/install/views.view.search.yml b/.vortex/installer/tests/Fixtures/install/_baseline/web/modules/custom/sw_search/config/install/views.view.search.yml index 0535388d4..2be400732 100644 --- a/.vortex/installer/tests/Fixtures/install/_baseline/web/modules/custom/sw_search/config/install/views.view.search.yml +++ b/.vortex/installer/tests/Fixtures/install/_baseline/web/modules/custom/sw_search/config/install/views.view.search.yml @@ -143,9 +143,6 @@ display: multiple: false remember_roles: authenticated: authenticated - anonymous: '0' - content_editor: '0' - administrator: '0' expose_fields: false placeholder: '' searched_fields_id: search_api_fulltext_searched_fields @@ -165,6 +162,44 @@ display: parse_mode: terms min_length: null fields: { } + status: + id: status + table: search_api_index_content + field: status + relationship: none + group_type: group + admin_label: '' + plugin_id: search_api_boolean + operator: '=' + value: '1' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + operator_limit_selection: false + operator_list: { } + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } style: type: default row: @@ -172,8 +207,7 @@ display: options: view_modes: 'entity:node': - ':default': default - article: ':default' + ':default': teaser page: ':default' query: type: search_api_query diff --git a/.vortex/installer/tests/Fixtures/install/hosting_acquia/.gitignore b/.vortex/installer/tests/Fixtures/install/hosting_acquia/.gitignore index 4bd54d219..d99532771 100644 --- a/.vortex/installer/tests/Fixtures/install/hosting_acquia/.gitignore +++ b/.vortex/installer/tests/Fixtures/install/hosting_acquia/.gitignore @@ -1,4 +1,4 @@ -@@ -5,47 +5,47 @@ +@@ -5,39 +5,39 @@ # To add an override file, explicitly un-ignore it below and add to the # repository (useful for robots.txt and .htaccess file overrides). @@ -49,7 +49,7 @@ -!web/sites/default/default.services.yml +!docroot/sites/default/default.settings.php +!docroot/sites/default/default.services.yml - # Whitelist Drupal Scaffold files. @see https://github.com/drupal-composer/drupal-scaffold#limitation + # Allow Drupal Scaffold files. @see https://github.com/drupal-composer/drupal-scaffold#limitation -!web/.editorconfig -!web/.eslintignore -!web/.gitattributes @@ -67,6 +67,9 @@ +!docroot/robots.txt +!docroot/update.php + # Ignore all recipes by default. Custom recipes should be added explicitly. + recipes/* +@@ -45,10 +45,10 @@ # Ignore dependencies cache files. /vendor /node_modules diff --git a/.vortex/installer/tests/Fixtures/install/hosting_acquia/composer.json b/.vortex/installer/tests/Fixtures/install/hosting_acquia/composer.json index f6fe417b3..40353cddb 100644 --- a/.vortex/installer/tests/Fixtures/install/hosting_acquia/composer.json +++ b/.vortex/installer/tests/Fixtures/install/hosting_acquia/composer.json @@ -1,4 +1,4 @@ -@@ -112,37 +112,37 @@ +@@ -112,40 +112,40 @@ "[web-root]/web.config": false }, "locations": { @@ -25,6 +25,9 @@ + "docroot/profiles/contrib/{$name}": [ "type:drupal-profile" ], + "recipes/{$name}": [ + "type:drupal-recipe" + ], - "web/themes/contrib/{$name}": [ + "docroot/themes/contrib/{$name}": [ "type:drupal-theme" diff --git a/.vortex/installer/tests/Fixtures/install/hosting_acquia/docroot/modules/custom/sw_search/config/install/search_api.index.content.yml b/.vortex/installer/tests/Fixtures/install/hosting_acquia/docroot/modules/custom/sw_search/config/install/search_api.index.content.yml index a5ada20e1..f4929115f 100644 --- a/.vortex/installer/tests/Fixtures/install/hosting_acquia/docroot/modules/custom/sw_search/config/install/search_api.index.content.yml +++ b/.vortex/installer/tests/Fixtures/install/hosting_acquia/docroot/modules/custom/sw_search/config/install/search_api.index.content.yml @@ -2,7 +2,6 @@ langcode: en status: true dependencies: config: - - field.storage.node.body - search_api.server.solr module: - node @@ -59,14 +58,14 @@ name: Content description: '' read_only: false field_settings: - processed: - label: 'Body » Processed text' + status: + label: Published datasource_id: 'entity:node' - property_path: 'body:processed' - type: 'solr_text_custom:ngram' + property_path: status + type: boolean dependencies: - config: - - field.storage.node.body + module: + - node title: label: Title datasource_id: 'entity:node' diff --git a/.vortex/installer/tests/Fixtures/install/hosting_acquia/docroot/modules/custom/sw_search/config/install/views.view.search.yml b/.vortex/installer/tests/Fixtures/install/hosting_acquia/docroot/modules/custom/sw_search/config/install/views.view.search.yml index 0535388d4..2be400732 100644 --- a/.vortex/installer/tests/Fixtures/install/hosting_acquia/docroot/modules/custom/sw_search/config/install/views.view.search.yml +++ b/.vortex/installer/tests/Fixtures/install/hosting_acquia/docroot/modules/custom/sw_search/config/install/views.view.search.yml @@ -143,9 +143,6 @@ display: multiple: false remember_roles: authenticated: authenticated - anonymous: '0' - content_editor: '0' - administrator: '0' expose_fields: false placeholder: '' searched_fields_id: search_api_fulltext_searched_fields @@ -165,6 +162,44 @@ display: parse_mode: terms min_length: null fields: { } + status: + id: status + table: search_api_index_content + field: status + relationship: none + group_type: group + admin_label: '' + plugin_id: search_api_boolean + operator: '=' + value: '1' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + operator_limit_selection: false + operator_list: { } + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } style: type: default row: @@ -172,8 +207,7 @@ display: options: view_modes: 'entity:node': - ':default': default - article: ':default' + ':default': teaser page: ':default' query: type: search_api_query diff --git a/.vortex/installer/tests/Fixtures/install/hosting_acquia/phpmd.xml b/.vortex/installer/tests/Fixtures/install/hosting_acquia/phpmd.xml index bd0af34d0..19307e541 100644 --- a/.vortex/installer/tests/Fixtures/install/hosting_acquia/phpmd.xml +++ b/.vortex/installer/tests/Fixtures/install/hosting_acquia/phpmd.xml @@ -1,4 +1,4 @@ -@@ -8,18 +8,18 @@ +@@ -8,19 +8,19 @@ */vendor/* */node_modules/* @@ -14,6 +14,7 @@ + */docroot/modules/contrib/* + */docroot/themes/contrib/* + */docroot/sites/* + */recipes/* */scripts/* */tests/*Test.php diff --git a/.vortex/installer/tests/Fixtures/install/names/web/modules/custom/the_force_search/config/install/search_api.index.content.yml b/.vortex/installer/tests/Fixtures/install/names/web/modules/custom/the_force_search/config/install/search_api.index.content.yml index a5ada20e1..f4929115f 100644 --- a/.vortex/installer/tests/Fixtures/install/names/web/modules/custom/the_force_search/config/install/search_api.index.content.yml +++ b/.vortex/installer/tests/Fixtures/install/names/web/modules/custom/the_force_search/config/install/search_api.index.content.yml @@ -2,7 +2,6 @@ langcode: en status: true dependencies: config: - - field.storage.node.body - search_api.server.solr module: - node @@ -59,14 +58,14 @@ name: Content description: '' read_only: false field_settings: - processed: - label: 'Body » Processed text' + status: + label: Published datasource_id: 'entity:node' - property_path: 'body:processed' - type: 'solr_text_custom:ngram' + property_path: status + type: boolean dependencies: - config: - - field.storage.node.body + module: + - node title: label: Title datasource_id: 'entity:node' diff --git a/.vortex/installer/tests/Fixtures/install/names/web/modules/custom/the_force_search/config/install/views.view.search.yml b/.vortex/installer/tests/Fixtures/install/names/web/modules/custom/the_force_search/config/install/views.view.search.yml index 0535388d4..2be400732 100644 --- a/.vortex/installer/tests/Fixtures/install/names/web/modules/custom/the_force_search/config/install/views.view.search.yml +++ b/.vortex/installer/tests/Fixtures/install/names/web/modules/custom/the_force_search/config/install/views.view.search.yml @@ -143,9 +143,6 @@ display: multiple: false remember_roles: authenticated: authenticated - anonymous: '0' - content_editor: '0' - administrator: '0' expose_fields: false placeholder: '' searched_fields_id: search_api_fulltext_searched_fields @@ -165,6 +162,44 @@ display: parse_mode: terms min_length: null fields: { } + status: + id: status + table: search_api_index_content + field: status + relationship: none + group_type: group + admin_label: '' + plugin_id: search_api_boolean + operator: '=' + value: '1' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + operator_limit_selection: false + operator_list: { } + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } style: type: default row: @@ -172,8 +207,7 @@ display: options: view_modes: 'entity:node': - ':default': default - article: ':default' + ':default': teaser page: ':default' query: type: search_api_query diff --git a/.vortex/installer/tests/Fixtures/install/starter_demo_db/.ignorecontent b/.vortex/installer/tests/Fixtures/install/starter_demo_db/.ignorecontent new file mode 100644 index 000000000..7490f6cc2 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/starter_demo_db/.ignorecontent @@ -0,0 +1 @@ +# Default diff --git a/.vortex/installer/tests/Fixtures/install/starter_drupal_cms_profile/.env b/.vortex/installer/tests/Fixtures/install/starter_drupal_cms_profile/.env new file mode 100644 index 000000000..bcdb452b6 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/starter_drupal_cms_profile/.env @@ -0,0 +1,27 @@ +@@ -39,7 +39,7 @@ + ################################################################################ + + # Drupal profile name. +-DRUPAL_PROFILE=standard ++DRUPAL_PROFILE=../recipes/drupal_cms_starter + + # Drupal configuration directory. + # +@@ -190,17 +190,3 @@ + # with optional names in the format "email|name". + # Example: "to1@example.com|Jane Doe, to2@example.com|John Doe" + VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com +- +-################################################################################ +-# DEMO # +-################################################################################ +-# # +-# Override project-specific values for demonstration purposes. # +-# Used to showcase Vortex without asking users to perform additional steps. # +-# # +-# Remove this section after completing database download integration. # +-# # +-################################################################################ +- +-# URL of the database used for demonstration with URL database download type. +-VORTEX_DB_DOWNLOAD_URL=https://github.com/drevops/vortex/releases/download/25.4.0/db_d11.demo.sql diff --git a/.vortex/installer/tests/Fixtures/install/starter_drupal_cms_profile/composer.json b/.vortex/installer/tests/Fixtures/install/starter_drupal_cms_profile/composer.json new file mode 100644 index 000000000..f23589c03 --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/starter_drupal_cms_profile/composer.json @@ -0,0 +1,52 @@ +@@ -9,6 +9,7 @@ + "cweagans/composer-patches": "__VERSION__", + "drupal/admin_toolbar": "__VERSION__", + "drupal/clamav": "__VERSION__", ++ "drupal/cms": "__VERSION__", + "drupal/coffee": "__VERSION__", + "drupal/config_split": "__VERSION__", + "drupal/config_update": "__VERSION__", +@@ -26,7 +27,9 @@ + "drupal/stage_file_proxy": "__VERSION__", + "drush/drush": "__VERSION__", + "oomphinc/composer-installers-extender": "__VERSION__", +- "webflo/drupal-finder": "__VERSION__" ++ "symfony/http-client": "^6.4 || ^7.0", ++ "webflo/drupal-finder": "__VERSION__", ++ "wikimedia/composer-merge-plugin": "__VERSION__" + }, + "require-dev": { + "behat/behat": "__VERSION__", +@@ -81,7 +84,9 @@ + "php-http/discovery": true, + "phpstan/extension-installer": true, + "pyrech/composer-changelogs": true, +- "tbachert/spi": true ++ "tbachert/spi": true, ++ "drupal/core-project-message": true, ++ "wikimedia/composer-merge-plugin": true + }, + "discard-changes": true, + "platform": { +@@ -157,7 +162,20 @@ + "patchLevel": { + "drupal/core": "-p2" + }, +- "patches": {} ++ "patches": {}, ++ "merge-plugin": { ++ "ignore-duplicates": false, ++ "merge-false": true, ++ "merge-extra": false, ++ "merge-extra-deep": false, ++ "merge-replace": true, ++ "merge-scripts": false, ++ "recurse": true, ++ "replace": true, ++ "require": [ ++ "vendor/drupal/cms/composer.json" ++ ] ++ } + }, + "scripts": { + "pre-install-cmd": [ diff --git a/.vortex/installer/tests/Fixtures/install/starter_drupal_profile/.env b/.vortex/installer/tests/Fixtures/install/starter_drupal_profile/.env new file mode 100644 index 000000000..ef456848b --- /dev/null +++ b/.vortex/installer/tests/Fixtures/install/starter_drupal_profile/.env @@ -0,0 +1,18 @@ +@@ -190,17 +190,3 @@ + # with optional names in the format "email|name". + # Example: "to1@example.com|Jane Doe, to2@example.com|John Doe" + VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com +- +-################################################################################ +-# DEMO # +-################################################################################ +-# # +-# Override project-specific values for demonstration purposes. # +-# Used to showcase Vortex without asking users to perform additional steps. # +-# # +-# Remove this section after completing database download integration. # +-# # +-################################################################################ +- +-# URL of the database used for demonstration with URL database download type. +-VORTEX_DB_DOWNLOAD_URL=https://github.com/drevops/vortex/releases/download/25.4.0/db_d11.demo.sql diff --git a/.vortex/installer/tests/Fixtures/install/theme_absent/phpmd.xml b/.vortex/installer/tests/Fixtures/install/theme_absent/phpmd.xml index b1149d2e0..f3316f9d2 100644 --- a/.vortex/installer/tests/Fixtures/install/theme_absent/phpmd.xml +++ b/.vortex/installer/tests/Fixtures/install/theme_absent/phpmd.xml @@ -4,5 +4,5 @@ */web/modules/contrib/* - */web/themes/contrib/* */web/sites/* + */recipes/* */scripts/* - */tests/*Test.php diff --git a/.vortex/installer/tests/Fixtures/install/tools_groups_no_be_tests/.gitignore b/.vortex/installer/tests/Fixtures/install/tools_groups_no_be_tests/.gitignore index ebbf780cb..8416ec994 100644 --- a/.vortex/installer/tests/Fixtures/install/tools_groups_no_be_tests/.gitignore +++ b/.vortex/installer/tests/Fixtures/install/tools_groups_no_be_tests/.gitignore @@ -1,4 +1,4 @@ -@@ -48,7 +48,6 @@ +@@ -51,7 +51,6 @@ web/themes/**/build .data .logs diff --git a/.vortex/installer/tests/Fixtures/install/tools_groups_no_be_tests_circleci/.gitignore b/.vortex/installer/tests/Fixtures/install/tools_groups_no_be_tests_circleci/.gitignore index ebbf780cb..8416ec994 100644 --- a/.vortex/installer/tests/Fixtures/install/tools_groups_no_be_tests_circleci/.gitignore +++ b/.vortex/installer/tests/Fixtures/install/tools_groups_no_be_tests_circleci/.gitignore @@ -1,4 +1,4 @@ -@@ -48,7 +48,6 @@ +@@ -51,7 +51,6 @@ web/themes/**/build .data .logs diff --git a/.vortex/installer/tests/Fixtures/install/tools_no_phpunit/.gitignore b/.vortex/installer/tests/Fixtures/install/tools_no_phpunit/.gitignore index ebbf780cb..8416ec994 100644 --- a/.vortex/installer/tests/Fixtures/install/tools_no_phpunit/.gitignore +++ b/.vortex/installer/tests/Fixtures/install/tools_no_phpunit/.gitignore @@ -1,4 +1,4 @@ -@@ -48,7 +48,6 @@ +@@ -51,7 +51,6 @@ web/themes/**/build .data .logs diff --git a/.vortex/installer/tests/Fixtures/install/tools_no_phpunit_circleci/.gitignore b/.vortex/installer/tests/Fixtures/install/tools_no_phpunit_circleci/.gitignore index ebbf780cb..8416ec994 100644 --- a/.vortex/installer/tests/Fixtures/install/tools_no_phpunit_circleci/.gitignore +++ b/.vortex/installer/tests/Fixtures/install/tools_no_phpunit_circleci/.gitignore @@ -1,4 +1,4 @@ -@@ -48,7 +48,6 @@ +@@ -51,7 +51,6 @@ web/themes/**/build .data .logs diff --git a/.vortex/installer/tests/Fixtures/install/tools_none/.gitignore b/.vortex/installer/tests/Fixtures/install/tools_none/.gitignore index ebbf780cb..8416ec994 100644 --- a/.vortex/installer/tests/Fixtures/install/tools_none/.gitignore +++ b/.vortex/installer/tests/Fixtures/install/tools_none/.gitignore @@ -1,4 +1,4 @@ -@@ -48,7 +48,6 @@ +@@ -51,7 +51,6 @@ web/themes/**/build .data .logs diff --git a/.vortex/installer/tests/Functional/Handlers/StarterInstallTest.php b/.vortex/installer/tests/Functional/Handlers/StarterInstallTest.php new file mode 100644 index 000000000..2dcd383b0 --- /dev/null +++ b/.vortex/installer/tests/Functional/Handlers/StarterInstallTest.php @@ -0,0 +1,37 @@ + [ + static::cw(fn() => Env::put(PromptManager::makeEnvName(Starter::id()), Starter::LOAD_DATABASE_DEMO)), + ], + + 'starter, Drupal profile' => [ + static::cw(fn() => Env::put(PromptManager::makeEnvName(Starter::id()), Starter::INSTALL_PROFILE_CORE)), + ], + + 'starter, Drupal CMS profile' => [ + static::cw(fn() => Env::put(PromptManager::makeEnvName(Starter::id()), Starter::INSTALL_PROFILE_DRUPALCMS)), + static::cw(fn(FunctionalTestCase $test) => $test->assertSutNotContains([ + 'drupal/cms', + 'wikimedia/composer-merge-plugin', + 'vendor/drupal/cms/composer.json', + ])), + ], + ]; + } + +} diff --git a/.vortex/installer/tests/Unit/Handlers/AbstractPromptManagerTestCase.php b/.vortex/installer/tests/Unit/Handlers/AbstractPromptManagerTestCase.php index 1a866c9fc..e25155d97 100644 --- a/.vortex/installer/tests/Unit/Handlers/AbstractPromptManagerTestCase.php +++ b/.vortex/installer/tests/Unit/Handlers/AbstractPromptManagerTestCase.php @@ -121,7 +121,7 @@ protected static function getExpectedDefaults(): array { Org::id() => 'myproject Org', OrgMachineName::id() => 'myproject_org', Domain::id() => 'myproject.com', - Starter::id() => Starter::DRUPAL_LOAD_DATABASE_DEMO, + Starter::id() => Starter::LOAD_DATABASE_DEMO, Profile::id() => Profile::STANDARD, ModulePrefix::id() => 'mypr', Theme::id() => 'myproject', diff --git a/.vortex/installer/tests/Unit/Handlers/StarterPromptManagerTest.php b/.vortex/installer/tests/Unit/Handlers/StarterPromptManagerTest.php index 1e2f0521d..2348203d6 100644 --- a/.vortex/installer/tests/Unit/Handlers/StarterPromptManagerTest.php +++ b/.vortex/installer/tests/Unit/Handlers/StarterPromptManagerTest.php @@ -4,6 +4,7 @@ namespace DrevOps\VortexInstaller\Tests\Unit\Handlers; +use DrevOps\VortexInstaller\Prompts\Handlers\Profile; use DrevOps\VortexInstaller\Prompts\Handlers\Starter; use Laravel\Prompts\Key; use PHPUnit\Framework\Attributes\CoversClass; @@ -17,17 +18,25 @@ public static function dataProviderRunPrompts(): array { return [ 'starter - prompt' => [ [Starter::id() => Key::ENTER], - [Starter::id() => Starter::DRUPAL_LOAD_DATABASE_DEMO] + $expected_defaults, + [Starter::id() => Starter::LOAD_DATABASE_DEMO] + $expected_defaults, ], - 'starter - prompt - profile' => [ + 'starter - prompt - Drupal profile' => [ [Starter::id() => Key::DOWN . Key::ENTER], - [Starter::id() => Starter::DRUPAL_INSTALL_PROFILE] + $expected_defaults, + [Starter::id() => Starter::INSTALL_PROFILE_CORE] + $expected_defaults, + ], + 'starter - prompt - Drupal CMS profile' => [ + [Starter::id() => Key::DOWN . Key::DOWN . Key::ENTER], + [ + Starter::id() => Starter::INSTALL_PROFILE_DRUPALCMS, + Profile::id() => Starter::INSTALL_PROFILE_DRUPALCMS_PATH, + ] + $expected_defaults, + ], 'starter - discovery' => [ [], - [Starter::id() => Starter::DRUPAL_LOAD_DATABASE_DEMO] + $expected_defaults, + [Starter::id() => Starter::LOAD_DATABASE_DEMO] + $expected_defaults, function (AbstractPromptManagerTestCase $test): void { // Noop. }, diff --git a/.vortex/tests/bats/_helper.bash b/.vortex/tests/bats/_helper.bash index faf6c2974..4a0457f2b 100644 --- a/.vortex/tests/bats/_helper.bash +++ b/.vortex/tests/bats/_helper.bash @@ -532,7 +532,7 @@ assert_files_present_drupal() { assert_dir_not_contains_string "${dir}" "YOURORG" assert_dir_not_contains_string "${dir}" "www.your-site-domain.example" # Assert all special comments were removed. - assert_dir_not_contains_string "${dir}" "#;" + # assert_dir_not_contains_string "${dir}" "#;" assert_dir_not_contains_string "${dir}" "#;<" assert_dir_not_contains_string "${dir}" "#;>" diff --git a/.vortex/tests/bats/e2e/workflow.install.profile_drupalcms.bats b/.vortex/tests/bats/e2e/workflow.install.profile_drupalcms.bats new file mode 100644 index 000000000..c1f3908f1 --- /dev/null +++ b/.vortex/tests/bats/e2e/workflow.install.profile_drupalcms.bats @@ -0,0 +1,40 @@ +#!/usr/bin/env bats +# +# Workflows using different types of install source. +# + +# shellcheck disable=SC2030,SC2031,SC2129 + +load ../_helper.bash +load ../_helper.workflow.bash + +@test "Workflow: profile-driven, Drupal CMS" { + rm -f .data/db.sql + export VORTEX_INSTALLER_IS_DEMO_DB_DOWNLOAD_SKIP=1 + assert_file_not_exists .data/db.sql + + export VORTEX_INSTALLER_PROMPT_STARTER="install_profile_drupalcms" + + prepare_sut "Starting fresh install WORKFLOW tests in build directory ${BUILD_DIR}" + # Assert that the database was not downloaded because VORTEX_INSTALLER_IS_DEMO_DB_DOWNLOAD_SKIP was set. + assert_file_not_exists .data/db.sql + + assert_file_contains .env "DRUPAL_PROFILE=../recipes/drupal_cms_starter" + assert_file_not_contains .env "DEMO" + assert_file_contains composer.json "drupal/cms" + assert_file_contains composer.json "wikimedia/composer-merge-plugin" + assert_file_contains composer.json "vendor/drupal/cms/composer.json" + + echo "VORTEX_PROVISION_TYPE=profile" >>.env + + assert_ahoy_build + assert_gitignore + + assert_ahoy_lint + + assert_ahoy_test "web" "1" + + assert_ahoy_fe + + assert_webpage_contains "/" "This is the home page of your new site." +} diff --git a/.vortex/tests/test.workflow.sh b/.vortex/tests/test.workflow.sh index 7f7a60f1b..fbb4e58e4 100755 --- a/.vortex/tests/test.workflow.sh +++ b/.vortex/tests/test.workflow.sh @@ -70,6 +70,7 @@ case ${index} in 3) bats "${TEST_DIR}"/bats/e2e/workflow.docker-compose.bats + bats "${TEST_DIR}"/bats/e2e/workflow.install.profile_drupalcms.bats bats "${TEST_DIR}"/bats/e2e/workflow.install.provision.bats bats "${TEST_DIR}"/bats/e2e/workflow.storage.image.bats # Disabled due to intermittent failures. @@ -81,6 +82,7 @@ case ${index} in phpunit "${TEST_DIR}"/phpunit bats "${TEST_DIR}"/bats/e2e/workflow.install.db.bats bats "${TEST_DIR}"/bats/e2e/workflow.install.profile.bats + bats "${TEST_DIR}"/bats/e2e/workflow.install.profile_drupalcms.bats bats "${TEST_DIR}"/bats/e2e/workflow.docker-compose.bats bats "${TEST_DIR}"/bats/e2e/workflow.install.provision.bats bats "${TEST_DIR}"/bats/e2e/workflow.storage.image.bats diff --git a/composer.json b/composer.json index ae997e161..22be58429 100644 --- a/composer.json +++ b/composer.json @@ -130,6 +130,9 @@ "web/profiles/contrib/{$name}": [ "type:drupal-profile" ], + "recipes/{$name}": [ + "type:drupal-recipe" + ], "web/themes/contrib/{$name}": [ "type:drupal-theme" ], diff --git a/phpmd.xml b/phpmd.xml index 34eac0634..c979582cd 100644 --- a/phpmd.xml +++ b/phpmd.xml @@ -14,6 +14,7 @@ */web/modules/contrib/* */web/themes/contrib/* */web/sites/* + */recipes/* */scripts/* */tests/*Test.php diff --git a/tests/behat/features/search.feature b/tests/behat/features/search.feature index 8e7aa9994..dadff2697 100644 --- a/tests/behat/features/search.feature +++ b/tests/behat/features/search.feature @@ -8,26 +8,26 @@ Feature: Search API @api Scenario: User searches for Page content Given page content: - | title | body | status | - | [TEST] Test page 1 | test content uniquestring | 1 | - | [TEST] Test page 2 | test content otheruniquestring | 1 | - And I add the "page" content with the title "[TEST] Test page 1" to the search index - And I add the "page" content with the title "[TEST] Test page 2" to the search index - And I run search indexing for 2 items - And I visit "/search" + | title | status | moderation_state | + | [TEST] Test page uniquestring | 1 | published | + | [TEST] Test page otheruniquestring | 1 | published | + | [TEST] Test page thirduniquestring | 0 | draft | + And I add the "page" content with the title "[TEST] Test page uniquestring" to the search index + And I add the "page" content with the title "[TEST] Test page otheruniquestring" to the search index + And I add the "page" content with the title "[TEST] Test page thirduniquestring" to the search index + And I run search indexing for 3 items And I wait for 5 seconds + And I visit "/search" And save screenshot When I fill in "search_api_fulltext" with "[TEST]" And I press "Apply" - Then I should see "[TEST] Test page 1" in the ".view-content" element - And I should see "test content uniquestring" in the ".view-content" element - And I should see "[TEST] Test page 2" in the ".view-content" element - And I should see "test content otheruniquestring" in the ".view-content" element + Then I should see "[TEST] Test page uniquestring" in the ".view-content" element + And I should see "[TEST] Test page otheruniquestring" in the ".view-content" element + And I should not see "[TEST] Test page thirduniquestring" in the ".view-content" element When I fill in "search_api_fulltext" with "otheruniquestring" And I press "Apply" - Then I should not see "[TEST] Test page 1" in the ".view-content" element - And I should not see "test content uniquestring" in the ".view-content" element - And I should see "[TEST] Test page 2" in the ".view-content" element - And I should see "test content otheruniquestring" in the ".view-content" element + Then I should not see "[TEST] Test page uniquestring" in the ".view-content" element + And I should see "[TEST] Test page otheruniquestring" in the ".view-content" element + And I should not see "[TEST] Test page thirduniquestring" in the ".view-content" element diff --git a/web/modules/custom/ys_search/config/install/search_api.index.content.yml b/web/modules/custom/ys_search/config/install/search_api.index.content.yml index a5ada20e1..f4929115f 100644 --- a/web/modules/custom/ys_search/config/install/search_api.index.content.yml +++ b/web/modules/custom/ys_search/config/install/search_api.index.content.yml @@ -2,7 +2,6 @@ langcode: en status: true dependencies: config: - - field.storage.node.body - search_api.server.solr module: - node @@ -59,14 +58,14 @@ name: Content description: '' read_only: false field_settings: - processed: - label: 'Body » Processed text' + status: + label: Published datasource_id: 'entity:node' - property_path: 'body:processed' - type: 'solr_text_custom:ngram' + property_path: status + type: boolean dependencies: - config: - - field.storage.node.body + module: + - node title: label: Title datasource_id: 'entity:node' diff --git a/web/modules/custom/ys_search/config/install/views.view.search.yml b/web/modules/custom/ys_search/config/install/views.view.search.yml index 0535388d4..2be400732 100644 --- a/web/modules/custom/ys_search/config/install/views.view.search.yml +++ b/web/modules/custom/ys_search/config/install/views.view.search.yml @@ -143,9 +143,6 @@ display: multiple: false remember_roles: authenticated: authenticated - anonymous: '0' - content_editor: '0' - administrator: '0' expose_fields: false placeholder: '' searched_fields_id: search_api_fulltext_searched_fields @@ -165,6 +162,44 @@ display: parse_mode: terms min_length: null fields: { } + status: + id: status + table: search_api_index_content + field: status + relationship: none + group_type: group + admin_label: '' + plugin_id: search_api_boolean + operator: '=' + value: '1' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + operator_limit_selection: false + operator_list: { } + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } style: type: default row: @@ -172,8 +207,7 @@ display: options: view_modes: 'entity:node': - ':default': default - article: ':default' + ':default': teaser page: ':default' query: type: search_api_query From c90ee6a9b410282651de2df2b79765ca19ac7aeb Mon Sep 17 00:00:00 2001 From: Alex Skrypnyk Date: Tue, 2 Sep 2025 09:06:09 +1000 Subject: [PATCH 2/2] Re-balanced Vortex own tests. --- .github/workflows/vortex-test-common.yml | 6 +++--- .vortex/tests/test.workflow.sh | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/vortex-test-common.yml b/.github/workflows/vortex-test-common.yml index 090c71e9d..20d1759de 100644 --- a/.github/workflows/vortex-test-common.yml +++ b/.github/workflows/vortex-test-common.yml @@ -114,9 +114,9 @@ jobs: runs-on: ubuntu-latest strategy: - fail-fast: false + fail-fast: true matrix: - batch: [0, 1, 2, 3] + batch: [0, 1, 2, 3, 4] container: image: drevops/ci-runner:25.8.0@sha256:d6ba40fc4248ce291302a2cf212de9b80da5433f2fdf29be09ed59659df9e18d @@ -183,7 +183,7 @@ jobs: runs-on: ubuntu-latest strategy: - fail-fast: false + fail-fast: true matrix: batch: [0, 1] diff --git a/.vortex/tests/test.workflow.sh b/.vortex/tests/test.workflow.sh index fbb4e58e4..5a9747a60 100755 --- a/.vortex/tests/test.workflow.sh +++ b/.vortex/tests/test.workflow.sh @@ -69,12 +69,14 @@ case ${index} in ;; 3) - bats "${TEST_DIR}"/bats/e2e/workflow.docker-compose.bats bats "${TEST_DIR}"/bats/e2e/workflow.install.profile_drupalcms.bats + ;; + + 4) + bats "${TEST_DIR}"/bats/e2e/workflow.docker-compose.bats bats "${TEST_DIR}"/bats/e2e/workflow.install.provision.bats bats "${TEST_DIR}"/bats/e2e/workflow.storage.image.bats # Disabled due to intermittent failures. - # @see https://github.com/drevops/vortex/issues/893 # bats "${TEST_DIR}"/bats/e2e/workflow.storage.image_cached.bats ;; @@ -87,7 +89,6 @@ case ${index} in bats "${TEST_DIR}"/bats/e2e/workflow.install.provision.bats bats "${TEST_DIR}"/bats/e2e/workflow.storage.image.bats # Disabled due to intermittent failures. - # @see https://github.com/drevops/vortex/issues/893 # bats "${TEST_DIR}"/bats/e2e/workflow.storage.image_cached.bats ;; esac