VACMS 21049 - wires up the VET_CENTER_OUTSTATION feature to work with correct real data - #1886
VACMS 21049 - wires up the VET_CENTER_OUTSTATION feature to work with correct real data#1886eselkin wants to merge 8 commits into
Conversation
Wires the Vet Center Outstation detail page to the CMS by switching the data loader from RESOURCE_TYPES.VET_CENTER to VET_CENTER_OUTSTATION, adding the route in [...slug].tsx, and extending NodeVetCenterOutstation with the centralized-content fields the existing formatter already reads. Adds null safety to buildFeaturedContentArray, buildFaqs, and a new buildCCWysiwyg helper so missing CC fields no longer crash the formatter on real CMS responses where editors haven't filled everything in. Outstation titles in the Vet Center location listing now link to the detail page via a new isVetCenterOutstation type guard. Adapted from the closed PR #1572. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…test that they work and also checked field_intro_text
| // Outstation title is rendered inside a va-link's `text` attribute | ||
| const titleLinkElement = document.querySelector( | ||
| 'va-link[text="Helena Vet Center Outstation"]' | ||
| ) | ||
| expect(titleLinkElement).toBeInTheDocument() | ||
|
|
||
| // Check for outstation address | ||
| expect(screen.getByText(/9737 Haskell Ave/)).toBeInTheDocument() | ||
| expect(screen.getByText(/1301 Elm Street/)).toBeInTheDocument() |
There was a problem hiding this comment.
Pull request overview
This PR wires up the VET_CENTER_OUTSTATION resource type so outstation pages can be fetched, formatted, and rendered with real Drupal data (including mission explainer content, banner images, and correct linking back to the parent Vet Center locations page).
Changes:
- Adds Outstation routing/rendering to the catch-all resource page and enables the feature flag in test/tugboat envs.
- Expands Drupal and formatted types + updates the outstation query/template to support mission explainer, banner image, and parent-path linking.
- Updates mocks/snapshots and adds/adjusts tests for outstation rendering and location listing behavior.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/types/drupal/node.ts | Extends the Drupal outstation node type to include additional (nullable) fields pulled from real data. |
| src/pages/[...slug].tsx | Adds rendering support for VET_CENTER_OUTSTATION resources. |
| src/components/vetCenterOutstation/template.tsx | Updates the outstation page template (mission explainer, banner image, footer, parent locations link). |
| src/components/vetCenterOutstation/template.test.tsx | Adds tests for mission explainer, banner image, FAQ body, and parentPath link behavior. |
| src/components/vetCenterOutstation/query.ts | Updates the outstation data loader/formatter to fetch/format new fields and banner media. |
| src/components/vetCenterOutstation/query.test.ts | Updates query tests to match the new loader shape and includes list. |
| src/components/vetCenterOutstation/mock.ts | Updates template mock data with mission explainer and parentPath fields. |
| src/components/vetCenterOutstation/mock.json | Updates the raw Drupal JSON fixture to a real (published) outstation with richer centralized content fields. |
| src/components/vetCenterOutstation/mock.formatted.ts | Updates formatted mock data shape to include new fields. |
| src/components/vetCenterOutstation/formatted-type.ts | Extends the formatted outstation type with missionExplainer, bannerImage, and parentPath. |
| src/components/vetCenterOutstation/snapshots/query.test.ts.snap | Updates snapshots for the new formatted output shape. |
| src/components/vetCenterLocationListing/VetCenterLocationInfo.tsx | Treats outstations like main offices for title-link rendering on the locations list. |
| src/components/vetCenterLocationListing/template.test.tsx | Updates assertions to verify outstation titles render within va-link and address text matches updated fixture data. |
| src/components/paragraph/ParagraphList.test.tsx | Updates a test paragraph ID in an existing ParagraphList test. |
| envs/.env.tugboat | Enables the Outstation feature flag in tugboat environment config. |
| envs/.env.test | Enables the Outstation feature flag in test environment config. |
| .qa-data/node--vet_center_outstation.json | Adds QA tool paths for outstation pages. |
| .qa-data/node--vet_center_locations_list.json | Adds/updates QA tool paths for vet center locations list pages. |
Comments suppressed due to low confidence (1)
src/components/vetCenterOutstation/query.ts:93
field_health_servicesis now nullable/optional onNodeVetCenterOutstation, but this formatter passes it directly intoqueries.formatData(RESOURCE_TYPES.VET_CENTER_HEALTH_SERVICES, ...). The health services formatter assumes an array and will throw onnull/undefined. Default to an empty array before formatting (e.g.,entity.field_health_services ?? []).
// format health services / filter per category
const healthServicesArray = queries.formatData(
RESOURCE_TYPES.VET_CENTER_HEALTH_SERVICES,
entity.field_health_services
)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const buildCCWysiwyg = (ccField, entityId: string): Wysiwyg | null => { | ||
| if (!ccField?.fetched?.field_wysiwyg?.[0]?.processed) return null | ||
| return { | ||
| type: PARAGRAPH_RESOURCE_TYPES.QA_SECTION as FormattedQaSection['type'], | ||
| id: faqs.target_id, | ||
| header: faqs.fetched.field_section_header[0]?.value || null, | ||
| intro: faqs.fetched.field_section_intro[0]?.value || null, | ||
| displayAccordion: | ||
| Boolean(faqs.fetched.field_accordion_display[0]?.value) || false, | ||
| questions: buildQuestionArray(faqs.fetched.field_questions), | ||
| type: PARAGRAPH_RESOURCE_TYPES.WYSIWYG as Wysiwyg['type'], | ||
| id: entityId, | ||
| html: ccField.fetched.field_wysiwyg[0].processed, | ||
| } |
| export type VetCenterOutstation = PublishedEntity & { | ||
| address: FieldAddress | ||
| ccNonTraditionalHours: FormattedWysiwyg | ||
| ccVetCenterCallCenter: FormattedWysiwyg | ||
| ccVetCenterFaqs: PublishedQaSection | ||
| geolocation: FieldGeoLocation | ||
| introText: string | ||
| missionExplainer: { |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…e HTML fetching in formatter
|
Tugboats weren't building unless rebuilt for some reason... Example page: |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 18 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/components/vetCenterOutstation/query.ts:94
NodeVetCenterOutstation.field_health_servicesis now optional/nullable, butqueries.formatData(RESOURCE_TYPES.VET_CENTER_HEALTH_SERVICES, entity.field_health_services)will throw if the value isnull/undefined(the VetCenterHealthServices formatter calls.map). Default this to an empty array (e.g.,entity.field_health_services ?? []) before formatting to avoid runtime crashes when the field is missing.
// format health services / filter per category
const healthServicesArray = queries.formatData(
RESOURCE_TYPES.VET_CENTER_HEALTH_SERVICES,
entity.field_health_services
)
pwolfert
left a comment
There was a problem hiding this comment.
Everything else is looking good. One comment below
|
Tugboat has finished building the preview for this pull request! Link: Link (redis): Dashboard: |
… correct real data (#1886) * [VACMS-21049] connect Vet Center Outstation pages to CMS Wires the Vet Center Outstation detail page to the CMS by switching the data loader from RESOURCE_TYPES.VET_CENTER to VET_CENTER_OUTSTATION, adding the route in [...slug].tsx, and extending NodeVetCenterOutstation with the centralized-content fields the existing formatter already reads. Adds null safety to buildFeaturedContentArray, buildFaqs, and a new buildCCWysiwyg helper so missing CC fields no longer crash the formatter on real CMS responses where editors haven't filled everything in. Outstation titles in the Vet Center location listing now link to the detail page via a new isVetCenterOutstation type guard. Adapted from the closed PR #1572. * Add in the optional (feature flagged) mission explainer and image to test that they work and also checked field_intro_text * qa data * Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix: update VetCenterOutstation types to allow null values and improve HTML fetching in formatter * fix: streamline banner media fetching logic in VetCenterOutstation query * returning h2 to VADS defaults --------- Co-authored-by: Eli Selkin <5606931+eselkin@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Description
What does this PR address?
Wires up and fixes the Vet Center Outstation data (with or without the drupal feature toggle
feature_vet_center_outstation_enhancementson. Fixes the template and mocks to draw from real data.This pull request introduces support for Vet Center Outstation locations throughout the application, including feature flag updates, type and component logic, and test data improvements. The changes ensure that Outstation locations are properly recognized, displayed, and formatted, and that the data structures and tests reflect the new requirements.
Feature enablement:
FEATURE_NEXT_BUILD_CONTENT_VET_CENTER_OUTSTATIONfeature flag to both.env.testand.env.tugboatto enable Outstation-related functionality in relevant environments. [1] [2]Component and logic updates:
isVetCenterOutstationtype guard function and updatedVetCenterLocationInfoso Outstation locations are treated similarly to main offices, displaying their titles as links. [1] [2]VetCenterOutstationtype to include a new optionalmissionExplainerfield for additional explanatory content.Test and mock data improvements:
VetCenterOutstationto include new fields (bannerImage,missionExplainer,parentPath) and improved formatting for Q&A sections, ensuring test coverage for the new data structure and display logic. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]VetCenterLocationListingto check that Outstation titles are rendered insideva-linkcomponents and that the correct address is displayed.ParagraphListcomponent tests to update a paragraph ID.Ticket
Closes department-of-veterans-affairs/va.gov-cms#21049
Developer Task
Testing Steps
/colorado-springs-vet-center/locationssee that no changes between tugboat and staging/prod/anoka-vet-center/locationssee that tugboat has linked title for outstation/anoka-vet-center/st-cloud-vet-center-outstation)/great-falls-vet-center/helena-outstationfrom Canvas, check that it meets requirements of Figma without the intro_text (since that's not filled in for any of the outstations - but it does work - see the screenshot or edit a node on the tugboat CMS and check)QA steps
What needs to be checked to prove this works?
What needs to be checked to prove it didn't break any related things?
What variations of circumstances (users, actions, values) need to be checked?
Screenshots
Before: No page
After:
Reviewer
Reviewing a PR
This section lists items that need to be checked or updated when making changes to this repository.
Standard Checks
Merging a Layout
When merging a layout, you must ensure that the content type has been turned on for
next-buildin the .tugboat.env. This method mocks the CMS flag that must be turned on for a layout to be included in the build.The layout component and matching resource type should be included in the slug.tsx, so that it can reviewed. Including a component in the slug.tsx does not mean a page will be viewable in production only on the tugboat for the branch.
When a layout is merged to main and approved for deployment, the prod CMS will turn the toggle on for the resource type.
The status of layouts should be kept up to date inside templates.md. This includes QA progress, development progress, etc. A link should be provided for where testing can occur.