profile
viewpoint

bkjohnson/biobots-challenge 1

Simple web app for the biobots challenge

bkjohnson/roguelike-tutorial 1

Follow the progress here: https://github.com/bkjohnson/roguelike-tutorial/wiki

bkjohnson/bbcwx 0

A Cinnamon desklet displaying weather from a variety of sources

bkjohnson/Boostnote 0

Boostnote, the opensource note app for developer.

bkjohnson/brave-website 0

Our amazing web presence.

bkjohnson/Bullet 0

Shiny app that creates a bullet graph from a CSV

bkjohnson/cypress 0

Fast, easy and reliable testing for anything that runs in a browser.

Pull request review commentdepartment-of-veterans-affairs/vets-website

Add more information in order to debug unit test failures

+const printUnitTestHelp = require('./run-unit-test-help.js');+const commandLineArgs = require('command-line-args');+const { runCommand } = require('./utils');++const COMMAND_LINE_OPTIONS_DEFINITIONS = [+  { name: 'log-level', type: String, defaultValue: 'log' },+  { name: 'coverage', type: Boolean, defaultValue: false },+  { name: 'help', alias: 'h', type: Boolean, defaultValue: false },+  {+    name: 'path',+    type: String,+    defaultOption: true,+    defaultValue: './src/**/*.unit.spec.js?(x)',+  },+];+const options = commandLineArgs(COMMAND_LINE_OPTIONS_DEFINITIONS);++if (options.help) {+  printUnitTestHelp();+  process.exit(0);+}++const mochaPath = 'BABEL_ENV=test mocha';+const coveragePath =+  'NODE_ENV=test nyc --all --reporter=lcov --reporter=text-summary mocha --reporter mocha-junit-reporter --no-color';+const testRunner = options.coverage ? coveragePath : mochaPath;+const mochaOpts =+  'src/platform/testing/unit/mocha.opts src/platform/testing/unit/helper.js';++// Otherwise, run the command+runCommand(+  `LOG_LEVEL=${options[+    'log-level'+  ].toLowerCase()} ${testRunner} --opts ${mochaOpts} --recursive '${+    options.path+  }'`,+);

It looks like this matches up with what the bash script would do for running a specific test (the path option), but the order of the args is different in the script for running all of the tests. I checked out the branch and ran yarn test:unit locally to see if there were any issues, but I'm getting errors which are also happening for me on master, so this may not be a problem.

jbalboni

comment created time in a day

Pull request review commentdepartment-of-veterans-affairs/vets-website

Add more information in order to debug unit test failures

+const printUnitTestHelp = require('./run-unit-test-help.js');+const commandLineArgs = require('command-line-args');+const { runCommand } = require('./utils');++const COMMAND_LINE_OPTIONS_DEFINITIONS = [+  { name: 'log-level', type: String, defaultValue: 'log' },+  { name: 'coverage', type: Boolean, defaultValue: false },+  { name: 'help', alias: 'h', type: Boolean, defaultValue: false },+  {+    name: 'path',+    type: String,+    defaultOption: true,+    defaultValue: './src/**/*.unit.spec.js?(x)',+  },+];+const options = commandLineArgs(COMMAND_LINE_OPTIONS_DEFINITIONS);++if (options.help) {+  printUnitTestHelp();+  process.exit(0);+}++const mochaPath = 'BABEL_ENV=test mocha';+const coveragePath =+  'NODE_ENV=test nyc --all --reporter=lcov --reporter=text-summary mocha --reporter mocha-junit-reporter --no-color';+const testRunner = options.coverage ? coveragePath : mochaPath;+const mochaOpts =+  'src/platform/testing/unit/mocha.opts src/platform/testing/unit/helper.js';

So, is this meant to replace what the run-unit-test.shscript and run-coverage.sh are doing? I kind of like combining the two into one file since they are so related.

Does the --all flag need to be conditional based on options.path?

jbalboni

comment created time in a day

Pull request review commentdepartment-of-veterans-affairs/vets-website

