From b68dc4118d6ba50bc444e3a1e6946703e5a26063 Mon Sep 17 00:00:00 2001 From: Lisa Lindsey Date: Mon, 30 Dec 2024 10:46:36 -0600 Subject: [PATCH 1/8] Create CMS Announcement Template for Editors --- READMES/CMS Announcement Template for Editors | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 READMES/CMS Announcement Template for Editors diff --git a/READMES/CMS Announcement Template for Editors b/READMES/CMS Announcement Template for Editors new file mode 100644 index 0000000000..7cb0834e1c --- /dev/null +++ b/READMES/CMS Announcement Template for Editors @@ -0,0 +1,38 @@ +CMS Announcement Template for Editors +The purpose of this template is to use it when sharing a change to VA CMS that will impact editors to the CMS Announcements Page. When filling out this template, remember that your audience are editors and to follow VA.gov’s plain language guide. All instructions are in italics. +Overview +Brief summary of how this announcement directly affects content creation, editing, and publishing processes. +Date: Month ##, Year +Type of Change: For example: Workflow Update / Content Guidelines / System Enhancement / Editorial Process Change +Who is impacted: Editor and Content Type + +What’s Changing? +Specific changes to existing editorial workflow, new steps or processes to be implemented, and Impact on current content creation procedures. + +Why is it changing? +Explain the rationale for the change. +—------------------------------------------------------------------------------------------------- +Each section below is optional and to only be used if it is relevant to the change you are posting about. +Drupal CMS Updates +New Features: +Feature 1 relevant to editors +Feature 2 relevant to editors +Workflow Changes: +Modifications to editorial interface +New navigation or editing tools +(Optional) Content Guidelines Revision +Updated writing standards +New formatting requirements +Metadata and tagging guidelines +(Optional) Training and Support +Training Sessions: + Date and time of training + How to register/attend +Resources: +Link to updated editorial guidelines +Walkthrough of new CMS features +(Optional) Frequently Asked Questions (FAQ) +Q: How will this affect my current drafts? +A: Detailed explanation +Q: What if I encounter issues? +A: Troubleshooting guidance From 7c97d8789824f0a24bf9984944bd6bc594c03aab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 18:19:39 -0800 Subject: [PATCH 2/8] Bump va-gov/content-build from 0.0.3655 to 0.0.3656 (#20207) Bumps [va-gov/content-build](https://github.com/department-of-veterans-affairs/content-build) from 0.0.3655 to 0.0.3656. - [Release notes](https://github.com/department-of-veterans-affairs/content-build/releases) - [Commits](https://github.com/department-of-veterans-affairs/content-build/compare/v0.0.3655...v0.0.3656) --- updated-dependencies: - dependency-name: va-gov/content-build dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 4fd0fa3077..b9730884b5 100644 --- a/composer.json +++ b/composer.json @@ -228,7 +228,7 @@ "symfony/phpunit-bridge": "^7.1", "symfony/process": "^6.3", "symfony/routing": "^6.3", - "va-gov/content-build": "^0.0.3655", + "va-gov/content-build": "^0.0.3656", "vlucas/phpdotenv": "^5.6", "webflo/drupal-finder": "1.3.1", "webmozart/path-util": "^2.3", diff --git a/composer.lock b/composer.lock index 34e203638e..e1274e83ef 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1fa2ffdec82a120fc683f5623ce328b1", + "content-hash": "031fbf075a33d00a7864f01e99cd4109", "packages": [ { "name": "asm89/stack-cors", @@ -26902,16 +26902,16 @@ }, { "name": "va-gov/content-build", - "version": "v0.0.3655", + "version": "v0.0.3656", "source": { "type": "git", "url": "https://github.com/department-of-veterans-affairs/content-build.git", - "reference": "89b09b3660f4e0b7005675ec6f2b3a952c5616b4" + "reference": "46750775cf7b6d8c871753fc531dbad197230e4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/department-of-veterans-affairs/content-build/zipball/89b09b3660f4e0b7005675ec6f2b3a952c5616b4", - "reference": "89b09b3660f4e0b7005675ec6f2b3a952c5616b4", + "url": "https://api.github.com/repos/department-of-veterans-affairs/content-build/zipball/46750775cf7b6d8c871753fc531dbad197230e4a", + "reference": "46750775cf7b6d8c871753fc531dbad197230e4a", "shasum": "" }, "type": "node-project", @@ -26938,9 +26938,9 @@ "description": "Front-end for VA.gov. This repository contains the code that generates the www.va.gov website. It contains a Metalsmith static site builder that uses a Drupal CMS for content. This file is here to publish releases to https://packagist.org/packages/va-gov/content-build, so that the CMS CI system can install it and update it using standard composer processes, and so that we can run tests across both systems. See https://github.com/department-of-veterans-affairs/va.gov-cms for the CMS repo, and stand by for more documentation.", "support": { "issues": "https://github.com/department-of-veterans-affairs/content-build/issues", - "source": "https://github.com/department-of-veterans-affairs/content-build/tree/v0.0.3655" + "source": "https://github.com/department-of-veterans-affairs/content-build/tree/v0.0.3656" }, - "time": "2024-12-20T15:41:52+00:00" + "time": "2025-01-02T23:33:14+00:00" }, { "name": "vlucas/phpdotenv", From 3653c51c98398b0cfeeb2223205c1df90088a79c Mon Sep 17 00:00:00 2001 From: Ryan Koch <6863534+ryguyk@users.noreply.github.com> Date: Mon, 6 Jan 2025 10:32:53 -0600 Subject: [PATCH 3/8] VAGOV-TEAM-97920: Form Builder Navbar (#20149) * VAGOV-TEAM-97920: - Renames form-builder theme and sets it as page-level theme. * Allows for active tab to be set on each path. * Updates page template and styles for navbar * Removes unnecessary properties from base form. * Adds id class to each navbar tab * Adds unpkg external stylesheet to the module-defined library. * Attaches styles at page level rather than form level. * Adds unit test for libraries.yml. * Updates existing test suites. * Updates class names in test to reflect changes in template. --- .../css/va_gov_form_builder.css | 90 ++++++++++++++++++- .../Controller/VaGovFormBuilderController.php | 45 +++++++++- .../src/Form/Base/FormBuilderBase.php | 22 ++--- .../page--va-gov-form-builder.html.twig | 70 ++++++++++----- .../va_gov_form_builder.libraries.yml | 2 + .../va_gov_form_builder.module | 6 +- .../VaGovFormBuilderControllerTest.php | 31 +++++-- .../functional/Form/IntroTest.php | 14 ++- .../functional/Form/NameAndDobTest.php | 20 +++-- .../functional/Form/StartConversionTest.php | 23 +++-- .../templates/FormBuilderPageTemplateTest.php | 4 +- .../unit/Form/Base/FormBuilderBaseTest.php | 29 +----- .../unit/LibrariesTest.php | 71 +++++++++++++++ .../va_gov_form_builder/unit/ModuleTest.php | 10 +-- 14 files changed, 332 insertions(+), 105 deletions(-) create mode 100644 tests/phpunit/va_gov_form_builder/unit/LibrariesTest.php diff --git a/docroot/modules/custom/va_gov_form_builder/css/va_gov_form_builder.css b/docroot/modules/custom/va_gov_form_builder/css/va_gov_form_builder.css index e5f1ffc8dc..80bc63ece9 100644 --- a/docroot/modules/custom/va_gov_form_builder/css/va_gov_form_builder.css +++ b/docroot/modules/custom/va_gov_form_builder/css/va_gov_form_builder.css @@ -1,4 +1,92 @@ /* page container */ -.va-gov-form-builder-page-container { +.form-builder-page-container { font-family: var(--font-family-serif); } + +/* headings */ +.form-builder-page-container h1 { + font-size: var(--vads-font-size-heading-level-1); + line-height: var(--units-6); +} + +.form-builder-page-container h2 { + font-size: var(--vads-font-size-heading-level-2); +} + +.form-builder-page-container h2 { + font-size: var(--vads-font-size-heading-level-2); +} + +.form-builder-page-container h3 { + font-size: var(--vads-font-size-heading-level-3); +} + +.form-builder-page-container h4 { + font-size: var(--vads-font-size-heading-level-4); +} + +.form-builder-page-container h5 { + font-size: var(--vads-font-size-heading-level-5); +} + +.form-builder-page-container h6 { + font-size: var(--vads-font-size-heading-level-6); +} + +/* header */ +.form-builder-header { + background-color: var(--va-blue-darkest); + color: var(--va-white); + padding-top: var(--units-1); +} + +/* layout container */ +.form-builder-layout-container { + margin: 0 var(--units-7); +} + +/* title */ +.form-builder-title { + margin-bottom: var(--units-1p5); +} + +/* navbar */ +.form-builder-navbar__nav { + display: flex; +} + +.form-builder-navbar__tabs { + display: flex; + gap: var(--units-5); + list-style: none; + margin: 0; +} + +.form-builder-navbar__tab { + min-width: 100px; + padding: var(--units-1); + position: relative; + text-align: center; +} + +.form-builder-navbar__tab--active { + border-bottom: var(--units-0p5) solid var(--uswds-system-color-gold-vivid-20); +} + +.form-builder-navbar__link { + color: var(--vads-color-white); + font-size: var(--font-size-lg); + font-weight: var(--font-weight-bold); + line-height: var(--vads-font-line-height-default); + text-decoration: none; +} + +.form-builder-navbar__link:hover { + background: transparent; + color: var(--vads-color-white); +} + +.form-builder-navbar__tab--active .form-builder-navbar__link, +.form-builder-navbar__tab--active .form-builder-navbar__link:hover { + color: var(--uswds-system-color-gold-vivid-20); +} diff --git a/docroot/modules/custom/va_gov_form_builder/src/Controller/VaGovFormBuilderController.php b/docroot/modules/custom/va_gov_form_builder/src/Controller/VaGovFormBuilderController.php index 82308e899b..5217021410 100644 --- a/docroot/modules/custom/va_gov_form_builder/src/Controller/VaGovFormBuilderController.php +++ b/docroot/modules/custom/va_gov_form_builder/src/Controller/VaGovFormBuilderController.php @@ -31,6 +31,13 @@ class VaGovFormBuilderController extends ControllerBase { */ private $drupalFormBuilder; + /** + * The active tab in the form builder. + * + * @var 'forms'|'content'|'layout' + */ + private $activeTab; + /** * {@inheritdoc} */ @@ -41,6 +48,34 @@ public static function create(ContainerInterface $container) { return $instance; } + /** + * Returns a render array representing the page with the passed-in form. + * + * @param string $formName + * The filename of the form to be rendered. + * @param string $nid + * The node id, passed in when the form in question edits an existing node. + */ + private function getFormPage($formName, $nid = NULL) { + // @phpstan-ignore-next-line + $form = $this->drupalFormBuilder->getForm('Drupal\va_gov_form_builder\Form\\' . $formName, $nid); + + return [ + '#type' => 'page', + 'content' => $form, + // Add custom data. + 'form_builder_page_data' => [ + 'active_tab' => $this->activeTab, + ], + // Add styles. + '#attached' => [ + 'library' => [ + 'va_gov_form_builder/va_gov_form_builder_styles', + ], + ], + ]; + } + /** * Entry point for the VA Form Builder. Redirects to the intro page. */ @@ -52,22 +87,24 @@ public function entry() { * Intro page. */ public function intro() { - return $this->drupalFormBuilder->getForm('Drupal\va_gov_form_builder\Form\Intro'); + $this->activeTab = 'forms'; + return $this->getFormPage('Intro'); } /** * Start-conversion page. */ public function startConversion() { - return $this->drupalFormBuilder->getForm('Drupal\va_gov_form_builder\Form\StartConversion'); + $this->activeTab = 'forms'; + return $this->getFormPage('StartConversion'); } /** * Name-and-date-of-birth page. */ public function nameAndDob($nid) { - // @phpstan-ignore-next-line - return $this->drupalFormBuilder->getForm('Drupal\va_gov_form_builder\Form\NameAndDob', $nid); + $this->activeTab = 'content'; + return $this->getFormPage('NameAndDob', $nid); } } diff --git a/docroot/modules/custom/va_gov_form_builder/src/Form/Base/FormBuilderBase.php b/docroot/modules/custom/va_gov_form_builder/src/Form/Base/FormBuilderBase.php index fdf2f6c7c2..da73db7070 100644 --- a/docroot/modules/custom/va_gov_form_builder/src/Form/Base/FormBuilderBase.php +++ b/docroot/modules/custom/va_gov_form_builder/src/Form/Base/FormBuilderBase.php @@ -12,25 +12,13 @@ abstract class FormBuilderBase extends FormBase { /** * {@inheritdoc} + * + * After initially containing some logic, this function + * is now empty, and this entire class is a candiate + * for removal. Leaving it here for now, as it might prove + * necessary as we continue on. */ public function buildForm(array $form, FormStateInterface $form_state) { - $form['#theme'] = 'va_gov_form_builder'; - $form['#title'] = $this->t('Form Builder'); - - // Add styles. - $form['#attached']['html_head'][] = [ - [ - '#tag' => 'link', - '#attributes' => [ - 'rel' => 'stylesheet', - 'href' => 'https://unpkg.com/@department-of-veterans-affairs/css-library@0.16.0/dist/tokens/css/variables.css', - ], - ], - 'external_stylesheet', - ]; - $form['#attached']['library'][] = 'va_gov_form_builder/va_gov_form_builder_styles'; - - return $form; } } diff --git a/docroot/modules/custom/va_gov_form_builder/templates/page--va-gov-form-builder.html.twig b/docroot/modules/custom/va_gov_form_builder/templates/page--va-gov-form-builder.html.twig index 86efcd7ae3..0bc5004f56 100644 --- a/docroot/modules/custom/va_gov_form_builder/templates/page--va-gov-form-builder.html.twig +++ b/docroot/modules/custom/va_gov_form_builder/templates/page--va-gov-form-builder.html.twig @@ -3,38 +3,66 @@ * @file * VA.gov Form Builder's implementation of a single page. * - * Nearly identical to VAgovClaro's implementation, except: - * - An outermost page container has been added. - * - The header includes additional content (navbar, eventually) - * - Breadcrumbs have been removed + * The variables available to this template are passed from the controller: + * - page + * - content: The main content of the page; the individual form + * - form_builder_page_data + * - active_tab: The active tab in the navbar * - * For more information: - * @see docroot/themes/custom/vagovclaro/templates/page/page.html.twig + * @see /docroot/modules/custom/va_gov_form_builder/src/Controller/VaGovFormBuilderController.php */ #} -
-
-
- {{ page.header }} +
+
+
-
- +
+