22-1995 form submit tracking updates

 export const display1995StemFlow = form =>   isEdithNourseRogersScholarship(form) &&   (isEligibleForEdithNourseRogersScholarship(form) ||     determineEligibilityFor1995Stem(form));++export const buildSubmitEventData = formData => {+  if (environment.isProduction()) {+    const exhaustedAllBenefits =+      formData['view:exhaustionOfBenefits'] === true ||+      formData['view:exhaustionOfBenefitsAfterPursuingTeachingCert'] === true;+    return {+      benefitsUsedRecently: formData.benefit,+      'edu-stemApplicant': formData.isEdithNourseRogersScholarship+        ? 'Yes'+        : 'No',+      'edu-undergradStem': formData.isEnrolledStem ? 'Yes' : 'No',+      'edu-pursueTeaching': formData.isPursuingTeachingCert ? 'Yes' : 'No',+      activeDuty: formData.isActiveDuty ? 'Yes' : 'No',+      calledActiveDuty: formData.isActiveDuty ? 'Yes' : 'No',+      preferredContactMethod: formData.preferredContactMethod,+      'edu-exhaustedAllBenefits': exhaustedAllBenefits ? 'Yes' : 'No',+    };+  }++  const yesNoOrUndefined = value => {+    if (value === undefined) {+      return undefined;+    }+    return value ? 'Yes' : 'No';+  };++  return {+    'benefits-used-recently': formData.benefit,+    'new-service-periods-to-record': yesNoOrUndefined(+      formData['view:newService'],+    ),+    'service-details': _.get(formData, 'toursOfDuty', []).map(tour => ({

You don't need to import lodash for this. Try this instead:

     'service-details':  (formData.toursOfDuty || []).map(tour => ({
dmccurdybah

comment created time in 5 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

add in common grid components for row and column. add tests to suppor…

+// libs
+import React from 'react';
+import { render } from '@testing-library/react';
+import { expect } from 'chai';
+
+import Column from 'platform/forms/components/common/grid/Column';
+
+describe('Common Column component', () => {
+  it('should render', () => {
+    const tree = render(<Column testId="12345" />);
+
+    expect(tree.getByTestId('12345')).to.not.be.null;
+    tree.unmount();
+  });
+
+  it('should render child components', () => {
+    const childComponent = <div data-testid="12345">i am a component</div>;
+
+    const tree = render(<Column>{childComponent}</Column>);
+
+    expect(tree.getByTestId('12345')).to.not.be.null;
+    tree.unmount();
+  });
+
+  it('should add classNames to output', () => {
+    const classNames = 'i-am-classname';
+
+    const tree = render(<Column classNames={classNames} testId="12345" />);
+
+    expect(tree.getByTestId('12345')).to.have.class(classNames);
+    tree.unmount();
+  });
+
+  it('should role to output', () => {
+    const role = 'alert';
+
+    const tree = render(<Column role={role} testId="12345" />);
+
+    expect(tree.getByTestId('12345')).to.not.be.null;

This isn't checking the role.

Clark-W-Griswold

comment created time in 5 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

add in common grid components for row and column. add tests to suppor…

+// libs
+import React from 'react';
+import { render } from '@testing-library/react';
+import { expect } from 'chai';
+
+import Column from 'platform/forms/components/common/grid/Column';
+
+describe('Common Column component', () => {
+  it('should render', () => {
+    const tree = render(<Column testId="12345" />);
+
+    expect(tree.getByTestId('12345')).to.not.be.null;
+    tree.unmount();
+  });
+
+  it('should render child components', () => {
+    const childComponent = <div data-testid="12345">i am a component</div>;
+
+    const tree = render(<Column>{childComponent}</Column>);
+
+    expect(tree.getByTestId('12345')).to.not.be.null;
+    tree.unmount();
+  });

Like I mentioned earlier, what do you think of this pattern that avoids relying on data-testid?

  it('should render child components', () => {
    const childComponent = <div>i am a component</div>;

    const tree = render(<Column>{childComponent}</Column>);

    expect(tree.getByText('i am a component')).to.not.be.null;
    tree.unmount();
  });
Clark-W-Griswold

comment created time in 5 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

add in common grid components for row and column. add tests to suppor…

+// libs
+import React from 'react';
+import { render } from '@testing-library/react';
+import { expect } from 'chai';
+
+import Column from 'platform/forms/components/common/grid/Column';
+
+describe('Common Column component', () => {
+  it('should render', () => {
+    const tree = render(<Column testId="12345" />);
+
+    expect(tree.getByTestId('12345')).to.not.be.null;
+    tree.unmount();
+  });

Are there situations where it would make sense to have a <Column> without any children?

Clark-W-Griswold

comment created time in 5 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

add in common grid components for row and column. add tests to suppor…

+// libs
+import React from 'react';
+
+/**
+ * A column layout component
+ * @param {string} classNames strig of classNames to be added to the columns class
+ * @param {node} children content that the columns class wraps
+ * @param {string} role ARIA role for component if needed
+ */
+function Column(props) {
+  const { children, classNames = '', role, testId } = props;
+
+  return (
+    <div className={`${classNames} columns`} role={role} data-testid={testId}>

Is it necessary to add the data-testid attribute just for the sake of testing?

Clark-W-Griswold

comment created time in 5 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

add in common grid components for row and column. add tests to suppor…

+// libs
+import React from 'react';
+import { render } from '@testing-library/react';
+import { expect } from 'chai';
+
+import Column from 'platform/forms/components/common/grid/Column';
+
+describe('Common Column component', () => {
+  it('should render', () => {
+    const tree = render(<Column testId="12345" />);
+
+    expect(tree.getByTestId('12345')).to.not.be.null;
+    tree.unmount();
+  });
+
+  it('should render child components', () => {
+    const childComponent = <div data-testid="12345">i am a component</div>;
+
+    const tree = render(<Column>{childComponent}</Column>);
+
+    expect(tree.getByTestId('12345')).to.not.be.null;
+    tree.unmount();
+  });
+
+  it('should add classNames to output', () => {
+    const classNames = 'i-am-classname';
+
+    const tree = render(<Column classNames={classNames} testId="12345" />);
+
+    expect(tree.getByTestId('12345')).to.have.class(classNames);

This could be:

    const { container } = render(<Column classNames={classNames} />);

    expect(container.firstChild).to.have.class(classNames);
Clark-W-Griswold

comment created time in 5 days

PR merged department-of-veterans-affairs/vets-website

Remove unused key-value pairs from bucket consts

Description

We had been importing the DEVELOPMENT, PRODUCTION, and STAGING values from the environments file and using them as keys to set bucket values, but those values were not being exported from the environments file. Having keys like STAGING and VAGOVSTAGING only adds confusion, so this PR removes the keys that are no longer used.

The exported values:

https://github.com/department-of-veterans-affairs/vets-website/blob/5836f211f0033506ff3c07836d39a7612cc9d1e2/src/site/constants/environments.js#L6-L18

Testing done

Screenshots

Acceptance criteria

  • [ ]

Definition of done

  • [ ] Events are logged appropriately
  • [ ] Documentation has been updated, if applicable
  • [ ] A link has been provided to the originating GitHub issue (or connected to it via ZenHub)
  • [ ] No sensitive information (i.e. PII/credentials/internal URLs/etc.) is captured in logging, hardcoded, or specs
+1 -15

0 comment

1 changed file

bkjohnson

pr closed time in 5 days

push eventdepartment-of-veterans-affairs/vets-website

Brooks Johnson

commit sha 0dc23be1ebd3a3aab8e3a327b2a8dfbdbcaacfbe

Remove unused key-value pairs from bucket consts (#13588) These can cause confusion

view details

push time in 5 days

delete branch department-of-veterans-affairs/vets-website

delete branch : bucket-const-cleanup

delete time in 5 days

push eventdepartment-of-veterans-affairs/va.gov-team

Brooks Johnson

commit sha 47d2d9866df5d0d749119dc5f87662a84eb39349

Update platform/engineering/design-docs/2020-04-09-separate-content-build.md Co-authored-by: Rian Fowler <rian.fowler@adhocteam.us>

view details

push time in 7 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Remove unused key-value pairs from bucket consts

-const {-  DEVELOPMENT,-  PRODUCTION,-  STAGING,

Confusing is right. There was a recent devops PR that prompted me to do this after my own confusion trying to understand what was going on with the s3 buckets.

To my knowledge they aren't useful in any other context. I'll let @rianfowler take a look before I merge though.

bkjohnson

comment created time in 8 days

issue commentdepartment-of-veterans-affairs/va.gov-team

Code Isolation - Remove Dependencies between Content and Site Builds

Release plan for: https://github.com/department-of-veterans-affairs/devops/pull/7262

(Draft)

Once the mentioned PR is merged, any new reverse proxy deploy will be using the reorganized files. The logic isn't changed, but we want to make sure that the reorganization hasn't overlooked any critical parts and that the reverse proxy continues to function as it did previously.

In order to do this, after deploys to each environment we will monitor the Grafana dashboards for the reverse proxy. Additionally, shortly after it is merged I will open a PR to revert it so that we have that ready to go immediately in case the reverse proxy has a failure.

Manual testing

To get an idea of whether or not the reverse proxy is working, we can go to va.gov (or the dev/staging environment) and see if the site loads correctly. An issue with the reverse proxy would prevent the site assets from being proxied appropriately.

brandonrapp

comment created time in 8 days

delete branch department-of-veterans-affairs/va.gov-team

delete branch : bkjohnson/flag-for-manual-review-doc

delete time in 11 days

push eventdepartment-of-veterans-affairs/va.gov-team

Brooks Johnson

commit sha 72d4d5e4c658bb83efe2476d0710e8cf17261282

Flag for manual review design doc (#6138) * Create flag-for-manual-review.md More revisions will follow * Add some more overview info * Add some specifics * Add some more details * Remove some remplate info * Add more info on what triggers a manual review * Add a caveat * Move into design-docs folder * Fix typo Co-Authored-By: Rian Fowler <rian.fowler@adhocteam.us> * Remove harsh-sounding non-goal Co-Authored-By: Rian Fowler <rian.fowler@adhocteam.us> * Be more succinct about review turnaround Co-Authored-By: Rian Fowler <rian.fowler@adhocteam.us> * Apply suggestions from code review Co-Authored-By: Andrew Gunsch <andrew.gunsch@adhocteam.us> * Update security concerns section * Add detail on how to handle the token securely * Add more info on environment variables Pulled from PR description in https://github.com/department-of-veterans-affairs/vets-website/pull/11670 * Use file extension in link Co-Authored-By: Andrew Gunsch <andrew.gunsch@adhocteam.us> * Move design doc out of design-docs folder That seems to be just for the template * Fix typo in environment variables link * Add detail on discovering when process is ignored * Add repo and file description to code location * Be more specific about testing plan * Add a bit of background on codeowners changes * Add detail on how the Github API is used * Fix ref case * Apply suggestions from code review Co-Authored-By: Andrew Gunsch <andrew.gunsch@adhocteam.us> * Remove manual-review-triggers doc This was pulled out and added in this PR: - https://github.com/department-of-veterans-affairs/va.gov-team/pull/6592 * Mark as approved Co-authored-by: Rian Fowler <rian.fowler@adhocteam.us> Co-authored-by: Andrew Gunsch <andrew.gunsch@adhocteam.us>

view details

push time in 11 days

PR merged department-of-veterans-affairs/va.gov-team

Reviewers
Flag for manual review design doc

This is a draft design doc for what we've been calling the automated "flag for manual review" process. It is not strictly a design doc since I ended up creating the solution ahead of time as I was experimenting with Github's API and Circle's CI config, but I tried to capture some design decisions and open questions.

All feedback welcome.

Here is an earlier issue which describes some of the goals. I will try to work that into the design doc somehow.

+147 -3

0 comment

2 changed files

bkjohnson

pr closed time in 11 days

push eventdepartment-of-veterans-affairs/va.gov-team

Brooks Johnson

commit sha c41f349a584c9a22fd5a3bb1238859b4d5e30f47

Remove manual-review-triggers doc This was pulled out and added in this PR: - https://github.com/department-of-veterans-affairs/va.gov-team/pull/6592

view details

Brooks Johnson

commit sha 11ae9013265e89e008420a640d7c99344e6c6bbb

Mark as approved

view details

push time in 11 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Add React Error boundary#13576

+// libs
+import React from 'react';
+import * as Sentry from '@sentry/react';
+
+// default fallback component
+function FallbackComponent() {
+  return <div />;
+}
+
+function ErrorBoundary(props) {
+  const { children, fallback, showDialog = false } = props;
+
+  return (
+    <Sentry.ErrorBoundary
+      fallback={fallback || FallbackComponent}
+      showDialog={showDialog}
+    >
+      {children}
+    </Sentry.ErrorBoundary>
+  );

So what exactly is this doing for us?

Clark-W-Griswold

comment created time in 11 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

New transformer for node-full_width_banner_alert

+const {+  getDrupalValue,+  createMetaTagArray,+  utcToEpochTime,+} = require('./helpers');++const transform = entity => ({+  entityType: 'node',+  entityBundle: 'full_width_banner_alert',+  title: getDrupalValue(entity.title),+  changed: utcToEpochTime(getDrupalValue(entity.changed)),+  entityMetatags: createMetaTagArray(entity.metatag.value),+  path: getDrupalValue(entity.path),

So if path isn't in the transformed output, then shouldn't it be removed from the transformer?

jhonnyoddball

comment created time in 11 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

bradl3yC - 11493 11502 - debt letter error states and ff

 fn.name@1.x.x:   resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"   integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -focus-lock@^0.7.0:

Changing the yarn.lock file without changing package.json, and not calling it out in the PR description is concerning. Do you know what is happening here?

bradl3yC

comment created time in 11 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

bradl3yC - 11493 11502 - debt letter error states and ff

+import React from 'react';+import reverse from 'lodash/reverse';+import { connect } from 'react-redux';+import DebtLetterCard from './DebtLetterCard';++const DebtCardsList = ({ debts, isError }) => {+  const renderAlert = () => (+    <div+      className="usa-alert usa-alert-error vads-u-margin-top--0 vads-u-padding--3"+      role="alert"+    >+      <div className="usa-alert-body">+        <h3 className="usa-alert-heading">+          Information about your current debts is unavailable+        </h3>

And here too.

bradl3yC

comment created time in 11 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

bradl3yC - 11493 11502 - debt letter error states and ff

 import React from 'react';-import DebtLetterCard from './DebtLetterCard';-import { connect } from 'react-redux'; import Breadcrumbs from '@department-of-veterans-affairs/formation-react/Breadcrumbs';+import { connect } from 'react-redux'; import HowDoIPay from './HowDoIPay'; import NeedHelp from './NeedHelp';-import reverse from 'lodash/reverse';+import DebtCardsList from './DebtCardsList';+import DebtLettersList from './DebtLettersList'; -const DebtLettersSummary = ({ debts }) => (-  <>-    <Breadcrumbs className="vads-u-font-family--sans">-      <a href="/">Home</a>-      <a href="/debt-letters">Manage your VA debt</a>-      <a href="/debt-letters/debt-list">Your VA debt</a>-    </Breadcrumbs>-    <div className="vads-l-row vads-u-margin-x--neg2p5">-      <h1 className="vads-u-padding-x--2p5">Your VA debt</h1>-      <div className="vads-u-display--flex vads-u-flex-direction--row">-        <div className="vads-l-col--12 vads-u-padding-x--2p5 medium-screen:vads-l-col--8">-          <p className="vads-u-font-size--h3 vads-u-margin-top--0">-            Check the details of your VA debts and find out the next stops to-            resolving your debt.-          </p>-          {debts.length > 0 && (-            <>-              <p className="vads-u-font-size--h2 vads-u-font-weight--bold">-                Current debts-              </p>-              {reverse(debts).map((debt, index) => (-                <DebtLetterCard-                  key={`${index}-${debt.fileNumber}`}-                  debt={debt}-                />-              ))}-              <h2 className="vads-u-font-size--h3">-                What if I don't see a debt?-              </h2>-              <p className="vads-u-margin-bottom--0 vads-u-font-family--sans">-                If you have been notified of a debt that you do not see on this-                page or would like to get information about your debts that have-                been resolved, call the Debt Management Center at-              </p>-              <p className="vads-u-margin-top--0 vads-u-font-family--sans">-                <a href="tel: 800-827-0648" aria-label="800. 8 2 7. 0648.">-                  800-827-0648-                </a>-                {'.'}-              </p>-            </>-          )}-          {debts.length < 1 && (-            <div className="vads-u-background-color--gray-lightest vads-u-padding--3">-              <h4 className="vads-u-font-family--serif vads-u-margin-top--0">-                You don't have any current Education or Compensation & Pension-                Debts-              </h4>-              <p className="vads-u-font-family--sans vads-u-margin-bottom--0">-                If you believe that you have a debt with the VA or would like to-                get information about your debts that have been resolved, call-                the Debt Management Center at{' '}-                <a href="tel: 800-827-0648" aria-label="800. 8 2 7. 0648.">-                  800-827-0648-                </a>-              </p>-            </div>-          )}-        </div>-        <div className="vads-u-display--flex vads-u-flex-direction--column vads-l-col--12 vads-u-padding-x--2p5 medium-screen:vads-l-col--4">-          <HowDoIPay />-          <NeedHelp />-        </div>+const DebtLettersSummary = ({ isError, isVBMSError }) => {+  const renderAlert = () => (+    <div+      className="usa-alert usa-alert-error vads-u-margin-top--0 vads-u-padding--3"+      role="alert"+    >+      <div className="usa-alert-body">+        <h3 className="usa-alert-heading">+          We're sorry. Something went wrong on our end.+        </h3>

And possibly here as well?

bradl3yC

comment created time in 11 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

bradl3yC - 11493 11502 - debt letter error states and ff

 import React from 'react';-import { connect } from 'react-redux';-import HowDoIPay from './HowDoIPay';-import NeedHelp from './NeedHelp'; import environment from 'platform/utilities/environment';-import Breadcrumbs from '@department-of-veterans-affairs/formation-react/Breadcrumbs'; import moment from 'moment';+import { connect } from 'react-redux'; -const DebtLettersList = ({ debtLinks }) => (-  <>-    <Breadcrumbs className="vads-u-font-family--sans">-      <a href="/">Home</a>-      <a href="/debt-letters">Manage your VA debt</a>-      <a href="/debt-letters/debt-list">Your VA debt</a>-    </Breadcrumbs>-    <div className="vads-l-row vads-u-margin-x--neg2p5">-      <h1 className="vads-u-padding-x--2p5">View debt letters</h1>-      <div className="vads-u-display--flex vads-u-flex-direction--row">-        <div className="vads-l-col--12 vads-u-padding-x--2p5 medium-screen:vads-l-col--8">-          <p className="vads-u-font-size--h3 vads-u-margin-y--0">-            See your debt letters history and download individual letters, and-            find out how to resolve your debt.-          </p>-          {debtLinks.length > 0 && (-            <div className="vads-l-row">-              <h2 className="vads-u-margin-bottom--0 vads-u-margin-top--5">-                Your debt letters-              </h2>-              <table className="vads-u-font-family--sans vads-u-margin-bottom--5 vads-u-margin-top--3">-                <thead>-                  <tr>-                    <th className="vads-u-border--0">Date</th>-                    <th className="vads-u-border--0">Type</th>-                    <th className="vads-u-border--0">Action</th>+const DebtLettersList = ({ debtLinks, isVBMSError }) => {+  const renderAlert = () => (+    <div+      className="usa-alert usa-alert-error vads-u-margin-top--0 vads-u-padding--3"+      role="alert"+    >+      <div className="usa-alert-body">+        <h3 className="usa-alert-heading">+          Your debt letters are currently unavailable+        </h3>

Is there a reason that the <AlertBox> component wasn't used here?

bradl3yC

comment created time in 11 days

PR opened department-of-veterans-affairs/vets-website

Remove unused key-value pairs from bucket consts

Description

We had been importing the DEVELOPMENT, PRODUCTION, and STAGING values from the environments file and using them as keys to set bucket values, but those values were not being exported. Having keys like STAGING and VAGOVSTAGING only adds confusion, so this PR removes the keys that are no longer used.

Testing done

Screenshots

Acceptance criteria

  • [ ]

Definition of done

  • [ ] Events are logged appropriately
  • [ ] Documentation has been updated, if applicable
  • [ ] A link has been provided to the originating GitHub issue (or connected to it via ZenHub)
  • [ ] No sensitive information (i.e. PII/credentials/internal URLs/etc.) is captured in logging, hardcoded, or specs
+1 -15

0 comment

1 changed file

pr created time in 12 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Jc adjust location fields

 import currentOrPastDateUI from 'platform/forms-system/src/js/definitions/currentOrPastDate'; import { addSpouse } from '../../../utilities'; import { SpouseTitle } from '../../../../components/ArrayPageItemSpouseTitle';-import { stateTitle, cityTitle } from '../../../helpers';+import {+  stateTitle,+  cityTitle,+  isChapterFieldRequired,

I see this being added as an import but it doesn't seem to be used in the diff. Does this need to be here?

cohnjesse

comment created time in 12 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Jc adjust location fields

 export const cityTitle = (     City <strong>or</strong> county   </> );++export const isInsideListLoopReturn = (+  chapter,+  outerField,+  isInsideListLoop,+  uiTitle,+  formChapter,+) => {+  return {+    'ui:title': uiTitle,+    isOutsideUS: {+      'ui:title': 'This occurred outside the US',+    },+    country: {+      'ui:title': 'Country',+      'ui:required': (formData, index) =>+        formData[chapter][`${index}`][outerField]?.isOutsideUS,+      'ui:options': {+        hideIf: (formData, index) => {+          if (!formData[chapter][`${index}`][outerField]?.isOutsideUS) {+            return true;+          }+          return false;+        },+      },+    },+    state: {+      'ui:title': 'State',+      'ui:required': (formData, index) =>+        !formData[chapter][`${index}`][outerField]?.isOutsideUS,+      'ui:options': {+        hideIf: (formData, index) => {+          if (formData[chapter][`${index}`][outerField]?.isOutsideUS) {+            return true;+          }+          return false;+        },+      },+    },+    city: {+      'ui:required': formData => isChapterFieldRequired(formData, formChapter),+      'ui:title': 'City',+    },+  };+};++export const isOutsideListLoopReturn = (+  chapter,+  outerField,+  isInsideListLoop,+  uiTitle,+  formChapter,+) => {+  return {+    'ui:title': 'Where were you married?',+    isOutsideUS: {+      'ui:title': 'This occurred outsite the US',+    },+    country: {+      'ui:title': 'Country',+      'ui:required': formData => formData[chapter][outerField]?.isOutsideUS,+      'ui:options': {+        hideIf: formData => {+          if (!formData[chapter][outerField].isOutsideUS) {+            return true;+          }+          return false;+        },+      },+    },+    state: {+      'ui:title': 'State',+      'ui:required': formData => !formData[chapter][outerField]?.isOutsideUS,+      'ui:options': {+        hideIf: formData => {+          if (formData[chapter][outerField].isOutsideUS) {+            return true;+          }+          return false;

If isOutsideUs is a boolean like the name suggests, this could just be:

return formData[chapter][outerField].isOutsideUS

If undefined values are a problem and boolean values are always needed here, then you could put a !! at the beginning to convert the value to a boolean.

cohnjesse

comment created time in 12 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Add node-health_services_listing transformer

+/* eslint-disable camelcase */++module.exports = {+  type: 'object',+  properties: {+    title: { $ref: 'GenericNestedString' },+    created: { $ref: 'GenericNestedString' },+    changed: { $ref: 'GenericNestedString' },+    promote: { $ref: 'GenericNestedBoolean' },+    sticky: { $ref: 'GenericNestedBoolean' },+    default_langcode: { $ref: 'GenericNestedBoolean' },+    revision_translation_affected: { $ref: 'GenericNestedBoolean' },+    moderation_state: { $ref: 'GenericNestedString' },+    metatag: { $ref: 'RawMetaTags' },+    path: { $ref: 'RawPath' },+    field_administration: {

Sometimes the value will always be an array of exactly one EntityReference, so in those cases it is more specific to say that it is an array of on EntityReference instead of an EntityReferenceArray.

theodur

comment created time in 12 days

pull request commentdepartment-of-veterans-affairs/vets-website

Add more information in order to debug unit test failures

What if we used script/mocha.js instead? It looks like this is the script that is run for the test:watch command, so we may be able to consolidate this node script and run-unit-test.sh into one node script.

jbalboni

comment created time in 12 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

New transformer for node-full_width_banner_alert

+const {+  getDrupalValue,+  createMetaTagArray,+  utcToEpochTime,+} = require('./helpers');++const transform = entity => ({+  entityType: 'node',+  entityBundle: 'full_width_banner_alert',+  title: getDrupalValue(entity.title),+  changed: utcToEpochTime(getDrupalValue(entity.changed)),+  entityMetatags: createMetaTagArray(entity.metatag.value),+  path: getDrupalValue(entity.path),

I see that path is part of the transformer, so shouldn't it be uncommented in the output schema?

jhonnyoddball

comment created time in 13 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

New transformer for node-full_width_banner_alert

+/* eslint-disable camelcase */++module.exports = {+  type: 'object',+  properties: {+    title: { $ref: 'GenericNestedString' },+    changed: {+      type: 'array',+      maxItems: 1,+      items: {+        type: 'object',+        properties: {+          value: { type: 'string' },+          format: { type: 'string' },+        },+        required: ['value', 'format'],+      },+    },+    metatag: { $ref: 'RawMetaTags' },+    path: {+      type: 'array',+      maxItems: 1,+      items: {+        type: 'object',+        properties: {+          alias: { type: 'string' },+        },+        required: ['alias'],+      },+    },

We have a common path schema that I think you could use here like this:

path: { $ref: 'RawPath' },
jhonnyoddball

comment created time in 13 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

New transformer for node-full_width_banner_alert

 module.exports = {   type: 'object',+  properties: {+    contentModelType: { enum: ['node-full_width_banner_alert'] },+    entityType: { enum: ['node'] },+    entityBundle: { enum: ['full_width_banner_alert'] },+    title: { type: 'string' },+    changed: { type: 'number' },+    entityUrl: { $ref: 'EntityUrl' },+    // path: { type: 'object', properties: {} },+    entityMetatags: { $ref: 'MetaTags' },+    fieldAdministration: {+      $ref: 'output/taxonomy_term-administration',+    },+    fieldAlertDismissable: { type: 'boolean' },+    fieldAlertEmailUpdatesButton: { type: 'boolean' },+    fieldAlertFindFacilitiesCta: { type: 'boolean' },+    fieldAlertInheritanceSubpages: { type: 'boolean' },+    fieldAlertOperatingStatusCta: { type: 'boolean' },+    fieldAlertType: { type: 'string' },+    fieldBannerAlertComputdvalues: { type: 'string' },+    fieldBannerAlertVamcs: {+      $ref: 'output/node-vamc_operating_status_and_alerts',+    },+    fieldBody: { type: 'string' },+    fieldOperatingStatusSendemail: { type: 'boolean' },+    fieldSituationUpdates: {+      type: 'array',+      items: {+        $ref: 'Paragraph',+      },+    },+  },+  required: [+    'title',+    'changed',+    'entityUrl',+    // 'path',

Is this something we care about for this entity?

jhonnyoddball

comment created time in 13 days

push eventdepartment-of-veterans-affairs/va.gov-team

Brooks Johnson

commit sha b095c9e2dd7ca074f632488af12ecd990fe7c5e3

Update manual-review-triggers.md (#11454) Add docs for how to add a new trigger

view details

push time in 13 days

delete branch department-of-veterans-affairs/va.gov-team

delete branch : manual-review-docs

delete time in 13 days

PR merged department-of-veterans-affairs/va.gov-team

Reviewers
Update manual-review-triggers.md

Add docs for how to add a new trigger

Related to https://github.com/department-of-veterans-affairs/va.gov-team/issues/11358

+49 -0

0 comment

1 changed file

bkjohnson

pr closed time in 13 days

pull request commentdepartment-of-veterans-affairs/vets-website

updated displayed word to "Selected" for checkboxes on review page of a form

Tagging @peggygannon for awareness

zurbergram

comment created time in 13 days

issue openeddepartment-of-veterans-affairs/va.gov-team

Document the frontend revproxy config

Description

In anticipation of making changes to the reverse proxy config for the frontend website, we need to first document what each existing piece does so that we are aware of what may need to be changed.

Background/context/resources

  • https://github.com/department-of-veterans-affairs/va.gov-team/issues/11023

Tasks

  • [ ] Write a document that captures all of the things that the reverse proxy is doing for the va.gov frontend

Definition of Done

  • [ ] We have a document covering the revproxy responsibilities on the frontend

created time in 13 days

PR opened department-of-veterans-affairs/va.gov-team

Update manual-review-triggers.md

Add docs for how to add a new trigger

Related to https://github.com/department-of-veterans-affairs/va.gov-team/issues/11358

+49 -0

0 comment

1 changed file

pr created time in 14 days

create barnchdepartment-of-veterans-affairs/va.gov-team

branch : manual-review-docs

created branch time in 14 days

PR closed department-of-veterans-affairs/vets-website

Webpack copy assets

Description

This is part of https://github.com/department-of-veterans-affairs/va.gov-team/issues/7946

Here is a list of our current js assets:

✔︎ js (webpack-copy-assets) ✗ pwd
/home/brooks/Projects/vets-website/src/site/assets/js
✔︎ js (webpack-copy-assets) ✗ tree
.
├── execute-axe-check.js
├── foresee
│   ├── vagovprod.js
│   └── vagovstaging.js
├── google-analytics
│   ├── vagovdev.js
│   ├── vagovprod.js
│   └── vagovstaging.js
├── incompatible-browser.js
├── record-event.js
├── static-page-widgets.js
└── vendor
    └── uswds.min.js

3 directories, 10 files

The foresee files are included in the templates, so we don't need to worry about copying them over. The google-analytics files are the same way

incompatible-browser.js is included in the header along with record-event.js

static-page-widgets.js is included in the footer.

vendor/uswds.min.js is only used in our teamsite header injection.

This just leaves execute-axe-check.js, which is loaded using a src attribute, so we do need to copy it over:

https://github.com/department-of-veterans-affairs/vets-website/blob/65720f7eb2ad0a9824740bc3900ccb77dc80b8c3/src/site/stages/build/plugins/inject-axe-core.js#L38-L40

This PR adds the webpack-copy-plugin and leaves the src/site/assets/img and src/site/assets/fonts copying in with the metalsmith build, and moves the execute-axe-check.js script and robots.txt copying into the webpack portion of the build.

Testing done

Local build and watch.

Screenshots

Acceptance criteria

  • [ ]

Definition of done

  • [ ] Events are logged appropriately
  • [ ] Documentation has been updated, if applicable
  • [ ] A link has been provided to the originating GitHub issue (or connected to it via ZenHub)
  • [ ] No sensitive information (i.e. PII/credentials/internal URLs/etc.) is captured in logging, hardcoded, or specs
+67 -5

1 comment

9 changed files

bkjohnson

pr closed time in 15 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Add common properties to entities after transformation

 const validateOutput = (entity, transformedEntity) => {   } }; +/**+ * Add common properties to the transformed entity. Mutates `transformedEntity`+ * to save memory.+ * @param {Object} transformedEntity - The entity after transformation+ * @param {Object} originalEntity - The entity before transformation+ * @returns {void}+ */+const addCommonProperties = (transformedEntity, originalEntity) => {+  /* eslint-disable no-param-reassign */+  transformedEntity.contentModelType =+    transformedEntity.contentModelType || getContentModelType(originalEntity);+  const [+    entityType,+    entityBundle,+  ] = transformedEntity.contentModelType.includes('-')+    ? transformedEntity.contentModelType.split('-')+    : [transformedEntity.contentModelType, transformedEntity.contentModelType];

Having entityType and entityBundle be the same here seems odd. For things like paragraph-q_a_section it's clear which is the bundle and which is the type, but for a plain ol' paragraph why do we need the bundle as well?

cvalarida

comment created time in 18 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Add common properties to entities after transformation

 function getContentModelType(entity) {   return [entity.baseType, subType].filter(x => x).join('-'); } +/**+ * Add common properties to the entity. Does not mutate `entity`; instead,+ * returns a new object.

Is there an advantage here to not modifying the entity directly?

cvalarida

comment created time in 18 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Sanlouise 11196 align checkmarks

 import PropTypes from 'prop-types';  * children content  */ const Verified = ({ children }) => (-  <p className="vads-u-margin--0 vads-u-padding-left--3">-    <i className="fa fa-check vads-u-color--green vads-u-margin-right--0p5 vads-u-margin-left--neg3" />{' '}-    {children}-  </p>-);+  <span className="vads-u-display--flex">+    <i className="fa fa-check vads-u-color--green vads-u-margin-top--0p5" />

This icon appears to be purely decorative, so it should probably just have an additional aria-hidden="true".

sanlouise

comment created time in 18 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Don't transform unpublished entities

 const PUBLIC_URLS_NO_SCHEME = Object.entries(PUBLIC_URLS).reduce(   {}, ); -function replacePathInData(data, replacer) {+function replacePathInData(data, replacer, ancestors = []) {+  // Circular references happen when an entity in the CMS has a child entity+  // which is also in its ancestor tree. When this hapens, this function becomes+  // infinitely recursive. This check looks for circular references and, when+  // found, exits early because it's already checked that data.+  if (ancestors.includes(data)) return data;

I'm guessing that this also doesn't have to do with unpublished entities, so can you expand the description a bit? If this would cause infinite recursion, how is it just now being noticed?

cvalarida

comment created time in 21 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Don't transform unpublished entities

 const shouldPullDrupal = buildOptions =>   !fs.existsSync(getDrupalCachePath(buildOptions));  function pipeDrupalPagesIntoMetalsmith(contentData, files) {-  const {-    data: {-      nodeQuery: { entities: pages },-    },-  } = contentData;--  const skippedContent = {-    nullEntities: 0,-    emptyEntities: 0,-  };+  const pages = contentData.data.nodeQuery.entities.filter(

Can you elaborate on these changes?

cvalarida

comment created time in 21 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

VACMS-2235: Adding filter to prevent expired events from being featured.

 Example data:                 class="fa fa-chevron-right va-l-font-size--12px"></i>             </a>           </section>+          {% elsif eventTeasersAll.entities.0.reverseFieldListingNode.entities.length %}+          <section>+            <h2+              class="vads-u-margin-top--4 vads-u-margin-bottom--2 medium-screen:vads-u-margin-bottom--2p5">+              Events</h2>+            {% for event in eventTeasersAll.entities.0.reverseFieldListingNode.entities %}+            {% assign node = event %}+            {% include "src/site/teasers/event.drupal.liquid" %}+            {% endfor %}+            <a onClick="recordEvent({ event: 'nav-secondary-button-click' });"+              class="usa-button usa-button-secondary vads-facility-hub-button vads-u-width--full medium-screen:vads-u-width--auto vads-u-font-size--md vads-u-margin--0"+              href="{{ entityUrl.path }}/events">+              See all events <i class="fa fa-chevron-right va-l-font-size--12px"></i>

This doesn't appear to conform to the fontawesome accessibility guidelines.

ethanteague

comment created time in 21 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Don't transform unpublished entities

 const entityAssemblerFactory = contentDir => {         parentFieldName,         contentDir,         assembleEntityTree,+        transformUnpublished,

It looks like we're passing this extra boolean argument to transformEntity defined in src/site/stages/build/process-cms-exports/transform.js. Do you want to add an arg there?

cvalarida

comment created time in 22 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Don't transform unpublished entities

 if (entityNames) {     );   } -  const modifiedEntities = map(entities, entity => assembleEntityTree(entity));+  const modifiedEntities = map(+    entities,+    entity => assembleEntityTree(entity),+    transformUnpublished,

Should transformUnpublished be passed to assembleEntityTree as the second argument instead?

cvalarida

comment created time in 22 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

[Development] Remove obsolete form 526EZ v1

 const excludedForms = new Set([   '24-0296',   '10-10CG-example',   '686C-674', // Until we import the schema-  VA_FORM_IDS.FORM_21_526EZ, // old+  VA_FORM_IDS.FORM_21_526EZ, // old (v1 removed)

Interesting, good to know. I'll go ahead and approve.

Mottie

comment created time in 25 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

[Development] Remove obsolete form 526EZ v1

 const excludedForms = new Set([   '24-0296',   '10-10CG-example',   '686C-674', // Until we import the schema-  VA_FORM_IDS.FORM_21_526EZ, // old+  VA_FORM_IDS.FORM_21_526EZ, // old (v1 removed)

Since this is no longer part of vets-json-schema can this line just be removed? If so, we could also remove the entry in the platform/forms/constants file.

Mottie

comment created time in 25 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Sanlouise 10596 profile content edits

+import React from 'react';+import PhoneNumberWidget from 'platform/forms-system/src/js/review/PhoneNumberWidget';++export default function VAPPhoneView({ data: phoneData }) {+  const phoneNumber = (+    <PhoneNumberWidget+      value={[phoneData.areaCode, phoneData.phoneNumber].join('')}+    />+  );++  const extension = phoneData.extension && <span>x{phoneData.extension}</span>;+  return (+    <div>+      {phoneNumber} {extension}

I'm kind of surprised that extension isn't an optional prop for <PhoneNumberWidget> - I wonder if that's something worth adding eventually.

sanlouise

comment created time in 25 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Cms transformer generator

+module.exports = {+  type: 'object',+  properties: {+  entityType: { type: 'string', enum: ['<%= entityType %>'] },+  entityBundle: { type: 'string', enum: ['<%= entityBundle %>'] },+  <%_ fieldData.forEach(fd => { _%>+  <%- fd.outputFieldName %>: <%- fd.outputSchema %>,+  <%_ }); _%>+  },+};

Same here regarding required.

cvalarida

comment created time in 25 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Cms transformer generator

+const path = require('path');+const fs = require('fs');+const Generator = require('yeoman-generator');+const fuzzy = require('fuzzy');+const _ = require('lodash');++const transformersDir = path.resolve(__dirname, '../transformers');++const inputSchemas = [+  `{ $ref: 'GenericNestedString' }`,+  `{ $ref: 'GenericNestedBoolean' }`,+  `{ $ref: 'GenericNestedNumber' }`,+  `{ $ref: 'EntityReferenceArray' }`,+  `{ $ref: 'RawMetaTag' }`, // Used in the input schema+  `{ $ref: 'MetaTag' }`, // Used in the output schema+];++const outputSchemas = [+  `{ type: 'string' }`,+  `{ type: 'object', properties: {} }`,+  `{ type: 'array' }`,+  `{ type: 'number' }`,+  `{ type: 'boolean' }`,+];++const getFieldSchema = schemaOptions => async (answers, input = '') =>+  fuzzy.filter(input, schemaOptions).map(el => el.original);++module.exports = class extends Generator {+  constructor(args, opts) {+    super(args, opts);+    this.env.adapter.promptModule.registerPrompt(+      'autocomplete',+      require('inquirer-autocomplete-prompt'),

:sparkles:

cvalarida

comment created time in 25 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Cms transformer generator

+/* eslint-disable camelcase */++module.exports = {+  type: 'object',+  properties: {+  <% fieldData.forEach(fd => { %>    <%- fd.inputFieldName %>: <%- fd.inputSchema %>,+  <% }) %>+  },+};

This doesn't have the required key. Should that be included?

cvalarida

comment created time in 25 days

Pull request review commentdepartment-of-veterans-affairs/vets-website

Cms transformer generator

     "lint:sass": "sass-lint --verbose",     "mock-api": "node src/platform/testing/e2e/mockapi.js",     "new:app": "yo @department-of-veterans-affairs/vets-website && npm run lint:js:untracked:fix",-    "new:cms-content-model": "yo ./src/site/stages/build/process-cms-exports/generator-cms-content-model/generators/app/index.js",+    "new:cms-content-model": "yo ./src/site/stages/build/process-cms-exports/generator/index.js && npm run lint:js:untracked:fix",

The linting is a nice addition :+1:

cvalarida

comment created time in 25 days

push eventdepartment-of-veterans-affairs/vets-website

Chris Valarida

commit sha 431ab07075e541d8904b8718f61883228927e9ff

Rename schemas (#13422) * Rename schemas: raw -> input; transformed -> output * Change import references * Point $refs from 'transformed/' to 'output/'

view details

push time in a month

delete branch department-of-veterans-affairs/vets-website

delete branch : rename-schemas-cv

delete time in a month

PR merged department-of-veterans-affairs/vets-website

Reviewers
Rename schemas

Description

I discovered better names for these schemas a few weeks back and now would like to rename them.

raw -> input transformed -> output

It feels like the kind of thing that's obvious in retrospect, so it seems like a good move.

Testing done

Ran node script/cms/test-bundle-export.js and it compiled the schemas correctly and validated the data against them, so I'm confident it's working.

Screenshots

image Note: The schemas it says it's missing just haven't been written yet. Notice the input validation error. Means the schemas are being used as expected.

+31 -31

0 comment

82 changed files

cvalarida

pr closed time in a month

issue openeddepartment-of-veterans-affairs/va.gov-team

Reorganize the reverse proxy config

Description

Our reverse proxy config has a lot going on inside of it, and it would be helpful to reorganize that so that other efforts can be finished in an easier way.

Background/context/resources

This will help us with https://github.com/department-of-veterans-affairs/va.gov-team/issues/10413


Tasks

  • [ ] Remove any outdated pieces of config
  • [ ] Reorganize the remaining config so that there is only a single server {} block per file

created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

7488 e2e tests 5

 function expectNavigateAwayFrom(client, urlSubstring) {     .before(Timeouts.slow); } +function expectElementNotPresent(client, elementSelector) {+  client.expect.element(elementSelector).to.not.be.present;+}+

Cool. It looks like you can merge if you want since a frontend review isn't required.

cohnjesse

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

[Development] Show back pay details in CST complete step

 export function makeAuthRequest( }  export function getCompletedDate(claim) {-  if (claim.attributes && claim.attributes.eventsTimeline) {+  if (claim?.attributes && claim.attributes.eventsTimeline) {

This might be able to be reduced to:

   if (claim?.attributes.eventsTimeline) { 
Mottie

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

7488 e2e tests 5

 function expectNavigateAwayFrom(client, urlSubstring) {     .before(Timeouts.slow); } +function expectElementNotPresent(client, elementSelector) {+  client.expect.element(elementSelector).to.not.be.present;+}+

Yes.

cohnjesse

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

10734 custom question hawaii

 import MetaTags from 'react-meta-tags'; import MultiQuestionForm from '../components/MultiQuestionForm'; import { questions, defaultOptions } from '../config/questions'; -export default function App() {-  return (-    <div className="covid-screener">-      <MetaTags>-        <meta name="robots" content="noindex" />-      </MetaTags>-      <div className="vads-l-grid-container">-        <h1>COVID-19 screening tool</h1>-        <div className="va-introtext">-          <p>-            Please answer the questions listed below. Share your results with-            the staff member at the facility entrance.-          </p>-          <p>We won't store or share your data.</p>+// eslint-disable-next-line react/prefer-stateless-function

What about something like:

diff --git a/src/applications/coronavirus-screener/containers/App.jsx b/src/applications/coronavirus-screener/containers/App.jsx
index e6d5385f88..f40f2212fb 100644
--- a/src/applications/coronavirus-screener/containers/App.jsx
+++ b/src/applications/coronavirus-screener/containers/App.jsx
@@ -3,7 +3,7 @@ import MetaTags from 'react-meta-tags';
 import MultiQuestionForm from '../components/MultiQuestionForm';
 import { questions, defaultOptions } from '../config/questions';
 
-export default function App() {
+export default function App({ params }) {
   return (
     <div className="covid-screener">
       <MetaTags>
@@ -21,6 +21,7 @@ export default function App() {
         <MultiQuestionForm
           questions={questions}
           defaultOptions={defaultOptions}
+          customId={params.id}
         />
       </div>
     </div>

If params is just a prop then it should get passed in as a value in the props argument of a functional component which can then be destructured.

mchelen-gov

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

10734 custom question hawaii

 import MetaTags from 'react-meta-tags'; import MultiQuestionForm from '../components/MultiQuestionForm'; import { questions, defaultOptions } from '../config/questions'; -export default function App() {-  return (-    <div className="covid-screener">-      <MetaTags>-        <meta name="robots" content="noindex" />-      </MetaTags>-      <div className="vads-l-grid-container">-        <h1>COVID-19 screening tool</h1>-        <div className="va-introtext">-          <p>-            Please answer the questions listed below. Share your results with-            the staff member at the facility entrance.-          </p>-          <p>We won't store or share your data.</p>+// eslint-disable-next-line react/prefer-stateless-function

Is there a reason that <App> needs to be a class based component?

mchelen-gov

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

Sanlouise 10397 Add cancellation modal to Personal Information

 class VAPProfileField extends React.Component {     return (       <div className="vet360-profile-field" data-field-name={fieldName}>         <Modal-          title={`You’re currently editing your ${VET360.FIELD_TITLES[-            activeEditView-          ]?.toLowerCase()}`}+          title={'Are you sure?'}+          status="warning"+          visible={this.state.showConfirmCancelModal}+          onClose={() => {+            this.setState({ showConfirmCancelModal: false });+          }}+        >+          <p>+            {' '}

It's a prettier thing :shrug:

sanlouise

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

7488 e2e tests 5

 function expectNavigateAwayFrom(client, urlSubstring) {     .before(Timeouts.slow); } +function expectElementNotPresent(client, elementSelector) {+  client.expect.element(elementSelector).to.not.be.present;+}+

It appears that you did add it as part of the commit "added stuff"

cohnjesse

comment created time in a month

pull request commentdepartment-of-veterans-affairs/vets-website

bradl3yC - 10543 - Updating entry point to URL provided

Can you add an issue, link, or provide more context?

bradl3yC

comment created time in a month

PR opened department-of-veterans-affairs/vets-website

[a11y] Don't wrap legend tags in divs

Description

This might be a total fix for https://github.com/department-of-veterans-affairs/va.gov-team/issues/767

There is some refactoring happening but I scaled back on that to keep the focus mostly on the accessibility issue. The wrapping divs around the <legend> are removed, but further testing still needs to be done to make sure that the styling is acceptable.

Testing done

Local

Screenshots

Acceptance criteria

  • [ ] <legend> tags are not wrapped inside of a <div>

Definition of done

  • [ ] Events are logged appropriately
  • [ ] Documentation has been updated, if applicable
  • [ ] A link has been provided to the originating GitHub issue (or connected to it via ZenHub)
  • [ ] No sensitive information (i.e. PII/credentials/internal URLs/etc.) is captured in logging, hardcoded, or specs
+32 -60

0 comment

1 changed file

pr created time in a month

push eventdepartment-of-veterans-affairs/vets-website

Brooks Johnson

commit sha a4c9359a1ba633a871f711c905b0d72385c57d61

Remove wrapping divs Still need to consider the styling

view details

push time in a month

create barnchdepartment-of-veterans-affairs/vets-website

branch : 767-axe-refactor

created branch time in a month

issue commentdepartment-of-veterans-affairs/va.gov-team

[SCREENREADER]: Legends must be first child element of fieldesets for tabbing navigation

This particular problem (and likely others) can be traced to the <ObjectField> component being used with top level <div> tags inside of a <fieldset>:

https://github.com/department-of-veterans-affairs/vets-website/blob/20a303ad06309ccf5f41022c54d341cc60671edc/src/platform/forms-system/src/js/fields/ObjectField.jsx#L228-L231

https://github.com/department-of-veterans-affairs/vets-website/blob/20a303ad06309ccf5f41022c54d341cc60671edc/src/platform/forms-system/src/js/fields/ObjectField.jsx#L293-L295

1Copenut

comment created time in a month

issue commentdepartment-of-veterans-affairs/va.gov-team

[SCREENREADER]: Legends must be first child element of fieldesets for tabbing navigation

I've confirmed this markup structure happening on the Demographic Information part of the "Apply for health care" form.

image

The rendered page:

image

1Copenut

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

7488 e2e tests 5

 function expectNavigateAwayFrom(client, urlSubstring) {     .before(Timeouts.slow); } +function expectElementNotPresent(client, elementSelector) {+  client.expect.element(elementSelector).to.not.be.present;+}+

I'm not seeing this used anywhere - is it necessary?

cohnjesse

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

Webpack build option to generate landing pages

 module.exports = env => {         fileName: 'file-manifest.json',       }),     );-  } else {+  }++  // Optionally generate landing pages in the absence of a content build.+  if (buildOptions.scaffold) {     const landingPagePath = rootUrl =>       path.join(outputPath, '../', rootUrl, 'index.html'); +    const inlineScripts = [+      'incompatible-browser.js',+      'record-event.js',+      'static-page-widgets.js',+    ].reduce(+      (scripts, filename) => ({+        ...scripts,+        [filename]: fs.readFileSync(path.join('src/site/assets/js', filename)),+      }),+      {},+    );++    // Modifies the style tags output from HTML Webpack Plugin.+    const modifyStyleTags = pluginStyleTags =>+      pluginStyleTags+        .reduce(+          (tags, tag) =>+            // Puts style.css before the app-specific stylesheet.+            tag.attributes.href.match(/style/)+              ? [tag, ...tags]+              : [...tags, tag],+          [],+        )+        .join('');++    // Modifies the script tags output from HTML Webpack Plugin.+    const modifyScriptTags = pluginScriptTags =>+      pluginScriptTags+        .reduce((tags, tag) => {+          // Exclude style.entry.js, which gets included with the style chunk.+          if (tag.attributes.src.match(/style/)) return tags;++          // Force polyfills.entry.js to be first (and set `nomodules`), since+          // vendor.entry.js gets put first even with chunksSortMode: 'manual'.+          return tag.attributes.src.match(/polyfills/)+            ? [+                { ...tag, attributes: { ...tag.attributes, nomodule: true } },+                ...tags,+              ]+            : [...tags, tag];+        }, [])+        .join('');++    const generateLandingPage = ({+      appName,+      entryName = 'static-pages',+      loadingMessage = 'Please wait while we load the application for you.',+      rootUrl,+    }) =>+      new HtmlPlugin({+        chunks: ['polyfills', 'vendor', 'style', entryName],+        filename: landingPagePath(rootUrl),+        inject: false,+        scriptLoading: 'defer',+        template: 'src/platform/landing-pages/dev-template.ejs',+        templateParameters: {+          entryName,+          headerFooterData, // TODO: Get this placeholder data from another file+          inlineScripts,+          loadingMessage,+          modifyScriptTags,+          modifyStyleTags,+        },+        title: appName ? `${appName} | VA.gov` : 'VA.gov',+      });+     baseConfig.plugins = baseConfig.plugins.concat(       getAppManifests()-        .filter(manifest => manifest.rootUrl)-        // Only create a new landing page if one doesn't already exist from a-        // previous build. This is useful for using the content build page for-        // testing.-        .filter(manifest => !fs.existsSync(landingPagePath(manifest.rootUrl)))-        .map(-          manifest =>-            new HtmlWebpackPlugin({-              filename: landingPagePath(manifest.rootUrl),-              template:-                manifest.landingPageDevTemplate ||-                'src/platform/landing-pages/dev-template.ejs',-              // Pass data to the tempates-              templateParameters: {-                // Everything from the manifest file-                ...manifest,-                // With some defaults-                loadingMessage:-                  manifest.loadingMessage ||-                  'Please wait while we load the application for you.',-                entryName: manifest.entryName || 'static-pages',-                // TODO: Get this placeholder data from another file-                headerFooterData,-              },-              // Don't inject all the assets into all the landing pages-              // The assets we want are referenced in the template itself-              inject: false,-            }),-        ),+        .filter(({ rootUrl }) => rootUrl)+        .map(generateLandingPage),+    );++    baseConfig.plugins.push(+      new CopyPlugin({+        patterns: [+          {+            from: 'src/site/assets/img',+            to: path.join(outputPath, '..', 'img'),+          },+        ],+      }),

Are you saying that images aren't loading somehow?

U-DON

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

#10267 Continue button MUST give meaningful feedback during transitions

 import React from 'react';  export default function LoadingButton({   isLoading,+  loadingText,   children,   onClick,   disabled,   ...props }) {-  const contents = isLoading ? (-    <i className="fa fa-spinner fa-spin" />-  ) : (-    children-  );+  let contents;+  if (loadingText) {+    contents = isLoading ? (+      <>+        <i+          className="fa fa-spinner fa-spin"+          aria-hidden="true"+          role="presentation"+        />+        <span className="sr-only" role="status">+          {loadingText}+        </span>+      </>+    ) : (+      children+    );+  } else {+    contents = isLoading ? (+      <i+        className="fa fa-spinner fa-spin"+        aria-hidden="true"+        role="presentation"+      />+    ) : (+      children+    );+  }

Would this be possible instead? I feel like it is a bit simpler:

  const contents = isLoading ? (
    <>
      <i
        className="fa fa-spinner fa-spin"
        aria-hidden="true"
        role="presentation"
      />
      {loadingText && (
        <span className="sr-only" role="status">
          {loadingText}
        </span>
      )}
    </>
  ) : (
    children
  );
vbahinwillit

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

Webpack build option to generate landing pages

 module.exports = env => {         fileName: 'file-manifest.json',       }),     );-  } else {+  }++  // Optionally generate landing pages in the absence of a content build.+  if (buildOptions.scaffold) {     const landingPagePath = rootUrl =>       path.join(outputPath, '../', rootUrl, 'index.html'); +    const inlineScripts = [+      'incompatible-browser.js',+      'record-event.js',+      'static-page-widgets.js',+    ].reduce(+      (scripts, filename) => ({+        ...scripts,+        [filename]: fs.readFileSync(path.join('src/site/assets/js', filename)),+      }),+      {},+    );++    // Modifies the style tags output from HTML Webpack Plugin.+    const modifyStyleTags = pluginStyleTags =>+      pluginStyleTags+        .reduce(+          (tags, tag) =>+            // Puts style.css before the app-specific stylesheet.+            tag.attributes.href.match(/style/)+              ? [tag, ...tags]+              : [...tags, tag],+          [],+        )+        .join('');

It isn't clear to me why we're doing this, and additionally it seems less like we're modifying the tags and more like we're reordering them.

U-DON

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

#10267 Continue button MUST give meaningful feedback during transitions

 import React from 'react';  export default function LoadingButton({   isLoading,+  loadingText,   children,   onClick,   disabled,   ...props }) {-  const contents = isLoading ? (-    <i className="fa fa-spinner fa-spin" />-  ) : (-    children-  );+  let contents;+  if (loadingText) {+    contents = isLoading ? (+      <>+        <i+          className="fa fa-spinner fa-spin"+          aria-hidden="true"+          role="presentation"+        />+        <span className="sr-only" role="status">+          {loadingText}+        </span>+      </>+    ) : (+      children+    );+  } else {+    contents = isLoading ? <i className="fa fa-spinner fa-spin" /> : children;

This icon doesn't have aria-hidden="true" which could be problematic.

vbahinwillit

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

#10267 Continue button MUST give meaningful feedback during transitions

 import React from 'react';  export default function LoadingButton({   isLoading,+  loadingText,   children,   onClick,   disabled,   ...props }) {-  const contents = isLoading ? (-    <i className="fa fa-spinner fa-spin" />-  ) : (-    children-  );+  let contents;+  if (loadingText) {+    contents = isLoading ? (+      <>+        <i

At a glance it looks like this icon meets the expectations for FontAwesome accessibility

vbahinwillit

comment created time in a month

pull request commentdepartment-of-veterans-affairs/vets-website

10316 vre chp31 form chapters

Is there a person or team that can give this a peer review?

micahchiang

comment created time in a month

issue openeddepartment-of-veterans-affairs/va.gov-team

Document the public assets S3 bucketand the regular deployment bucket

Issue Description

For each environment in vets-website, we deploy to two S3 buckets. One is designated an "assets" bucket, and the other just seems to be a catch-all bucket which currently contains the output of both the content and the application builds.

In addition to the S3 bucket that holds the build outputs of the content and the webpack builds, we also have another bucket which holds just the app assets (no content).

  • prod-va-gov-assets
  • staging-va-gov-assets
  • dev-va-gov-assets

The purpose of the different buckets isn't very clear.


Tasks

  • [ ] Investigate & document the existence of each S3 bucket

Acceptance Criteria

  • [ ] A document exists describing why the buckets exist and how each one fits in with the website

created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

Field transformers

+const path = require('path');+const _ = require('lodash');+const chalk = require('chalk');++const {+  getContentModelType,+  getAllImportsFrom,+  readEntity,+} = require('./helpers');+const { fieldTransformers, serialize } = require('./field-transformers');++const transformers = getAllImportsFrom(+  path.resolve(__dirname, 'field-transformers'),+);++const inputSchemas = getAllImportsFrom(path.resolve(__dirname, 'schemas/raw'));++const outputSchemas = getAllImportsFrom(+  path.resolve(__dirname, 'schemas/transformed'),+);++// These will change if we can replace the manual JSON schema creation process+const getInputSchema = entity => inputSchemas[getContentModelType(entity)];+const getOutputSchema = entity => outputSchemas[getContentModelType(entity)];++/**+ * Identify whether the entity property is an entity reference.+ *+ * Assumes that if the first item in the array is an entity reference, they all+ * will be.+ * @param {Object} prop - The entity property to check+ * @returns {boolean} - True if the property is an entity reference+ */+const isEntityReferenceArray = prop =>+  Array.isArray(prop) && prop[0] && prop[0].target_type && prop[0].target_uuid;++/**+ * @param {Object} entity - The raw entity+ * @param {Object} [outputSchemaFromParent] - The schema defining what the+ *                 output should look like. If undefined, this will use the+ *                 transformed schema for the content model type. This is meant+ *                 to be passed for a child entity from the parent's schema,+ *                 specifying only the fields the parent needs.+ */+function transformFields(entity, outputSchemaFromParent) {+  // console.log(JSON.stringify(entity, null, 2));+  // throw new Error('stopping');++  const inputSchema = getInputSchema(entity);+  if (!inputSchema) {+    throw new Error(+      `Could not find input schema for ${getContentModelType(entity)}`,+    );+  }++  const outputSchema = outputSchemaFromParent || getOutputSchema(entity);+  if (!outputSchema) {+    // eslint-disable-next-line no-console+    console.log(`No output schema found for ${getContentModelType(entity)}`);+    return entity;+  }++  // Iterate over each field:+  return Object.entries(outputSchema.properties).reduce(+    /* eslint-disable no-param-reassign */+    /* eslint-disable no-console */+    (result, [outputKey, outputFieldSchema]) => {+      // Find the snake_case key for use in the input schema and entity data+      const inputKey = _.snakeCase(outputKey);++      // If the input schema is an entity reference, find the entity reference data and recurse+      if (isEntityReferenceArray(entity[inputKey])) {+        console.log(+          chalk.gray(`Expanding ${outputKey} (${getContentModelType(entity)})`),+        );+        result[outputKey] = entity[inputKey].map(ref => {+          const childEntity = readEntity(+            path.resolve(+              __dirname,+              '../../../../../.cache/localhost/cms-export-content',+            ),+            ref.target_type,+            ref.target_uuid,+          );+          return transformFields(childEntity, outputFieldSchema);+        });++        if (+          result[outputKey].length > 1 &&+          outputFieldSchema.type !== 'array'+        ) {+          // eslint-disable-next-line no-console+          console.error(+            chalk.red(+              `Multiple entity references found at ${inputKey} on ${getContentModelType(+                entity,+              )}, but the output schema for ${outputKey} expects a single object.`,+            ),+          );+        } else if (outputFieldSchema.type === 'object') {+          result[outputKey] = result[outputKey][0];+        }+        return result;+      }++      // TODO: If the content model has a transformer hook for that field, use it++      // Find the input schema transformers+      const inputTransformerMap = fieldTransformers.get(+        serialize(inputSchema.properties[inputKey]),+      );+      if (!inputTransformerMap) {+        console.warn(+          chalk.yellow(+            `Could not find transformer map for ${inputKey} (${getContentModelType(+              entity,+            )})`,+          ),+        );+        result[outputKey] = entity[inputKey];+        return result;+      }++      // Find the specific field transformer+      const transformField = inputTransformerMap.get(+        serialize(outputSchema.properties[outputKey]),+      );

I don't quite understand the situation where that inner Map has multiple mappings that we care about.

cvalarida

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

Field transformers

+// TODO: Move this to field-transformers/getDrupalValue.js once we replace the+// content model transformers with these field transformers.+const { getDrupalValue } = require('../transformers/helpers');++/**+ * Reorders object properties for consistency. Returns all other types+ * unmodified.+ * @param {*} thing - The variable to normalize+ * @returns {*} Whatever type thing is+ */+const normalize = thing => {+  if (typeof thing !== 'object' || thing === null) {+    return thing;+  }++  // Alphabetize fields+  return Object.keys(thing)+    .sort()+    .reduce((res, currentKey) => {+      res[currentKey] = thing[currentKey];+      return res;+    }, {});+};++/**+ * Normalizes and stringifies a variable.+ *+ * For objects, normalization means alphabetizing the properties so two+ * otherwise-equal objects can be stringified and compared to each other even if+ * the properties are in a different order.+ * @param {*} thing - A variable to normalize and stringify+ * @returns {String}+ */+const serialize = thing => JSON.stringify(normalize(thing), null, 2);++/**+ * Maps a transformer to an input and output schema for an individual field.+ *+ * TODO: Make this less annoying for enums. This may mean removing enums+ * recursively in normalize(), but that seems maybe too specific? Not sure what+ * else we may need to do. Probably reasonable for a prototype, though.+ */+const fieldTransformers = new Map([+  [+    // Input schema: Data from Drupal looks like this+    serialize({ $ref: 'GenericNestedString' }),+    new Map([+      // Output schema: Data in the templates look like this+      [serialize({ type: 'string' }), getDrupalValue],+    ]),+  ],+]);

It isn't immediately obvious why we have a map within a map. Can that be made clearer? I get the idea of "if we have a GenericNestedString then we want to use getDrupalValue to transform it"

cvalarida

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

Field transformers

 const entityAssemblerFactory = contentDir => {    *                    with the body of the referenced entities.    */   const assembleEntityTree = (entity, ancestors = [], parentFieldName = '') => {+    // Use the automatic transformer process for certain content models+    // This is a test. Eventually,

I'm guessing that eventually the transformFields will be the default and only way that we do this?

cvalarida

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

Field transformers

+const path = require('path');+const _ = require('lodash');+const chalk = require('chalk');++const {+  getContentModelType,+  getAllImportsFrom,+  readEntity,+} = require('./helpers');+const { fieldTransformers, serialize } = require('./field-transformers');++const transformers = getAllImportsFrom(+  path.resolve(__dirname, 'field-transformers'),+);++const inputSchemas = getAllImportsFrom(path.resolve(__dirname, 'schemas/raw'));++const outputSchemas = getAllImportsFrom(+  path.resolve(__dirname, 'schemas/transformed'),+);++// These will change if we can replace the manual JSON schema creation process+const getInputSchema = entity => inputSchemas[getContentModelType(entity)];+const getOutputSchema = entity => outputSchemas[getContentModelType(entity)];++/**+ * Identify whether the entity property is an entity reference.+ *+ * Assumes that if the first item in the array is an entity reference, they all+ * will be.+ * @param {Object} prop - The entity property to check+ * @returns {boolean} - True if the property is an entity reference+ */+const isEntityReferenceArray = prop =>+  Array.isArray(prop) && prop[0] && prop[0].target_type && prop[0].target_uuid;++/**+ * @param {Object} entity - The raw entity+ * @param {Object} [outputSchemaFromParent] - The schema defining what the+ *                 output should look like. If undefined, this will use the+ *                 transformed schema for the content model type. This is meant+ *                 to be passed for a child entity from the parent's schema,+ *                 specifying only the fields the parent needs.+ */+function transformFields(entity, outputSchemaFromParent) {+  // console.log(JSON.stringify(entity, null, 2));+  // throw new Error('stopping');

Are these useful?

cvalarida

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

Field transformers

+// TODO: Move this to field-transformers/getDrupalValue.js once we replace the+// content model transformers with these field transformers.+const { getDrupalValue } = require('../transformers/helpers');++/**+ * Reorders object properties for consistency. Returns all other types+ * unmodified.+ * @param {*} thing - The variable to normalize+ * @returns {*} Whatever type thing is+ */+const normalize = thing => {+  if (typeof thing !== 'object' || thing === null) {+    return thing;+  }++  // Alphabetize fields+  return Object.keys(thing)+    .sort()+    .reduce((res, currentKey) => {+      res[currentKey] = thing[currentKey];+      return res;+    }, {});+};++/**+ * Normalizes and stringifies a variable.+ *+ * For objects, normalization means alphabetizing the properties so two+ * otherwise-equal objects can be stringified and compared to each other even if+ * the properties are in a different order.+ * @param {*} thing - A variable to normalize and stringify+ * @returns {String}+ */+const serialize = thing => JSON.stringify(normalize(thing), null, 2);++/**+ * Maps a transformer to an input and output schema for an individual field.+ *+ * TODO: Make this less annoying for enums. This may mean removing enums+ * recursively in normalize(), but that seems maybe too specific? Not sure what+ * else we may need to do. Probably reasonable for a prototype, though.+ */+const fieldTransformers = new Map([+  [+    // Input schema: Data from Drupal looks like this+    serialize({ $ref: 'GenericNestedString' }),+    new Map([+      // Output schema: Data in the templates look like this+      [serialize({ type: 'string' }), getDrupalValue],+    ]),+  ],+]);++module.exports = { fieldTransformers, normalize, serialize };

I might have overlooked something, but we might not need to export normalize.

cvalarida

comment created time in a month

Pull request review commentdepartment-of-veterans-affairs/vets-website

Add video instructions and update show more UI

+import React from 'react';+import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';++export default function AdditionalInfoRow({+  onClick,+  id,+  triggerText,+  open,+  children,+}) {+  return (+    <>+      <button+        className="va-button-link additional-info-button vads-u-margin-right--4"+        id={`${id}-vaos-info-expand`}+        aria-controls={`${id}-vaos-info-content`}+        aria-expanded={open ? 'true' : 'false'}+        onClick={onClick}+      >+        <span className="additional-info-title">{triggerText}</span>+        <i className={`fas fa-angle-down ${open ? 'open' : ''}`} />

Should there have been an aria-hidden="true" here?

jbalboni

comment created time in 2 months

Pull request review commentdepartment-of-veterans-affairs/vets-website

Process cms exports refactor

 const entityAssemblerFactory = contentDir => {    */   const assembleEntityTree = (entity, ancestors = [], parentFieldName = '') => {     // Handle circular references-    const ancestorIds = ancestors.map(a => a.id);-    const a = ancestors.find(r => r.id === toId(entity));-    if (a) {-      /* eslint-disable no-console */-      // This logging is to help debug if AJV fails on an unexpected circular-      // reference-      console.log(`I'm my own grandpa! (${toId(entity)})`);-      console.log(`  Parents:\n    ${ancestorIds.join('\n    ')}`);-      /* eslint-enable no-console */--      // NOTE: If we find a circular reference, it needs to be addressed in the-      // transformer and accounted for in the transformed schema.-      //-      // If it isn't handled in the transformer, the post-transformation-      // validation will fail because of a circular reference (AJV will throw-      // up).-      //-      // If the modified child isn't accounted for in the transformed schema, it-      // won't be valid (assuming we've omited a normally-required property to-      // avoid the circular reference).-      return a;-    }+    const a = findCircularReference(entity, ancestors);+    if (a) return a; -    // Pre-transformation JSON schema validation-    const rawErrors = validateRawEntity(entity);-    if (rawErrors.length) {-      /* eslint-disable no-console */-      console.warn(-        chalk.yellow(-          `${toId(entity)} (${getContentModelType(-            entity,-          )}) is invalid before transformation:`,-        ),-      );-      console.warn(`${rawErrors.map(e => JSON.stringify(e, null, 2))}`);-      rawErrors.forEach(e => {-        console.warn(-          chalk.yellow(`Data found at ${e.dataPath}:`),-          JSON.stringify(get(entity, e.dataPath.slice(1))),-        );-      });-      console.warn(`-------------------`);-      /* eslint-enable no-console */--      // Abort! (We may want to change this later)-      throw new Error(`${toId(entity)} is invalid before transformation`);-    }+    validateInput(entity);      const filteredEntity = getFilteredEntity(entity); -    // Recursively expand entity references-    for (const [key, prop] of Object.entries(filteredEntity)) {-      // Properties with target_uuids are always arrays from tome-sync-      if (Array.isArray(prop)) {-        prop.forEach((item, index) => {-          const { target_uuid: targetUuid, target_type: targetType } = item;--          // We found a reference! Override it with the expanded entity.-          if (targetUuid && targetType) {-            filteredEntity[key][index] = assembleEntityTree(-              readEntity(contentDir, targetType, targetUuid),-              ancestors.concat([{ id: toId(entity), entity }]),

Ah, I bet if I took a closer look I might find that filteredEntity is just an alias for entity. :shrug:

cvalarida

comment created time in 2 months

Pull request review commentdepartment-of-veterans-affairs/vets-website

Process cms exports refactor

 const {   validateTransformedEntity, } = require('./schema-validation'); +/**+ * An ancestor for an entity.+ * @typedef {Object} Ancestor+ * @property {string} id - The toId()'d string for the ancestor+ * @property {Object} entity - The actual ancestor entity+ */++/**+ * @param {Object} entity - The current entity+ * @param {Ancestor[]} ancestors - A list of all ancestors+ * @return {Object|bool} If the current entity is a circular reference, return the original+ * If the current entity is not a circular reference, return false+ */+const findCircularReference = (entity, ancestors) => {+  const ancestorIds = ancestors.map(a => a.id);+  const a = ancestors.find(r => r.id === toId(entity));+  if (a) {+    /* eslint-disable no-console */+    // This logging is to help debug if AJV fails on an unexpected circular+    // reference+    console.log(`I'm my own grandpa! (${toId(entity)})`);+    console.log(`  Parents:\n    ${ancestorIds.join('\n    ')}`);+    /* eslint-enable no-console */++    // NOTE: If we find a circular reference, it needs to be addressed in the+    // transformer and accounted for in the transformed schema.+    //+    // If it isn't handled in the transformer, the post-transformation+    // validation will fail because of a circular reference (AJV will throw+    // up).+    //+    // If the modified child isn't accounted for in the transformed schema, it+    // won't be valid (assuming we've omited a normally-required property to+    // avoid the circular reference).+    return a;+  }+  return false;+};++/**+ * @param {Object} entity - The entity we're validating+ * @throws {Error} If the entity is invalid+ */+const validateInput = entity => {+  // Pre-transformation JSON schema validation+  const rawErrors = validateRawEntity(entity);+  if (rawErrors.length) {+    /* eslint-disable no-console */+    console.warn(+      chalk.yellow(+        `${toId(entity)} (${getContentModelType(+          entity,+        )}) is invalid before transformation:`,+      ),+    );+    console.warn(`${rawErrors.map(e => JSON.stringify(e, null, 2))}`);+    rawErrors.forEach(e => {+      console.warn(+        chalk.yellow(`Data found at ${e.dataPath}:`),+        JSON.stringify(get(entity, e.dataPath.slice(1))),+      );+    });+    console.warn(`-------------------`);+    /* eslint-enable no-console */++    // Abort! (We may want to change this later)+    throw new Error(`${toId(entity)} is invalid before transformation`);+  }+};++/**+ * @param {Object} transformedEntity - The entity after transformation+ * @throws {Error} If the entity is invalid+ */+const validateOutput = (entity, transformedEntity) => {+  const transformedErrors = validateTransformedEntity(transformedEntity);+  if (transformedErrors.length) {+    /* eslint-disable no-console */+    console.warn(+      chalk.yellow(+        `${toId(entity)} (${getContentModelType(+          entity,+        )}) is invalid after transformation:`,+      ),+    );+    console.warn(`${transformedErrors.map(e => JSON.stringify(e, null, 2))}`);+    transformedErrors.forEach(e => {+      console.warn(+        chalk.yellow(`Data found at ${e.dataPath}:`),+        JSON.stringify(get(transformedEntity, e.dataPath.slice(1))),+      );+    });+    console.warn(`-------------------`);+    /* eslint-enable no-console */++    // Abort! (We may want to change this later)+    throw new Error(`${toId(entity)} is invalid after transformation`);+  }+};+ const entityAssemblerFactory = contentDir => {+  /**+   * @param {Object} entity - The entity with entity references+   * @param {Ancestor[]} ancestors - A list of all ancestors+   * @param {function} assembleTree - The assembleEntityTree closure; defined as+   *                                  a parameter here because eslint didn't+   *                                  like using it before it was defined+   * @return {Object} The entity with the references filled in+   */+  const expandEntityReferences = (entity, ancestors, assembleTree) => {+    const filteredEntity = getFilteredEntity(entity);++    // Recursively expand entity references+    for (const [key, prop] of Object.entries(filteredEntity)) {+      // Properties with target_uuids are always arrays from tome-sync+      if (Array.isArray(prop)) {+        prop.forEach((item, index) => {+          const { target_uuid: targetUuid, target_type: targetType } = item;++          // We found a reference! Override it with the expanded entity.+          if (targetUuid && targetType) {+            filteredEntity[key][index] = assembleTree(+              readEntity(contentDir, targetType, targetUuid),+              ancestors.concat([{ id: toId(entity), entity }]),

But the arg that we use here has already been filtered. Is that a problem?

cvalarida

comment created time in 2 months

Pull request review commentdepartment-of-veterans-affairs/vets-website

Process cms exports refactor

 const {   validateTransformedEntity, } = require('./schema-validation'); +/**+ * An ancestor for an entity.+ * @typedef {Object} Ancestor+ * @property {string} id - The toId()'d string for the ancestor+ * @property {Object} entity - The actual ancestor entity+ */++/**+ * @param {Object} entity - The current entity+ * @param {Ancestor[]} ancestors - A list of all ancestors+ * @return {Object|bool} If the current entity is a circular reference, return the original+ * If the current entity is not a circular reference, return false+ */+const findCircularReference = (entity, ancestors) => {+  const ancestorIds = ancestors.map(a => a.id);+  const a = ancestors.find(r => r.id === toId(entity));+  if (a) {+    /* eslint-disable no-console */+    // This logging is to help debug if AJV fails on an unexpected circular+    // reference+    console.log(`I'm my own grandpa! (${toId(entity)})`);+    console.log(`  Parents:\n    ${ancestorIds.join('\n    ')}`);+    /* eslint-enable no-console */++    // NOTE: If we find a circular reference, it needs to be addressed in the+    // transformer and accounted for in the transformed schema.+    //+    // If it isn't handled in the transformer, the post-transformation+    // validation will fail because of a circular reference (AJV will throw+    // up).+    //+    // If the modified child isn't accounted for in the transformed schema, it+    // won't be valid (assuming we've omited a normally-required property to+    // avoid the circular reference).+    return a;+  }+  return false;+};++/**+ * @param {Object} entity - The entity we're validating+ * @throws {Error} If the entity is invalid+ */+const validateInput = entity => {+  // Pre-transformation JSON schema validation+  const rawErrors = validateRawEntity(entity);+  if (rawErrors.length) {+    /* eslint-disable no-console */+    console.warn(+      chalk.yellow(+        `${toId(entity)} (${getContentModelType(+          entity,+        )}) is invalid before transformation:`,+      ),+    );+    console.warn(`${rawErrors.map(e => JSON.stringify(e, null, 2))}`);+    rawErrors.forEach(e => {+      console.warn(+        chalk.yellow(`Data found at ${e.dataPath}:`),+        JSON.stringify(get(entity, e.dataPath.slice(1))),+      );+    });+    console.warn(`-------------------`);+    /* eslint-enable no-console */++    // Abort! (We may want to change this later)+    throw new Error(`${toId(entity)} is invalid before transformation`);+  }+};++/**+ * @param {Object} transformedEntity - The entity after transformation+ * @throws {Error} If the entity is invalid+ */+const validateOutput = (entity, transformedEntity) => {+  const transformedErrors = validateTransformedEntity(transformedEntity);+  if (transformedErrors.length) {+    /* eslint-disable no-console */+    console.warn(+      chalk.yellow(+        `${toId(entity)} (${getContentModelType(+          entity,+        )}) is invalid after transformation:`,+      ),+    );+    console.warn(`${transformedErrors.map(e => JSON.stringify(e, null, 2))}`);+    transformedErrors.forEach(e => {+      console.warn(+        chalk.yellow(`Data found at ${e.dataPath}:`),+        JSON.stringify(get(transformedEntity, e.dataPath.slice(1))),+      );+    });+    console.warn(`-------------------`);+    /* eslint-enable no-console */++    // Abort! (We may want to change this later)+    throw new Error(`${toId(entity)} is invalid after transformation`);+  }+};+ const entityAssemblerFactory = contentDir => {+  /**+   * @param {Object} entity - The entity with entity references+   * @param {Ancestor[]} ancestors - A list of all ancestors+   * @param {function} assembleTree - The assembleEntityTree closure; defined as+   *                                  a parameter here because eslint didn't+   *                                  like using it before it was defined+   * @return {Object} The entity with the references filled in+   */+  const expandEntityReferences = (entity, ancestors, assembleTree) => {+    const filteredEntity = getFilteredEntity(entity);

And then it looks like we filter it again. Do we need to getFilteredEntity here?

cvalarida

comment created time in 2 months

Pull request review commentdepartment-of-veterans-affairs/vets-website

Process cms exports refactor

 const entityAssemblerFactory = contentDir => {    */   const assembleEntityTree = (entity, ancestors = [], parentFieldName = '') => {     // Handle circular references-    const ancestorIds = ancestors.map(a => a.id);-    const a = ancestors.find(r => r.id === toId(entity));-    if (a) {-      /* eslint-disable no-console */-      // This logging is to help debug if AJV fails on an unexpected circular-      // reference-      console.log(`I'm my own grandpa! (${toId(entity)})`);-      console.log(`  Parents:\n    ${ancestorIds.join('\n    ')}`);-      /* eslint-enable no-console */--      // NOTE: If we find a circular reference, it needs to be addressed in the-      // transformer and accounted for in the transformed schema.-      //-      // If it isn't handled in the transformer, the post-transformation-      // validation will fail because of a circular reference (AJV will throw-      // up).-      //-      // If the modified child isn't accounted for in the transformed schema, it-      // won't be valid (assuming we've omited a normally-required property to-      // avoid the circular reference).-      return a;-    }+    const a = findCircularReference(entity, ancestors);+    if (a) return a; -    // Pre-transformation JSON schema validation-    const rawErrors = validateRawEntity(entity);-    if (rawErrors.length) {-      /* eslint-disable no-console */-      console.warn(-        chalk.yellow(-          `${toId(entity)} (${getContentModelType(-            entity,-          )}) is invalid before transformation:`,-        ),-      );-      console.warn(`${rawErrors.map(e => JSON.stringify(e, null, 2))}`);-      rawErrors.forEach(e => {-        console.warn(-          chalk.yellow(`Data found at ${e.dataPath}:`),-          JSON.stringify(get(entity, e.dataPath.slice(1))),-        );-      });-      console.warn(`-------------------`);-      /* eslint-enable no-console */--      // Abort! (We may want to change this later)-      throw new Error(`${toId(entity)} is invalid before transformation`);-    }+    validateInput(entity);      const filteredEntity = getFilteredEntity(entity); -    // Recursively expand entity references-    for (const [key, prop] of Object.entries(filteredEntity)) {-      // Properties with target_uuids are always arrays from tome-sync-      if (Array.isArray(prop)) {-        prop.forEach((item, index) => {-          const { target_uuid: targetUuid, target_type: targetType } = item;--          // We found a reference! Override it with the expanded entity.-          if (targetUuid && targetType) {-            filteredEntity[key][index] = assembleEntityTree(-              readEntity(contentDir, targetType, targetUuid),-              ancestors.concat([{ id: toId(entity), entity }]),

Here we intentionally use the entity instead of filteredEntity...

cvalarida

comment created time in 2 months

Pull request review commentdepartment-of-veterans-affairs/vets-website

Process cms exports refactor

 const {   validateTransformedEntity, } = require('./schema-validation'); +/**+ * An ancestor for an entity.+ * @typedef {Object} Ancestor+ * @property {string} id - The toId()'d string for the ancestor+ * @property {Object} entity - The actual ancestor entity+ */

:thinking: neat

cvalarida

comment created time in 2 months

Pull request review commentdepartment-of-veterans-affairs/vets-website

Process cms exports refactor

 const entityAssemblerFactory = contentDir => {    */   const assembleEntityTree = (entity, ancestors = [], parentFieldName = '') => {     // Handle circular references-    const ancestorIds = ancestors.map(a => a.id);-    const a = ancestors.find(r => r.id === toId(entity));-    if (a) {-      /* eslint-disable no-console */-      // This logging is to help debug if AJV fails on an unexpected circular-      // reference-      console.log(`I'm my own grandpa! (${toId(entity)})`);-      console.log(`  Parents:\n    ${ancestorIds.join('\n    ')}`);-      /* eslint-enable no-console */--      // NOTE: If we find a circular reference, it needs to be addressed in the-      // transformer and accounted for in the transformed schema.-      //-      // If it isn't handled in the transformer, the post-transformation-      // validation will fail because of a circular reference (AJV will throw-      // up).-      //-      // If the modified child isn't accounted for in the transformed schema, it-      // won't be valid (assuming we've omited a normally-required property to-      // avoid the circular reference).-      return a;-    }+    const a = findCircularReference(entity, ancestors);+    if (a) return a; -    // Pre-transformation JSON schema validation-    const rawErrors = validateRawEntity(entity);-    if (rawErrors.length) {-      /* eslint-disable no-console */-      console.warn(-        chalk.yellow(-          `${toId(entity)} (${getContentModelType(-            entity,-          )}) is invalid before transformation:`,-        ),-      );-      console.warn(`${rawErrors.map(e => JSON.stringify(e, null, 2))}`);-      rawErrors.forEach(e => {-        console.warn(-          chalk.yellow(`Data found at ${e.dataPath}:`),-          JSON.stringify(get(entity, e.dataPath.slice(1))),-        );-      });-      console.warn(`-------------------`);-      /* eslint-enable no-console */--      // Abort! (We may want to change this later)-      throw new Error(`${toId(entity)} is invalid before transformation`);-    }+    validateInput(entity);      const filteredEntity = getFilteredEntity(entity); -    // Recursively expand entity references-    for (const [key, prop] of Object.entries(filteredEntity)) {-      // Properties with target_uuids are always arrays from tome-sync-      if (Array.isArray(prop)) {-        prop.forEach((item, index) => {-          const { target_uuid: targetUuid, target_type: targetType } = item;--          // We found a reference! Override it with the expanded entity.-          if (targetUuid && targetType) {-            filteredEntity[key][index] = assembleEntityTree(-              readEntity(contentDir, targetType, targetUuid),-              ancestors.concat([{ id: toId(entity), entity }]),-              key,-            );-          }-        });-      }-    }+    const expandedEntity = expandEntityReferences(+      filteredEntity,

So, we pass filteredEntity as the first argument...

cvalarida

comment created time in 2 months

issue openeddepartment-of-veterans-affairs/va.gov-team

Split reverse proxy configuration up by environment

Issue Description

Our devops repo is set up in a way that the deploy script has its own environment config, and essentially every other config is broken down by environment. The reverse proxy is not the same. We have a different reverse proxy for each environment, but they all use the same nginx config:

Having a config file for each environment where each file uses the include directive to load shared configs would make it easier and less risky to test out changes to the reverse proxy. We could try something out in the dev environment knowing for certain that that configuration wouldn't appear in the prod environment.


Tasks

  • [ ] Have nginx config scripts for each environment
  • [ ] Update the ansible configuration files to point to the new nginx config files

Acceptance Criteria

  • [ ] What will be created or happen as a result of this story?

created time in 2 months

Pull request review commentdepartment-of-veterans-affairs/vets-website

VAVFS-10002: Remove legacy mobile nav button.

 Used to open or close the side bar navigation bar on mobile screens. Must be used in a template with navigation-sidebar.html -{% endcomment %}-{% if buildtype == 'vagovprod' %}   <button type="button" class="va-btn-sidebarnav-trigger vads-u-width--full"     aria-controls="va-detailpage-sidebar">     <span>       <b>More in this section</b>       {% include "src/site/assets/img/arrow-right-white.svg" %}     </span>   </button>+{% endcomment %}

Rather than just comment out the markup in this file, can the file be deleted entirely? I count 25 files where it is included.

Also, I think we can remove this:

https://github.com/department-of-veterans-affairs/vets-website/blob/7db9b1d9b33b92d9c2fa0f46e605be039e6e0c30/src/platform/site-wide/sass/modules/_m-layers.scss#L37-L39

ethanteague

comment created time in 2 months

issue openeddepartment-of-veterans-affairs/va.gov-team

Add thorough testing for the reverse proxy

Issue Description

Right now we are using nginx as a reverse proxy. There is also a testing file that is designed to test some of the redirects, but this doesn't encompass all that the reverse proxy is doing.

Goal

Related to https://github.com/department-of-veterans-affairs/va.gov-team/issues/10001, we plan to make changes to the reverse proxy to account for changing the S3 bucket structure. Before this is done we would like to have testing place to ensure that the server we are proxying to will give us the expected results.


Tasks

  • [ ] Write a node script that will make requests against a list of URLs and ensure that the correct HTTP status is returned (likely 200) and possibly validate that the content in the proxied location matches what we expect
    • This could be as simple as checking to see if the title of the response body matches the expected value for the URL
  • [ ] Have a CI pipeline that runs this script each time a change to the reverse proxy would be made

Acceptance Criteria

  • [ ] What will be created or happen as a result of this story?

created time in 2 months

Pull request review commentdepartment-of-veterans-affairs/vets-website

Metalsmith debug emit to files

 function build(BUILD_OPTIONS) {     'Apply layouts',   ); +  smith.use(+    emitToFiles(+      BUILD_OPTIONS,+      path.resolve(__dirname, '../../../../build/', 'after-layouts'),+      file => file.contents,+    ),+    'Emit contents of files to build/after-layouts',+  );

I think this could get lost in the noise of the dozens of other build steps, and someone new might get confused trying to understand how these files get used or why we care about them.

cvalarida

comment created time in 2 months

Pull request review commentdepartment-of-veterans-affairs/vets-website

Metalsmith debug emit to files

+/* eslint-disable no-console */

:scream:

cvalarida

comment created time in 2 months

pull request commentdepartment-of-veterans-affairs/va.gov-team

Update Content Build Separation design doc

@cvalarida I've made some clarifications in response to your feedback.

bkjohnson

comment created time in 2 months

push eventdepartment-of-veterans-affairs/va.gov-team

Brooks Johnson

commit sha d5e9ee2e3eee121b8474cce94e3a5f4dfca924ac

Remove errant underscore

view details

push time in 2 months

more