Form Builder

+
+ + {% set active_tab = page.form_builder_page_data.active_tab %} +
+
-
- {{ page.pre_content }} - +
- {{ page.highlighted }} - {% if page.help %} -
- {{ page.help }} -
- {% endif %} + + {# The form content #} {{ page.content }} +
diff --git a/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.libraries.yml b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.libraries.yml index 8d4fd5bf12..4c70ae555e 100644 --- a/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.libraries.yml +++ b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.libraries.yml @@ -3,3 +3,5 @@ va_gov_form_builder_styles: css: theme: css/va_gov_form_builder.css: {} + https://unpkg.com/@department-of-veterans-affairs/css-library@0.16.0/dist/tokens/css/variables.css: + {} diff --git a/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.module b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.module index e3f9b98dca..69e564509f 100644 --- a/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.module +++ b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.module @@ -23,8 +23,8 @@ function va_gov_form_builder_entity_bundle_field_info_alter(&$fields, EntityType */ function va_gov_form_builder_theme() { return [ - 'va_gov_form_builder_page' => [ - 'template' => 'page--va-gov-form-builder', + 'page__va_gov_form_builder' => [ + 'base hook' => 'page', 'path' => \Drupal::service('extension.list.module')->getPath('va_gov_form_builder') . '/templates', ], ]; @@ -39,7 +39,7 @@ function va_gov_form_builder_theme_suggestions_page(array &$variables) { // Apply custom page template for all Form Builder routes. if (strpos($route_name, 'va_gov_form_builder.') === 0) { - $suggestions[] = 'va_gov_form_builder_page'; + $suggestions[] = 'page__va_gov_form_builder'; } return $suggestions; diff --git a/tests/phpunit/va_gov_form_builder/functional/Controller/VaGovFormBuilderControllerTest.php b/tests/phpunit/va_gov_form_builder/functional/Controller/VaGovFormBuilderControllerTest.php index 6f28128fe5..7c6bdae099 100644 --- a/tests/phpunit/va_gov_form_builder/functional/Controller/VaGovFormBuilderControllerTest.php +++ b/tests/phpunit/va_gov_form_builder/functional/Controller/VaGovFormBuilderControllerTest.php @@ -41,6 +41,19 @@ public function setUp(): void { $this->controller = VaGovFormBuilderController::create($container); } + /** + * Tests css is included. + */ + public function testCssIncluded() { + $page = $this->controller->intro(); + + $this->assertContains( + 'va_gov_form_builder/va_gov_form_builder_styles', + $page['#attached']['library'], + "The library 'va_gov_form_builder/va_gov_form_builder_styles' is successfully attached." + ); + } + /** * Tests the entry method redirects correctly. */ @@ -55,20 +68,20 @@ public function testEntryRedirect() { * Tests the intro method returns an Intro form. */ public function testIntro() { - $form = $this->controller->intro(); + $page = $this->controller->intro(); - $this->assertArrayHasKey('#type', $form); - $this->assertArrayHasKey('working_with_form_builder_header', $form); + $this->assertArrayHasKey('content', $page); + $this->assertArrayHasKey('working_with_form_builder_header', $page['content']); } /** * Tests the startConversion method returns a StartConversion form. */ public function testStartConversion() { - $form = $this->controller->startConversion(); + $page = $this->controller->startConversion(); - $this->assertArrayHasKey('#type', $form); - $this->assertArrayHasKey('start_new_conversion_header', $form); + $this->assertArrayHasKey('content', $page); + $this->assertArrayHasKey('start_new_conversion_header', $page['content']); } /** @@ -81,10 +94,10 @@ public function testNameAndDob() { 'field_chapters' => [], ]); - $form = $this->controller->nameAndDob($node->id()); + $page = $this->controller->nameAndDob($node->id()); - $this->assertArrayHasKey('#type', $form); - $this->assertArrayHasKey('name_and_dob_header', $form); + $this->assertArrayHasKey('content', $page); + $this->assertArrayHasKey('name_and_dob_header', $page['content']); } } diff --git a/tests/phpunit/va_gov_form_builder/functional/Form/IntroTest.php b/tests/phpunit/va_gov_form_builder/functional/Form/IntroTest.php index c3ff795837..80d6905791 100644 --- a/tests/phpunit/va_gov_form_builder/functional/Form/IntroTest.php +++ b/tests/phpunit/va_gov_form_builder/functional/Form/IntroTest.php @@ -20,7 +20,7 @@ class IntroTest extends VaGovExistingSiteBase { private static $modules = ['va_gov_form_builder']; /** - * Setup the environment for each test. + * Set up the environment for each test. */ public function setUp(): void { parent::setUp(); @@ -30,7 +30,7 @@ public function setUp(): void { } /** - * Test the form is accessible to a user with the correct privilege. + * Test that the form is accessible to a user with the correct privilege. */ public function testFormLoads() { $this->assertSession()->statusCodeEquals(200); @@ -38,7 +38,7 @@ public function testFormLoads() { } /** - * Test the form is not accessible to a user without the correct privilege. + * Test that the form is not accessible to a user without privilege. */ public function testFormDoesNotLoad() { // Log out the good user and log in a user without permission. @@ -48,6 +48,14 @@ public function testFormDoesNotLoad() { $this->assertSession()->statusCodeNotEquals(200); } + /** + * Test that the active tab is correct. + */ + public function testActiveTab() { + $activeTab = $this->getSession()->getPage()->find('css', '.form-builder-navbar__tab--active'); + $this->assertTrue($activeTab->hasClass('form-builder-navbar__tab--forms'), 'The expected tab is active.'); + } + /** * Test the 'Start conversion' button. */ diff --git a/tests/phpunit/va_gov_form_builder/functional/Form/NameAndDobTest.php b/tests/phpunit/va_gov_form_builder/functional/Form/NameAndDobTest.php index 67caf734e2..98a963b380 100644 --- a/tests/phpunit/va_gov_form_builder/functional/Form/NameAndDobTest.php +++ b/tests/phpunit/va_gov_form_builder/functional/Form/NameAndDobTest.php @@ -48,7 +48,7 @@ private function reloadNode() { } /** - * Setup the environment for each test. + * Set up the environment for each test. */ public function setUp(): void { parent::setUp(); @@ -65,21 +65,29 @@ public function setUp(): void { } /** - * Test the form is accessible to a user with the correct privilege. + * Test that the form is accessible to a user with the correct privilege. */ public function testFormLoads() { $this->sharedTestFormLoads($this->getFormPageUrl(), 'Collecting Name and Date of birth'); } /** - * Test the form is not accessible to a user without the correct privilege. + * Test that the form is not accessible to a user without privilege. */ public function testFormDoesNotLoad() { $this->sharedTestFormDoesNotLoad($this->getFormPageUrl()); } /** - * Test the form submission adds a chapter when not already present. + * Test that the active tab is correct. + */ + public function testActiveTab() { + $activeTab = $this->getSession()->getPage()->find('css', '.form-builder-navbar__tab--active'); + $this->assertTrue($activeTab->hasClass('form-builder-navbar__tab--content'), 'The expected tab is active.'); + } + + /** + * Test that the form submission adds a chapter when not already present. */ public function testFormSubmissionAddsChapter() { $formInput = [ @@ -93,7 +101,7 @@ public function testFormSubmissionAddsChapter() { } /** - * Test the form submission does not add a chapter when already present. + * Test that the form submission does not add a chapter when already present. */ public function testFormSubmissionDoesNotAddChapter() { // Add a chapter to begin. @@ -116,7 +124,7 @@ public function testFormSubmissionDoesNotAddChapter() { } /** - * Test the 'Back' button takes the user back to the start-conversion page. + * Test that the 'Back' button takes the user to the start-conversion page. */ public function testBackButton() { $this->click('.button#edit-back'); diff --git a/tests/phpunit/va_gov_form_builder/functional/Form/StartConversionTest.php b/tests/phpunit/va_gov_form_builder/functional/Form/StartConversionTest.php index d5b26a80e0..cdb1aeae36 100644 --- a/tests/phpunit/va_gov_form_builder/functional/Form/StartConversionTest.php +++ b/tests/phpunit/va_gov_form_builder/functional/Form/StartConversionTest.php @@ -32,7 +32,7 @@ private function getFormPageUrl() { } /** - * Setup the environment for each test. + * Set up the environment for each test. */ public function setUp(): void { parent::setUp(); @@ -42,21 +42,29 @@ public function setUp(): void { } /** - * Test the form is accessible to a user with the correct privilege. + * Test that the form is accessible to a user with the correct privilege. */ public function testFormLoads() { $this->sharedTestFormLoads($this->getFormPageUrl(), 'Start a new conversion'); } /** - * Test the form is not accessible to a user without the correct privilege. + * Test that the form is not accessible to a user without privilege. */ public function testFormDoesNotLoad() { $this->sharedTestFormDoesNotLoad($this->getFormPageUrl()); } /** - * Test the form submission succeeds. + * Test that the active tab is correct. + */ + public function testActiveTab() { + $activeTab = $this->getSession()->getPage()->find('css', '.form-builder-navbar__tab--active'); + $this->assertTrue($activeTab->hasClass('form-builder-navbar__tab--forms'), 'The expected tab is active.'); + } + + /** + * Test that the form submission succeeds. * * When proper information is entered, form should be submitted. */ @@ -71,8 +79,9 @@ public function testFormSubmissionSucceeds() { ]; $this->submitForm($formInput, 'Continue'); - // Check if the form submission was successful. - $this->assertSession()->pageTextNotContains('error has been found'); + // Successful submission should take user to next page. + $nextPageUrl = $this->getSession()->getCurrentUrl(); + $this->assertStringContainsString('/name-and-dob', $nextPageUrl); } /** @@ -90,7 +99,7 @@ public function testFormSubmissionFailsOnMissingRequiredField() { $this->submitForm($formInput, 'Continue'); // Check if the form submission was successful. - $this->assertSession()->pageTextContains('error has been found'); + $this->assertSession()->pageTextContains('Expiration date field is required.'); } /** diff --git a/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php b/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php index ab468cc5de..34f201df60 100644 --- a/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php +++ b/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php @@ -46,10 +46,10 @@ public function setUp(): void { public function testExpectedElementsExist() { $this->assertSession()->statusCodeEquals(200); - $containerElement = $this->cssSelect('.va-gov-form-builder-page-container'); + $containerElement = $this->cssSelect('.form-builder-page-container'); $this->assertCount(1, $containerElement); - $navbarElement = $this->cssSelect('.va-gov-form-builder-navbar'); + $navbarElement = $this->cssSelect('.form-builder-navbar'); $this->assertCount(1, $navbarElement); } diff --git a/tests/phpunit/va_gov_form_builder/unit/Form/Base/FormBuilderBaseTest.php b/tests/phpunit/va_gov_form_builder/unit/Form/Base/FormBuilderBaseTest.php index 1013072297..bd5246132c 100644 --- a/tests/phpunit/va_gov_form_builder/unit/Form/Base/FormBuilderBaseTest.php +++ b/tests/phpunit/va_gov_form_builder/unit/Form/Base/FormBuilderBaseTest.php @@ -28,6 +28,8 @@ class FormBuilderBaseTest extends VaGovUnitTestBase { * Setup the environment for each test. */ public function setUp(): void { + $this->markTestSkipped('Skipping all tests in this file.'); + parent::setUp(); // Create an anonymous instance of a class that extends our abstract class. @@ -44,33 +46,6 @@ public function testBuildForm() { $formStateMock = $this->createMock(FormStateInterface::class); $form = $this->classInstance->buildForm($form, $formStateMock); - - // Title. - $this->assertArrayHasKey('#title', $form); - $this->assertEquals($form['#title'], 'Form Builder'); - - // CSS. - $this->assertArrayHasKey('#attached', $form); - - // 1. Form Builder Library. - $this->assertArrayHasKey('html_head', $form['#attached']); - $this->assertNotEmpty($form['#attached']['html_head']); - - $found = FALSE; - foreach ($form['#attached']['html_head'] as $html_head_item) { - if ( - isset($html_head_item[0]['#attributes']['href']) && - $html_head_item[0]['#attributes']['href'] === 'https://unpkg.com/@department-of-veterans-affairs/css-library@0.16.0/dist/tokens/css/variables.css' - ) { - $found = TRUE; - break; - } - } - $this->assertTrue($found, 'The html_head array contains a link with the unpkg token url.'); - - // 2. External CSS. - $this->assertArrayHasKey('library', $form['#attached']); - $this->assertContains('va_gov_form_builder/va_gov_form_builder_styles', $form['#attached']['library']); } } diff --git a/tests/phpunit/va_gov_form_builder/unit/LibrariesTest.php b/tests/phpunit/va_gov_form_builder/unit/LibrariesTest.php new file mode 100644 index 0000000000..d306020496 --- /dev/null +++ b/tests/phpunit/va_gov_form_builder/unit/LibrariesTest.php @@ -0,0 +1,71 @@ + + * }, + * js?: array, + * dependencies?: array + * } + */ + private $libraries; + + /** + * Set up the environment for each test. + */ + protected function setUp(): void { + parent::setUp(); + + // Find Drupal root. + $drupalFinder = new DrupalFinder(); + $drupalFinder->locateRoot(__DIR__); + $drupalRoot = $drupalFinder->getDrupalRoot(); + + $yamlFile = $drupalRoot . '/' . $this->modulePath . '/va_gov_form_builder.libraries.yml'; + + $this->libraries = Yaml::parseFile($yamlFile); + } + + /** + * Tests that the library definition contains necessary css. + */ + public function testLibraryCss() { + $this->assertArrayHasKey('va_gov_form_builder_styles', $this->libraries); + $this->assertArrayHasKey('css', $this->libraries['va_gov_form_builder_styles']); + $this->assertArrayHasKey('theme', $this->libraries['va_gov_form_builder_styles']['css']); + + $cssArray = array_keys($this->libraries['va_gov_form_builder_styles']['css']['theme']); + + // Assert Form Builder css is present. + $this->assertContains('css/va_gov_form_builder.css', $cssArray, 'Form Builder css is present.'); + + // Assert external VADS tokens definition is present. + $matches = preg_grep('/unpkg.*@department-of-veterans-affairs.*css-library.*tokens\/css\/variables.css/', $cssArray); + $this->assertNotEmpty($matches, 'VADS tokens css is present.'); + } + +} diff --git a/tests/phpunit/va_gov_form_builder/unit/ModuleTest.php b/tests/phpunit/va_gov_form_builder/unit/ModuleTest.php index 6e41d85f00..07ad0b2858 100644 --- a/tests/phpunit/va_gov_form_builder/unit/ModuleTest.php +++ b/tests/phpunit/va_gov_form_builder/unit/ModuleTest.php @@ -31,7 +31,7 @@ class ModuleTest extends VaGovUnitTestBase { private $container; /** - * Setup the environment for each test. + * Set up the environment for each test. */ protected function setUp(): void { parent::setUp(); @@ -69,9 +69,9 @@ public function testVaGovFormBuilderHookTheme() { $result = va_gov_form_builder_theme(); // Assert the expected theme definition exists. - $this->assertArrayHasKey('va_gov_form_builder_page', $result); - $this->assertEquals('page--va-gov-form-builder', $result['va_gov_form_builder_page']['template']); - $this->assertEquals($this->modulePath . '/templates', $result['va_gov_form_builder_page']['path']); + $this->assertArrayHasKey('page__va_gov_form_builder', $result); + $this->assertEquals('page', $result['page__va_gov_form_builder']['base hook']); + $this->assertEquals($this->modulePath . '/templates', $result['page__va_gov_form_builder']['path']); } /** @@ -96,7 +96,7 @@ public function testVaGovFormBuilderThemeSuggestionsPage() { $suggestions = va_gov_form_builder_theme_suggestions_page($variables); // Assert the expected theme suggestion is returned. - $this->assertContains('va_gov_form_builder_page', $suggestions); + $this->assertContains('page__va_gov_form_builder', $suggestions); } } From 3a22d8450070a185277af9052e88b1fdb54c0dc9 Mon Sep 17 00:00:00 2001 From: Daniel Sasser <221539+dsasser@users.noreply.github.com> Date: Mon, 6 Jan 2025 10:36:47 -0800 Subject: [PATCH 4/8] VACMS-19098: VBA Facility Workflow Notifications (#20109) * VACMS-19098: Adds new AdvancedQueue processor plugin for Content Workflow notifications. * VACMS-19098: Adds new direct recipient option to VA.gov AdvancedQueue job type base plugin. * VACMS-19098: Adds eca_workflow module to the system. * VACMS-19098: Adds new queue for workflow content notifications. * VACMS-19098: Adds new message template for VBA Facility draft content notifications. * VACMS-19098: Adds new ECA workflow that triggers draft notifcations for VBA Facility nodes workflow state transitions. * VACMS-19098: Theme changes for rendering Content Workflow: VBA Facility message body using standard email template. * VACMS-19098: Renames field_field_target_node_path to field_target_node_path. * VACMS-19098: Adds vba_facility_draft_content to mailsystem configuration to allow for html multi-part emails. * VACMS-19098: Turns on the VBA Facility workflow ECA model. * VACMS-19098: Correct faulty return comment. * Update config/sync/language/en/message.template.vba_facility_draft_content.yml Co-authored-by: Christian Burk <766573+omahane@users.noreply.github.com> * I missed this comma change, too. * VACMS-19098: Add the 'reject' portion of the email body. --------- Co-authored-by: Christian Burk <766573+omahane@users.noreply.github.com> --- ...ue.advancedqueue_queue.content_worfkow.yml | 17 ++++ ...age.vba_facility_draft_content.default.yml | 56 +++++++++++ ...age.vba_facility_draft_content.default.yml | 46 +++++++++ ...e.vba_facility_draft_content.mail_body.yml | 32 +++++++ ...ba_facility_draft_content.mail_subject.yml | 32 +++++++ config/sync/core.extension.yml | 1 + ...eca.eca.workflow_vba_facility_as_draft.yml | 93 +++++++++++++++++++ ...t_content.field_last_updated_by_editor.yml | 24 +++++ ...y_draft_content.field_target_node_path.yml | 24 +++++ ..._draft_content.field_target_node_title.yml | 24 +++++ ...e.message.field_last_updated_by_editor.yml | 21 +++++ ...storage.message.field_target_node_path.yml | 21 +++++ ...ge.template.vba_facility_draft_content.yml | 7 ++ config/sync/mailsystem.settings.yml | 3 + ...ge.template.vba_facility_draft_content.yml | 22 +++++ .../src/JobTypeMessageNotifyBase.php | 29 +++++- .../JobType/WorkflowContentNotification.php | 17 ++++ ...acility-draft-content--mail-body.html.twig | 6 ++ .../va_gov_notifications.module | 4 + .../kernel/JobTypeMessageNotifyBaseTest.php | 22 +++++ 20 files changed, 500 insertions(+), 1 deletion(-) create mode 100644 config/sync/advancedqueue.advancedqueue_queue.content_worfkow.yml create mode 100644 config/sync/core.entity_form_display.message.vba_facility_draft_content.default.yml create mode 100644 config/sync/core.entity_view_display.message.vba_facility_draft_content.default.yml create mode 100644 config/sync/core.entity_view_display.message.vba_facility_draft_content.mail_body.yml create mode 100644 config/sync/core.entity_view_display.message.vba_facility_draft_content.mail_subject.yml create mode 100644 config/sync/eca.eca.workflow_vba_facility_as_draft.yml create mode 100644 config/sync/field.field.message.vba_facility_draft_content.field_last_updated_by_editor.yml create mode 100644 config/sync/field.field.message.vba_facility_draft_content.field_target_node_path.yml create mode 100644 config/sync/field.field.message.vba_facility_draft_content.field_target_node_title.yml create mode 100644 config/sync/field.storage.message.field_last_updated_by_editor.yml create mode 100644 config/sync/field.storage.message.field_target_node_path.yml create mode 100644 config/sync/language/en/message.template.vba_facility_draft_content.yml create mode 100644 config/sync/message.template.vba_facility_draft_content.yml create mode 100644 docroot/modules/custom/va_gov_notifications/src/Plugin/AdvancedQueue/JobType/WorkflowContentNotification.php create mode 100644 docroot/modules/custom/va_gov_notifications/templates/message--vba-facility-draft-content--mail-body.html.twig diff --git a/config/sync/advancedqueue.advancedqueue_queue.content_worfkow.yml b/config/sync/advancedqueue.advancedqueue_queue.content_worfkow.yml new file mode 100644 index 0000000000..57456d71f7 --- /dev/null +++ b/config/sync/advancedqueue.advancedqueue_queue.content_worfkow.yml @@ -0,0 +1,17 @@ +uuid: 60db9e4b-4688-4ec6-ac1d-3038672ec705 +langcode: en +status: true +dependencies: { } +id: content_worfkow +label: 'Content Worfkow' +backend: database +backend_configuration: + lease_time: 30 +processor: cron +processing_time: 10 +locked: false +stop_when_empty: true +threshold: + type: 2 + limit: 30 + state: all diff --git a/config/sync/core.entity_form_display.message.vba_facility_draft_content.default.yml b/config/sync/core.entity_form_display.message.vba_facility_draft_content.default.yml new file mode 100644 index 0000000000..aab5a25682 --- /dev/null +++ b/config/sync/core.entity_form_display.message.vba_facility_draft_content.default.yml @@ -0,0 +1,56 @@ +uuid: df069181-a709-497a-89bf-c20e6c48cc41 +langcode: en +status: true +dependencies: + config: + - field.field.message.vba_facility_draft_content.field_last_updated_by_editor + - field.field.message.vba_facility_draft_content.field_target_node_path + - field.field.message.vba_facility_draft_content.field_target_node_title + - message.template.vba_facility_draft_content +id: message.vba_facility_draft_content.default +targetEntityType: message +bundle: vba_facility_draft_content +mode: default +content: + created: + type: datetime_timestamp + weight: 4 + region: content + settings: { } + third_party_settings: { } + field_last_updated_by_editor: + type: string_textfield + weight: 2 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + field_target_node_path: + type: string_textfield + weight: 1 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + field_target_node_title: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 3 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + '#group': advanced +hidden: { } diff --git a/config/sync/core.entity_view_display.message.vba_facility_draft_content.default.yml b/config/sync/core.entity_view_display.message.vba_facility_draft_content.default.yml new file mode 100644 index 0000000000..4b3d380019 --- /dev/null +++ b/config/sync/core.entity_view_display.message.vba_facility_draft_content.default.yml @@ -0,0 +1,46 @@ +uuid: 792c292e-e566-4fb0-bf70-e4d15b1986ad +langcode: en +status: true +dependencies: + config: + - field.field.message.vba_facility_draft_content.field_last_updated_by_editor + - field.field.message.vba_facility_draft_content.field_target_node_path + - field.field.message.vba_facility_draft_content.field_target_node_title + - message.template.vba_facility_draft_content + module: + - user +id: message.vba_facility_draft_content.default +targetEntityType: message +bundle: vba_facility_draft_content +mode: default +content: + field_last_updated_by_editor: + type: string + label: above + settings: + link_to_entity: false + third_party_settings: { } + weight: 1 + region: content + field_target_node_path: + type: string + label: above + settings: + link_to_entity: false + third_party_settings: { } + weight: 2 + region: content + partial_0: + settings: { } + third_party_settings: { } + weight: 0 + region: content + partial_1: + settings: { } + third_party_settings: { } + weight: 0 + region: content +hidden: + breadcrumbs: true + field_target_node_title: true + search_api_excerpt: true diff --git a/config/sync/core.entity_view_display.message.vba_facility_draft_content.mail_body.yml b/config/sync/core.entity_view_display.message.vba_facility_draft_content.mail_body.yml new file mode 100644 index 0000000000..138f7a30c2 --- /dev/null +++ b/config/sync/core.entity_view_display.message.vba_facility_draft_content.mail_body.yml @@ -0,0 +1,32 @@ +uuid: e03aaafc-ade6-49bc-8616-658b95a38e29 +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.message.mail_body + - field.field.message.vba_facility_draft_content.field_last_updated_by_editor + - field.field.message.vba_facility_draft_content.field_target_node_path + - field.field.message.vba_facility_draft_content.field_target_node_title + - message.template.vba_facility_draft_content + module: + - layout_builder + - user +third_party_settings: + layout_builder: + enabled: false + allow_custom: false +id: message.vba_facility_draft_content.mail_body +targetEntityType: message +bundle: vba_facility_draft_content +mode: mail_body +content: + partial_1: + weight: 0 + region: content +hidden: + breadcrumbs: true + field_last_updated_by_editor: true + field_target_node_path: true + field_target_node_title: true + partial_0: true + search_api_excerpt: true diff --git a/config/sync/core.entity_view_display.message.vba_facility_draft_content.mail_subject.yml b/config/sync/core.entity_view_display.message.vba_facility_draft_content.mail_subject.yml new file mode 100644 index 0000000000..76316220f6 --- /dev/null +++ b/config/sync/core.entity_view_display.message.vba_facility_draft_content.mail_subject.yml @@ -0,0 +1,32 @@ +uuid: 793ef29a-db3e-47f5-8a04-7352558efa93 +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.message.mail_subject + - field.field.message.vba_facility_draft_content.field_last_updated_by_editor + - field.field.message.vba_facility_draft_content.field_target_node_path + - field.field.message.vba_facility_draft_content.field_target_node_title + - message.template.vba_facility_draft_content + module: + - layout_builder + - user +third_party_settings: + layout_builder: + enabled: false + allow_custom: false +id: message.vba_facility_draft_content.mail_subject +targetEntityType: message +bundle: vba_facility_draft_content +mode: mail_subject +content: + partial_0: + weight: 0 + region: content +hidden: + breadcrumbs: true + field_last_updated_by_editor: true + field_target_node_path: true + field_target_node_title: true + partial_1: true + search_api_excerpt: true diff --git a/config/sync/core.extension.yml b/config/sync/core.extension.yml index 3a27a631da..abaf359da4 100644 --- a/config/sync/core.extension.yml +++ b/config/sync/core.extension.yml @@ -64,6 +64,7 @@ module: eca_content: 0 eca_ui: 0 eca_views: 0 + eca_workflow: 0 editor: 0 embed: 0 entity_block: 0 diff --git a/config/sync/eca.eca.workflow_vba_facility_as_draft.yml b/config/sync/eca.eca.workflow_vba_facility_as_draft.yml new file mode 100644 index 0000000000..1a0b786b3a --- /dev/null +++ b/config/sync/eca.eca.workflow_vba_facility_as_draft.yml @@ -0,0 +1,93 @@ +uuid: 57d6c892-1d53-4ebe-ae60-b4dd61d53248 +langcode: en +status: true +dependencies: + config: + - field.field.node.banner.field_last_saved_by_an_editor + - field.field.node.basic_landing_page.field_last_saved_by_an_editor + - field.field.node.campaign_landing_page.field_last_saved_by_an_editor + - field.field.node.centralized_content.field_last_saved_by_an_editor + - field.field.node.checklist.field_last_saved_by_an_editor + - field.field.node.digital_form.field_last_saved_by_an_editor + - field.field.node.documentation_page.field_last_saved_by_an_editor + - field.field.node.event.field_last_saved_by_an_editor + - field.field.node.event_listing.field_last_saved_by_an_editor + - field.field.node.faq_multiple_q_a.field_last_saved_by_an_editor + - field.field.node.full_width_banner_alert.field_last_saved_by_an_editor + - field.field.node.health_care_local_facility.field_last_saved_by_an_editor + - field.field.node.health_care_local_health_service.field_last_saved_by_an_editor + - field.field.node.health_care_region_detail_page.field_last_saved_by_an_editor + - field.field.node.health_care_region_page.field_last_saved_by_an_editor + - field.field.node.health_services_listing.field_last_saved_by_an_editor + - field.field.node.landing_page.field_last_saved_by_an_editor + - field.field.node.leadership_listing.field_last_saved_by_an_editor + - field.field.node.locations_listing.field_last_saved_by_an_editor + - field.field.node.media_list_images.field_last_saved_by_an_editor + - field.field.node.media_list_videos.field_last_saved_by_an_editor + - field.field.node.nca_facility.field_last_saved_by_an_editor + - field.field.node.news_story.field_last_saved_by_an_editor + - field.field.node.office.field_last_saved_by_an_editor + - field.field.node.outreach_asset.field_last_saved_by_an_editor + - field.field.node.page.field_last_saved_by_an_editor + - field.field.node.person_profile.field_last_saved_by_an_editor + - field.field.node.press_release.field_last_saved_by_an_editor + - field.field.node.press_releases_listing.field_last_saved_by_an_editor + - field.field.node.promo_banner.field_last_saved_by_an_editor + - field.field.node.publication_listing.field_last_saved_by_an_editor + - field.field.node.q_a.field_last_saved_by_an_editor + - field.field.node.regional_health_care_service_des.field_last_saved_by_an_editor + - field.field.node.service_region.field_last_saved_by_an_editor + - field.field.node.step_by_step.field_last_saved_by_an_editor + - field.field.node.story_listing.field_last_saved_by_an_editor + - field.field.node.support_resources_detail_page.field_last_saved_by_an_editor + - field.field.node.support_service.field_last_saved_by_an_editor + - field.field.node.va_form.field_last_saved_by_an_editor + - field.field.node.vamc_operating_status_and_alerts.field_last_saved_by_an_editor + - field.field.node.vamc_system_billing_insurance.field_last_saved_by_an_editor + - field.field.node.vamc_system_medical_records_offi.field_last_saved_by_an_editor + - field.field.node.vamc_system_policies_page.field_last_saved_by_an_editor + - field.field.node.vamc_system_register_for_care.field_last_saved_by_an_editor + - field.field.node.vamc_system_va_police.field_last_saved_by_an_editor + - field.field.node.vba_facility.field_last_saved_by_an_editor + - field.field.node.vba_facility_service.field_last_saved_by_an_editor + - field.field.node.vet_center.field_last_saved_by_an_editor + - field.field.node.vet_center_cap.field_last_saved_by_an_editor + - field.field.node.vet_center_facility_health_servi.field_last_saved_by_an_editor + - field.field.node.vet_center_locations_list.field_last_saved_by_an_editor + - field.field.node.vet_center_mobile_vet_center.field_last_saved_by_an_editor + - field.field.node.vet_center_outstation.field_last_saved_by_an_editor + - field.field.node.vha_facility_nonclinical_service.field_last_saved_by_an_editor + - field.storage.node.field_last_saved_by_an_editor + - node.type.vba_facility + module: + - eca_workflow + - va_gov_eca +id: workflow_vba_facility_as_draft +modeller: core +label: 'Workflow: VBA Facility as Draft' +version: null +weight: 0 +events: + workflow_transition: + plugin: 'workflow:transition' + label: 'Workflow: state transition' + configuration: + type: 'node vba_facility' + from_state: '' + to_state: draft + successors: + - + id: create_advancedqueue_job + condition: null +conditions: { } +gateways: { } +actions: + create_advancedqueue_job: + plugin: create_advancedqueue_job + label: 'Create an AdvancedQueue Job and optionally enqueue it.' + configuration: + token_name: job + type: va_gov_workflow_content_notification + payload: "template_values:\r\n uid: \"[entity:revision_uid:target_id]\"\r\n template: vba_facility_draft_content\r\nmail:\r\n - WEBADMIN.VBACO@va.gov\r\nvalues:\r\n field_last_updated_by_editor: \"[entity:field_last_saved_by_an_editor:date:medium]\"\r\n field_target_node_path: \"[entity:url:path]\"\r\n field_target_node_title: \"[entity:title]\"\r\n" + queue: content_worfkow + successors: { } diff --git a/config/sync/field.field.message.vba_facility_draft_content.field_last_updated_by_editor.yml b/config/sync/field.field.message.vba_facility_draft_content.field_last_updated_by_editor.yml new file mode 100644 index 0000000000..b8cacf05e8 --- /dev/null +++ b/config/sync/field.field.message.vba_facility_draft_content.field_last_updated_by_editor.yml @@ -0,0 +1,24 @@ +uuid: 80d16ec2-116b-4dd7-980d-6f8855b963dc +langcode: en +status: true +dependencies: + config: + - field.storage.message.field_last_updated_by_editor + - message.template.vba_facility_draft_content + module: + - tmgmt_content +third_party_settings: + tmgmt_content: + excluded: false +id: message.vba_facility_draft_content.field_last_updated_by_editor +field_name: field_last_updated_by_editor +entity_type: message +bundle: vba_facility_draft_content +label: 'Last Updated By Editor' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/config/sync/field.field.message.vba_facility_draft_content.field_target_node_path.yml b/config/sync/field.field.message.vba_facility_draft_content.field_target_node_path.yml new file mode 100644 index 0000000000..a2e23e1287 --- /dev/null +++ b/config/sync/field.field.message.vba_facility_draft_content.field_target_node_path.yml @@ -0,0 +1,24 @@ +uuid: 6ae7bb2c-7c26-4202-a3ff-7f865bfa496e +langcode: en +status: true +dependencies: + config: + - field.storage.message.field_target_node_path + - message.template.vba_facility_draft_content + module: + - tmgmt_content +third_party_settings: + tmgmt_content: + excluded: false +id: message.vba_facility_draft_content.field_target_node_path +field_name: field_target_node_path +entity_type: message +bundle: vba_facility_draft_content +label: 'Node Path' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/config/sync/field.field.message.vba_facility_draft_content.field_target_node_title.yml b/config/sync/field.field.message.vba_facility_draft_content.field_target_node_title.yml new file mode 100644 index 0000000000..8f3a38aaf6 --- /dev/null +++ b/config/sync/field.field.message.vba_facility_draft_content.field_target_node_title.yml @@ -0,0 +1,24 @@ +uuid: ebd109a5-47a4-4006-97c8-6de23bf7de42 +langcode: en +status: true +dependencies: + config: + - field.storage.message.field_target_node_title + - message.template.vba_facility_draft_content + module: + - tmgmt_content +third_party_settings: + tmgmt_content: + excluded: false +id: message.vba_facility_draft_content.field_target_node_title +field_name: field_target_node_title +entity_type: message +bundle: vba_facility_draft_content +label: 'Target Node Title' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/config/sync/field.storage.message.field_last_updated_by_editor.yml b/config/sync/field.storage.message.field_last_updated_by_editor.yml new file mode 100644 index 0000000000..d96dd307f9 --- /dev/null +++ b/config/sync/field.storage.message.field_last_updated_by_editor.yml @@ -0,0 +1,21 @@ +uuid: d194ed25-ff19-471c-9eb1-46d1e8a35e3e +langcode: en +status: true +dependencies: + module: + - message +id: message.field_last_updated_by_editor +field_name: field_last_updated_by_editor +entity_type: message +type: string +settings: + max_length: 255 + case_sensitive: false + is_ascii: false +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/config/sync/field.storage.message.field_target_node_path.yml b/config/sync/field.storage.message.field_target_node_path.yml new file mode 100644 index 0000000000..3201a90a96 --- /dev/null +++ b/config/sync/field.storage.message.field_target_node_path.yml @@ -0,0 +1,21 @@ +uuid: 014e70a5-fe7f-4b55-a969-e765aebd78cd +langcode: en +status: true +dependencies: + module: + - message +id: message.field_target_node_path +field_name: field_target_node_path +entity_type: message +type: string +settings: + max_length: 255 + case_sensitive: false + is_ascii: false +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/config/sync/language/en/message.template.vba_facility_draft_content.yml b/config/sync/language/en/message.template.vba_facility_draft_content.yml new file mode 100644 index 0000000000..d999e2b348 --- /dev/null +++ b/config/sync/language/en/message.template.vba_facility_draft_content.yml @@ -0,0 +1,7 @@ +text: + - + value: '

Drupal content changes

' + format: rich_text + - + value: '

Changes were made to [message:field_target_node_title] on [message:field_last_updated_by_editor], and saved as draft.
Please review the changes at your earliest convenience.

To approve and publish the draft content,

  1. Scroll down to the Editorial workflow and click to select Save as Published.
  2. Enter "Approved" as a Revision log message.
  3. Click Save.

The content will be queued for release and available on the page following the next successful content deployment.

' + format: rich_text diff --git a/config/sync/mailsystem.settings.yml b/config/sync/mailsystem.settings.yml index 739f584b0e..208c9ef85a 100644 --- a/config/sync/mailsystem.settings.yml +++ b/config/sync/mailsystem.settings.yml @@ -27,3 +27,6 @@ modules: aging_content_warn_news_promo: sender: mime_mail formatter: mime_mail + vba_facility_draft_content: + sender: mime_mail + formatter: mime_mail diff --git a/config/sync/message.template.vba_facility_draft_content.yml b/config/sync/message.template.vba_facility_draft_content.yml new file mode 100644 index 0000000000..bffe491b0b --- /dev/null +++ b/config/sync/message.template.vba_facility_draft_content.yml @@ -0,0 +1,22 @@ +uuid: 57cf55b3-98e2-45cd-8411-cf80b635f06a +langcode: en +status: true +dependencies: + config: + - filter.format.rich_text +template: vba_facility_draft_content +label: 'VBA Facility: Draft Content' +description: 'Email for VBA Facility moving to Draft Workflow State' +text: + - + value: '

Drupal content changes

' + format: rich_text + - + value: '

Changes were made to [message:field_target_node_title] on [message:field_last_updated_by_editor], and saved as draft.
Please review the changes at your earliest convenience.

To approve and publish the draft content,

  1. Scroll down to the Editorial workflow and click to select Save as Published.
  2. Enter "Approved" as a Revision log message.
  3. Click Save.

The content will be queued for release and available on the page following the next successful content deployment.

If you need to reject the changes,

  1. Scroll down to the Editorial workflow and click to select Save as In review.
  2. Enter an explanation for the rejection into the Revision log message field.
  3. Click Save.
' + format: rich_text +settings: + 'token options': + clear: false + 'token replace': true + purge_override: false + purge_methods: { } diff --git a/docroot/modules/custom/va_gov_notifications/src/JobTypeMessageNotifyBase.php b/docroot/modules/custom/va_gov_notifications/src/JobTypeMessageNotifyBase.php index de7623f3ec..5fdde4dc1f 100644 --- a/docroot/modules/custom/va_gov_notifications/src/JobTypeMessageNotifyBase.php +++ b/docroot/modules/custom/va_gov_notifications/src/JobTypeMessageNotifyBase.php @@ -86,7 +86,7 @@ public function process(Job $job): JobResult { if (!$this->allowedToSend($message, $this->job->getPayload())) { return JobResult::failure($this->getRestrictedRecipientMessage($job, $message), 0); } - $status = $this->messageNotifier->send($message); + $status = $this->messageNotifier->send($message, $this->getMessageNotifierOptions($message)); if (!$status) { $error_message = $this->getErrorMessage($job, $message); $this->logger->error($error_message); @@ -186,4 +186,31 @@ public function allowedToSend(Message $message, array $payload): bool { return TRUE; } + /** + * Gets options for the Message Notifier plugin. + * + * Initially used to set a specific mail recipient address, rather than use + * the Message owner as the recipient. + * + * @param \Drupal\message\Entity\Message $message + * The Message prior to being sent via Message Notify. + * + * @return array + * The message options to pass to Message Notify. + */ + protected function getMessageNotifierOptions(Message $message): array { + $messageOptions = []; + $payload = $this->job->getPayload(); + // Determine if the job has a specified 'mail' address. If so, set the + // 'mail' configuration option, which will become the recipient(s) when + // processed by the Email Message Notifier. + if (!empty($payload['mail'])) { + // If there are multiple recipients, implode them into a single comma + // separated string. + $recipients = is_array($payload['mail']) ? implode(',', $payload['mail']) : $payload['mail']; + $messageOptions['mail'] = $recipients; + } + return $messageOptions; + } + } diff --git a/docroot/modules/custom/va_gov_notifications/src/Plugin/AdvancedQueue/JobType/WorkflowContentNotification.php b/docroot/modules/custom/va_gov_notifications/src/Plugin/AdvancedQueue/JobType/WorkflowContentNotification.php new file mode 100644 index 0000000000..b13ec2e45a --- /dev/null +++ b/docroot/modules/custom/va_gov_notifications/src/Plugin/AdvancedQueue/JobType/WorkflowContentNotification.php @@ -0,0 +1,17 @@ + +
+ VA logo and seal, U.S. Department of Veterans Affairs +
+ {{ content }} +
diff --git a/docroot/modules/custom/va_gov_notifications/va_gov_notifications.module b/docroot/modules/custom/va_gov_notifications/va_gov_notifications.module index 0e976bf13e..22141cc96c 100644 --- a/docroot/modules/custom/va_gov_notifications/va_gov_notifications.module +++ b/docroot/modules/custom/va_gov_notifications/va_gov_notifications.module @@ -31,6 +31,9 @@ function va_gov_notifications_theme() { 'message__aging_content_warn_news_promo__mail_body' => [ 'base hook' => 'message', ], + 'message__vba_facility_draft_content__mail_body' => [ + 'base hook' => 'message', + ], ]; } @@ -45,6 +48,7 @@ function va_gov_notifications_mail_alter(&$message) { 'aging_content_warn_fwb', 'aging_content_warn_news_promo', 'aging_content_expired_news_promo', + 'vba_facility_draft_content', ]; if (in_array($message['key'], $types) && !empty($message['params']['message_entity'])) { $message['headers']['Content-Type'] = 'multipart/related; charset=UTF-8; format=flowed; delsp=yes'; diff --git a/tests/phpunit/va_gov_notifications/kernel/JobTypeMessageNotifyBaseTest.php b/tests/phpunit/va_gov_notifications/kernel/JobTypeMessageNotifyBaseTest.php index 2266d4adc2..12d1ebf4e0 100644 --- a/tests/phpunit/va_gov_notifications/kernel/JobTypeMessageNotifyBaseTest.php +++ b/tests/phpunit/va_gov_notifications/kernel/JobTypeMessageNotifyBaseTest.php @@ -180,4 +180,26 @@ public function testProcessFailureMissingTemplateValues() { $this->assertEquals(Job::STATE_FAILURE, $result->getState()); } + /** + * Tests the process with Message Notifier Options and no Message owner. + */ + public function testProcessMessageNotifierOptionsNoOwner() { + $payload = [ + 'values' => [], + 'mail' => 'test@example.com', + 'template_values' => [ + 'template' => 'foo_template', + 'uid' => 1, + ], + ]; + $job = new Job([ + 'type' => 'test_job_type', + 'payload' => $payload, + 'state' => Job::STATE_QUEUED, + ]); + $result = $this->jobType->process($job); + $this->assertEquals(Job::STATE_SUCCESS, $result->getState()); + $this->assertEquals('Message 1 sent successfully.', $result->getMessage()); + } + } From e896d493c2fd4c7d0afa2baf8fb0ad7af437cc5a Mon Sep 17 00:00:00 2001 From: Daniel Sasser <221539+dsasser@users.noreply.github.com> Date: Mon, 6 Jan 2025 11:30:44 -0800 Subject: [PATCH 5/8] VACMS-19060: Ensure job is exported as an associative array to allow for proper tokenization of the DTO. (#20200) --- .../va_gov_eca/src/Plugin/Action/CreateAdvancedQueueJob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docroot/modules/custom/va_gov_eca/src/Plugin/Action/CreateAdvancedQueueJob.php b/docroot/modules/custom/va_gov_eca/src/Plugin/Action/CreateAdvancedQueueJob.php index 63a743943d..a1b6ccd683 100644 --- a/docroot/modules/custom/va_gov_eca/src/Plugin/Action/CreateAdvancedQueueJob.php +++ b/docroot/modules/custom/va_gov_eca/src/Plugin/Action/CreateAdvancedQueueJob.php @@ -78,7 +78,7 @@ public function execute() { if ($this->configuration['queue']) { Queue::load($this->configuration['queue'])?->enqueueJob($job); } - $this->tokenService->addTokenData($this->configuration['token_name'], DataTransferObject::create([$job])); + $this->tokenService->addTokenData($this->configuration['token_name'], DataTransferObject::create($job->toArray())); } /** From 7085339be365c33127c128f79bb1d0bbdebfb611 Mon Sep 17 00:00:00 2001 From: Ryan Koch <6863534+ryguyk@users.noreply.github.com> Date: Mon, 6 Jan 2025 15:45:50 -0600 Subject: [PATCH 6/8] VAGOV-TEAM-97922: Adds sidebar placeholder (#20155) * VAGOV-TEAM-97922: Adds sidebar placeholder to Form Builder pages. * Adds min-width to left column. --- .../css/va_gov_form_builder.css | 29 ++++++++++++++++++- .../page--va-gov-form-builder.html.twig | 23 ++++++++++----- .../templates/FormBuilderPageTemplateTest.php | 3 ++ 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/docroot/modules/custom/va_gov_form_builder/css/va_gov_form_builder.css b/docroot/modules/custom/va_gov_form_builder/css/va_gov_form_builder.css index 80bc63ece9..8c0aebdbc3 100644 --- a/docroot/modules/custom/va_gov_form_builder/css/va_gov_form_builder.css +++ b/docroot/modules/custom/va_gov_form_builder/css/va_gov_form_builder.css @@ -1,5 +1,8 @@ /* page container */ .form-builder-page-container { + --vads-color-divider: #a9aeb1; + --color-shadow: #00000040; + font-family: var(--font-family-serif); } @@ -42,7 +45,7 @@ /* layout container */ .form-builder-layout-container { - margin: 0 var(--units-7); + margin: var(--units-2p5) var(--units-7); } /* title */ @@ -90,3 +93,27 @@ .form-builder-navbar__tab--active .form-builder-navbar__link:hover { color: var(--uswds-system-color-gold-vivid-20); } + +/* two-column layout */ +.form-builder-two-column-layout { + display: flex; + gap: var(--units-5); + justify-content: space-between; + width: 100%; +} + +.form-builder-left-column { + min-width: 900px; +} + +.form-builder-right-column { + padding-top: var(--units-2); +} + +/* sidebar */ +.form-builder-sidebar { + border: 1px solid var(--vads-color-divider); + box-shadow: 0 4px 4px 0 var(--color-shadow); + padding: var(--units-2p5); + width: 340px; +} diff --git a/docroot/modules/custom/va_gov_form_builder/templates/page--va-gov-form-builder.html.twig b/docroot/modules/custom/va_gov_form_builder/templates/page--va-gov-form-builder.html.twig index 0bc5004f56..221ac167e2 100644 --- a/docroot/modules/custom/va_gov_form_builder/templates/page--va-gov-form-builder.html.twig +++ b/docroot/modules/custom/va_gov_form_builder/templates/page--va-gov-form-builder.html.twig @@ -57,12 +57,21 @@
-
-
- - {# The form content #} - {{ page.content }} - -
+
+
+
+
+ +
+ {{ page.content }} +
+
+
+ +
+
+
diff --git a/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php b/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php index 34f201df60..79513d5432 100644 --- a/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php +++ b/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php @@ -51,6 +51,9 @@ public function testExpectedElementsExist() { $navbarElement = $this->cssSelect('.form-builder-navbar'); $this->assertCount(1, $navbarElement); + + $sidebarElement = $this->cssSelect('.form-builder-sidebar'); + $this->assertCount(1, $sidebarElement); } /** From a0a78c9d25786876cebe2c876283f0ea6091d9a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 17:36:31 -0800 Subject: [PATCH 7/8] Bump va-gov/content-build from 0.0.3656 to 0.0.3657 (#20217) Bumps [va-gov/content-build](https://github.com/department-of-veterans-affairs/content-build) from 0.0.3656 to 0.0.3657. - [Release notes](https://github.com/department-of-veterans-affairs/content-build/releases) - [Commits](https://github.com/department-of-veterans-affairs/content-build/compare/v0.0.3656...v0.0.3657) --- updated-dependencies: - dependency-name: va-gov/content-build dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index b9730884b5..2f41f0282b 100644 --- a/composer.json +++ b/composer.json @@ -228,7 +228,7 @@ "symfony/phpunit-bridge": "^7.1", "symfony/process": "^6.3", "symfony/routing": "^6.3", - "va-gov/content-build": "^0.0.3656", + "va-gov/content-build": "^0.0.3657", "vlucas/phpdotenv": "^5.6", "webflo/drupal-finder": "1.3.1", "webmozart/path-util": "^2.3", diff --git a/composer.lock b/composer.lock index e1274e83ef..c193a2f595 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "031fbf075a33d00a7864f01e99cd4109", + "content-hash": "2e9a7625d24f80f308e27764fed4b72b", "packages": [ { "name": "asm89/stack-cors", @@ -26902,16 +26902,16 @@ }, { "name": "va-gov/content-build", - "version": "v0.0.3656", + "version": "v0.0.3657", "source": { "type": "git", "url": "https://github.com/department-of-veterans-affairs/content-build.git", - "reference": "46750775cf7b6d8c871753fc531dbad197230e4a" + "reference": "9ee617439ad36ed873ce42d2076a39523b2bc6ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/department-of-veterans-affairs/content-build/zipball/46750775cf7b6d8c871753fc531dbad197230e4a", - "reference": "46750775cf7b6d8c871753fc531dbad197230e4a", + "url": "https://api.github.com/repos/department-of-veterans-affairs/content-build/zipball/9ee617439ad36ed873ce42d2076a39523b2bc6ae", + "reference": "9ee617439ad36ed873ce42d2076a39523b2bc6ae", "shasum": "" }, "type": "node-project", @@ -26938,9 +26938,9 @@ "description": "Front-end for VA.gov. This repository contains the code that generates the www.va.gov website. It contains a Metalsmith static site builder that uses a Drupal CMS for content. This file is here to publish releases to https://packagist.org/packages/va-gov/content-build, so that the CMS CI system can install it and update it using standard composer processes, and so that we can run tests across both systems. See https://github.com/department-of-veterans-affairs/va.gov-cms for the CMS repo, and stand by for more documentation.", "support": { "issues": "https://github.com/department-of-veterans-affairs/content-build/issues", - "source": "https://github.com/department-of-veterans-affairs/content-build/tree/v0.0.3656" + "source": "https://github.com/department-of-veterans-affairs/content-build/tree/v0.0.3657" }, - "time": "2025-01-02T23:33:14+00:00" + "time": "2025-01-06T13:35:03+00:00" }, { "name": "vlucas/phpdotenv", From 0993b3559f25b668810346dfe8bb018e09cf8ae5 Mon Sep 17 00:00:00 2001 From: Ryan Koch <6863534+ryguyk@users.noreply.github.com> Date: Tue, 7 Jan 2025 09:57:14 -0600 Subject: [PATCH 8/8] VAGAOV-TEAM-97941: Adds Form Builder role and permission (#20192) * Changes module name to include VA.gov prefix. * Adds `access form builder` permission. * Adds `Form Builder user` (form_builder_user) role with `access form builder` permission. * Adds unit test for permissions.yml * Updates annotation on existing test to be more accurate. * Updates routing: - Use RouteSubscriber rather than repeating same permission on every route. - Update to use new permission. * Updates existing tests to align with new permission. Note that these existing tests effectively test the RouteSubscriber functionality. * Small fix to `hasRequirement` check. Cannot take a specific permission as a second parameter. We'll set the permission whenever one is not set. --- config/sync/user.role.form_builder_user.yml | 16 +++++ .../src/Routing/RouteSubscriber.php | 26 +++++++ .../va_gov_form_builder.info.yml | 2 +- .../va_gov_form_builder.permissions.yml | 4 ++ .../va_gov_form_builder.routing.yml | 8 --- .../va_gov_form_builder.services.yml | 5 ++ .../Traits/TestFormLoads.php | 6 +- .../functional/Form/IntroTest.php | 22 +++--- .../functional/Form/NameAndDobTest.php | 2 +- .../functional/Form/StartConversionTest.php | 2 +- .../templates/FormBuilderPageTemplateTest.php | 2 +- .../unit/LibrariesTest.php | 4 +- .../unit/PermissionsTest.php | 68 +++++++++++++++++++ 13 files changed, 141 insertions(+), 26 deletions(-) create mode 100644 config/sync/user.role.form_builder_user.yml create mode 100644 docroot/modules/custom/va_gov_form_builder/src/Routing/RouteSubscriber.php create mode 100644 docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.permissions.yml create mode 100644 docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.services.yml create mode 100644 tests/phpunit/va_gov_form_builder/unit/PermissionsTest.php diff --git a/config/sync/user.role.form_builder_user.yml b/config/sync/user.role.form_builder_user.yml new file mode 100644 index 0000000000..1b5dff7c74 --- /dev/null +++ b/config/sync/user.role.form_builder_user.yml @@ -0,0 +1,16 @@ +uuid: 2793e5e4-37aa-49b3-9c29-5e1c7ddc3772 +langcode: en +status: true +dependencies: + module: + - va_gov_backend + - va_gov_form_builder +third_party_settings: + va_gov_backend: + vgb_description: "A user of the VA.gov Form Builder tool." +id: form_builder_user +label: "Form Builder user" +weight: 14 +is_admin: null +permissions: + - "access form builder" diff --git a/docroot/modules/custom/va_gov_form_builder/src/Routing/RouteSubscriber.php b/docroot/modules/custom/va_gov_form_builder/src/Routing/RouteSubscriber.php new file mode 100644 index 0000000000..c7876c5878 --- /dev/null +++ b/docroot/modules/custom/va_gov_form_builder/src/Routing/RouteSubscriber.php @@ -0,0 +1,26 @@ +all() as $route_name => $route) { + if (strpos($route_name, 'va_gov_form_builder.') === 0) { + if (!$route->hasRequirement('_permission')) { + $route->setRequirement('_permission', 'access form builder'); + } + } + } + } + +} diff --git a/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.info.yml b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.info.yml index bc3406b916..d3a96562c6 100644 --- a/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.info.yml +++ b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.info.yml @@ -1,4 +1,4 @@ -name: "Form Builder" +name: "VA.gov Form Builder" type: module description: "A module that builds a custom experience for creating and editing Digital Form nodes." core_version_requirement: ^9 || ^10 diff --git a/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.permissions.yml b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.permissions.yml new file mode 100644 index 0000000000..85f3d3db04 --- /dev/null +++ b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.permissions.yml @@ -0,0 +1,4 @@ +access form builder: + title: "Access Form Builder" + description: "Allows the user to access the VA.gov Form Builder tool." + restrict access: FALSE diff --git a/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.routing.yml b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.routing.yml index 346b614ba0..52a9145505 100644 --- a/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.routing.yml +++ b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.routing.yml @@ -2,23 +2,15 @@ va_gov_form_builder.entry: path: "/form-builder" defaults: _controller: '\Drupal\va_gov_form_builder\Controller\VaGovFormBuilderController::entry' - requirements: - _permission: "edit any digital_form content" va_gov_form_builder.intro: path: "/form-builder/intro" defaults: _controller: '\Drupal\va_gov_form_builder\Controller\VaGovFormBuilderController::intro' - requirements: - _permission: "edit any digital_form content" va_gov_form_builder.start_conversion: path: "/form-builder/start-conversion" defaults: _controller: '\Drupal\va_gov_form_builder\Controller\VaGovFormBuilderController::startConversion' - requirements: - _permission: "edit any digital_form content" va_gov_form_builder.name_and_dob: path: "/form-builder/{nid}/name-and-dob" defaults: _controller: '\Drupal\va_gov_form_builder\Controller\VaGovFormBuilderController::nameAndDob' - requirements: - _permission: "edit any digital_form content" diff --git a/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.services.yml b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.services.yml new file mode 100644 index 0000000000..b6af461fe8 --- /dev/null +++ b/docroot/modules/custom/va_gov_form_builder/va_gov_form_builder.services.yml @@ -0,0 +1,5 @@ +services: + va_gov_form_builder.route_subscriber: + class: Drupal\va_gov_form_builder\Routing\RouteSubscriber + tags: + - { name: "event_subscriber" } diff --git a/tests/phpunit/va_gov_form_builder/Traits/TestFormLoads.php b/tests/phpunit/va_gov_form_builder/Traits/TestFormLoads.php index 39b7ca00fd..506f523ad3 100644 --- a/tests/phpunit/va_gov_form_builder/Traits/TestFormLoads.php +++ b/tests/phpunit/va_gov_form_builder/Traits/TestFormLoads.php @@ -10,9 +10,9 @@ trait TestFormLoads { /** * Logs-in a user with appropriate privileges. */ - private function loginDigitalFormUser() { + private function loginFormBuilderUser() { $this->drupalLogin($this->createUser([ - 'edit any digital_form content', + 'access form builder', ])); } @@ -26,7 +26,7 @@ private function loginDigitalFormUser() { */ private function sharedTestFormLoads($url, $expectedText) { // Log in a user with permission. - $this->loginDigitalFormUser(); + $this->loginFormBuilderUser(); // Navigate to page. $this->drupalGet($url); diff --git a/tests/phpunit/va_gov_form_builder/functional/Form/IntroTest.php b/tests/phpunit/va_gov_form_builder/functional/Form/IntroTest.php index 80d6905791..955211e368 100644 --- a/tests/phpunit/va_gov_form_builder/functional/Form/IntroTest.php +++ b/tests/phpunit/va_gov_form_builder/functional/Form/IntroTest.php @@ -2,6 +2,7 @@ namespace tests\phpunit\va_gov_form_builder\functional\Form; +use tests\phpunit\va_gov_form_builder\Traits\TestFormLoads; use Tests\Support\Classes\VaGovExistingSiteBase; /** @@ -13,39 +14,42 @@ * @coversDefaultClass \Drupal\va_gov_form_builder\Form\Intro */ class IntroTest extends VaGovExistingSiteBase { + use TestFormLoads; /** * {@inheritdoc} */ private static $modules = ['va_gov_form_builder']; + /** + * Returns the url for this form (for the given node) + */ + private function getFormPageUrl() { + return '/form-builder/intro'; + } + /** * Set up the environment for each test. */ public function setUp(): void { parent::setUp(); - $this->drupalLogin($this->createUser(['edit any digital_form content'])); - $this->drupalGet('/form-builder/intro'); + $this->loginFormBuilderUser(); + $this->drupalGet($this->getFormPageUrl()); } /** * Test that the form is accessible to a user with the correct privilege. */ public function testFormLoads() { - $this->assertSession()->statusCodeEquals(200); - $this->assertSession()->pageTextContains('Working with the Form Builder'); + $this->sharedTestFormLoads($this->getFormPageUrl(), 'Working with the Form Builder'); } /** * Test that the form is not accessible to a user without privilege. */ public function testFormDoesNotLoad() { - // Log out the good user and log in a user without permission. - $this->drupalLogin($this->createUser([])); - $this->drupalGet('/form-builder/intro'); - - $this->assertSession()->statusCodeNotEquals(200); + $this->sharedTestFormDoesNotLoad($this->getFormPageUrl()); } /** diff --git a/tests/phpunit/va_gov_form_builder/functional/Form/NameAndDobTest.php b/tests/phpunit/va_gov_form_builder/functional/Form/NameAndDobTest.php index 98a963b380..f12f632c1f 100644 --- a/tests/phpunit/va_gov_form_builder/functional/Form/NameAndDobTest.php +++ b/tests/phpunit/va_gov_form_builder/functional/Form/NameAndDobTest.php @@ -53,7 +53,7 @@ private function reloadNode() { public function setUp(): void { parent::setUp(); - $this->loginDigitalFormUser(); + $this->loginFormBuilderUser(); // Create a node that doesn't have any chapters. $this->node = $this->createNode([ diff --git a/tests/phpunit/va_gov_form_builder/functional/Form/StartConversionTest.php b/tests/phpunit/va_gov_form_builder/functional/Form/StartConversionTest.php index cdb1aeae36..53de9e642a 100644 --- a/tests/phpunit/va_gov_form_builder/functional/Form/StartConversionTest.php +++ b/tests/phpunit/va_gov_form_builder/functional/Form/StartConversionTest.php @@ -37,7 +37,7 @@ private function getFormPageUrl() { public function setUp(): void { parent::setUp(); - $this->loginDigitalFormUser(); + $this->loginFormBuilderUser(); $this->drupalGet($this->getFormPageUrl()); } diff --git a/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php b/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php index 79513d5432..4865211feb 100644 --- a/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php +++ b/tests/phpunit/va_gov_form_builder/functional/templates/FormBuilderPageTemplateTest.php @@ -34,7 +34,7 @@ class FormBuilderPageTemplateTest extends VaGovExistingSiteBase { public function setUp(): void { parent::setUp(); - $this->drupalLogin($this->createUser(['edit any digital_form content'])); + $this->drupalLogin($this->createUser(['access form builder'])); // Form Builder entry. $this->drupalGet('/form-builder'); diff --git a/tests/phpunit/va_gov_form_builder/unit/LibrariesTest.php b/tests/phpunit/va_gov_form_builder/unit/LibrariesTest.php index d306020496..9e08fc2242 100644 --- a/tests/phpunit/va_gov_form_builder/unit/LibrariesTest.php +++ b/tests/phpunit/va_gov_form_builder/unit/LibrariesTest.php @@ -24,13 +24,13 @@ class LibrariesTest extends VaGovUnitTestBase { /** * The libraries defined in libraries.yml. * - * @var array{ + * @var array * }, * js?: array, * dependencies?: array - * } + * }> */ private $libraries; diff --git a/tests/phpunit/va_gov_form_builder/unit/PermissionsTest.php b/tests/phpunit/va_gov_form_builder/unit/PermissionsTest.php new file mode 100644 index 0000000000..d887e24169 --- /dev/null +++ b/tests/phpunit/va_gov_form_builder/unit/PermissionsTest.php @@ -0,0 +1,68 @@ + + */ + private $permissions; + + /** + * Set up the environment for each test. + */ + protected function setUp(): void { + parent::setUp(); + + // Find Drupal root. + $drupalFinder = new DrupalFinder(); + $drupalFinder->locateRoot(__DIR__); + $drupalRoot = $drupalFinder->getDrupalRoot(); + + $yamlFile = $drupalRoot . '/' . $this->modulePath . '/va_gov_form_builder.permissions.yml'; + + $this->permissions = Yaml::parseFile($yamlFile); + } + + /** + * Tests that the `access form builder` permission is present. + */ + public function testPermissionPresent() { + $this->assertArrayHasKey('access form builder', $this->permissions); + + // Assert expected keys are present. + $formBuilderPermission = $this->permissions['access form builder']; + $this->assertArrayHasKey('title', $formBuilderPermission); + $this->assertArrayHasKey('description', $formBuilderPermission); + $this->assertArrayHasKey('restrict access', $formBuilderPermission); + + // Assert `restrict access` is false. + $restrictAccess = $formBuilderPermission['restrict access']; + $this->assertFalse($restrictAccess); + } + +}