From 567e449966c39246a8a38f79ebf9840ce60b0ccf Mon Sep 17 00:00:00 2001 From: Wyatt Pearsall Date: Thu, 23 May 2024 10:04:48 -0400 Subject: [PATCH 1/5] Change how Cypress is invoked in GHA Also, provide a `fast-cypress` npm script to call a similar local command. Cypress tests should now only be invoked when files they test are changed. If this is found incomplete, more files can be defined in the `spec-map.js` file, as needed. --- .github/workflows/functional-tests.yml | 14 + .gitignore | 1 + package.json | 4 +- .../cypress/cypress.template.mjs | 0 test/cypress/dummy.cy.js | 5 + test/cypress/run-specs.sh | 4 + test/cypress/spec-map.js | 249 ++++++++++++++++++ 7 files changed, 276 insertions(+), 1 deletion(-) rename cypress.config.js => test/cypress/cypress.template.mjs (100%) create mode 100644 test/cypress/dummy.cy.js create mode 100755 test/cypress/run-specs.sh create mode 100644 test/cypress/spec-map.js diff --git a/.github/workflows/functional-tests.yml b/.github/workflows/functional-tests.yml index 2d53eb30443..83fd0fe5716 100644 --- a/.github/workflows/functional-tests.yml +++ b/.github/workflows/functional-tests.yml @@ -42,6 +42,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + fetch-depth: 2 - name: Set up Node uses: actions/setup-node@v4 @@ -58,13 +60,25 @@ jobs: python3 -m pip install --upgrade pip python3 -m pip install -r requirements/local.txt + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v44.5.2 + with: + separator: '___' + - name: Set up initial data run: ./refresh-data.sh test.sql.gz + - name: Prepare config + env: + CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} + run: ./test/cypress/run-specs.sh + - name: Run Cypress uses: cypress-io/github-action@v6 with: build: yarn build + config-file: test/cypress/cypress.config.mjs start: python cfgov/manage.py runserver 0.0.0.0:8000 wait-on: 'http://localhost:8000' diff --git a/.gitignore b/.gitignore index d81818bbdfc..4eb11cb2e4c 100755 --- a/.gitignore +++ b/.gitignore @@ -126,6 +126,7 @@ nosetests.xml coverage.xml .snyk test/cypress/screenshots/ +test/cypress/cypress.config.mjs # Temp data backups # ############### diff --git a/package.json b/package.json index 38a659d560c..f90e6af73b9 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,9 @@ "styles": "yarn build styles", "scripts": "yarn build scripts", "watch": "yarn build watch", - "build": "node ./esbuild/build.js" + "build": "node ./esbuild/build.js", + "cypress": "./node_modules/.bin/cypress run --config-file test/cypress/cypress.template.mjs", + "fast-cypress": "./test/cypress/run-specs.sh && ./node_modules/.bin/cypress run --config-file test/cypress/cypress.config.mjs" }, "prettier": { "singleQuote": true diff --git a/cypress.config.js b/test/cypress/cypress.template.mjs similarity index 100% rename from cypress.config.js rename to test/cypress/cypress.template.mjs diff --git a/test/cypress/dummy.cy.js b/test/cypress/dummy.cy.js new file mode 100644 index 00000000000..e2eb8c61129 --- /dev/null +++ b/test/cypress/dummy.cy.js @@ -0,0 +1,5 @@ +describe('Dummy suite', () => { + it('Does not integration tests on uninteresting commits', () => { + expect(true).to.equal(true) + }); +}) diff --git a/test/cypress/run-specs.sh b/test/cypress/run-specs.sh new file mode 100755 index 00000000000..e7258a7699c --- /dev/null +++ b/test/cypress/run-specs.sh @@ -0,0 +1,4 @@ +#!/bin/bash +echo -n "${CHANGED_FILES:-$(git --no-pager diff --name-only origin/main)}" \ + | tr -s "___" "\n" \ + | node "$(git rev-parse --show-toplevel)/test/cypress/spec-map.js" diff --git a/test/cypress/spec-map.js b/test/cypress/spec-map.js new file mode 100644 index 00000000000..4f96fd69b6b --- /dev/null +++ b/test/cypress/spec-map.js @@ -0,0 +1,249 @@ +import path from 'path'; +import { fileURLToPath } from 'url'; +import { readFileSync, writeFileSync } from 'node:fs'; +import * as readline from 'node:readline'; +import { stdin as input, stdout as output } from 'node:process'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const FULL_SUITE = "'test/cypress/integration/**/*.cy.{js,jsx,ts,tsx}'"; + +const rl = readline.createInterface({ input, output, terminal: false }); + +const candidates = []; + +const directories = [ + [ + [ + 'cfgov/unprocessed/apps/filing-instruction-guide', + 'cfgov/filing_instruction_guide', + 'cfgov/unprocessed/js/organisms/SecondaryNav.js', + 'cfgov/unprocessed/css/organisms/secondary-nav.less', + 'cfgov/v1/jinja2/v1/includes/organisms/secondary-nav-fig.html', + ], + 'compliance/small-business-lending', + ], + [[], 'admin'], + [ + ['cfgov/unprocessed/apps/ask-cfpb', 'cfgov/ask_cfpb'], + 'consumer-tools/ask-cfpb', + ], + [ + [ + 'cfgov/unprocessed/apps/retirement', + 'cfgov/retirement_api', + 'cfgov/unprocessed/js/modules/util/format.js', + ], + 'consumer-tools/before-you-claim', + ], + [ + [ + 'cfgov/unprocessed/apps/tccp', + 'cfgov/tccp', + 'cfgov/unprocessed/js/modules/util/web-storage-proxy', + ], + 'consumer-tools/credit-cards', + ], + [ + ['cfgov/unprocessed/apps/financial-well-being', 'cfgov/wellbeing'], + 'consumer-tools/financial-well-being', + ], + [ + [ + 'cfgov/unprocessed/apps/find-a-housing-counselor', + 'cfgov/housing_counselor', + ], + 'consumer-tools/find-a-housing-counselor', + ], + [ + ['cfgov/unprocessed/apps/ask-cfpb', 'cfgov/ask_cfpb'], + 'consumer-tools/obtener-respuestas', + ], + [ + [ + 'cfgov/unprocessed/apps/owning-a-home', + 'cfgov/jinja2/owning-a-home', + 'cfgov/unprocessed/js/modules/util/format.js', + ], + 'consumer-tools/owning-a-home', + ], + [ + [ + 'cfgov/unprocessed/apps/rural-or-underserved-tool', + 'cfgov/jinja2/rural-or-underserved', + ], + 'consumer-tools/rural-or-underserved-tool', + ], + [ + [ + 'cfgov/unprocessed/apps/teachers-digital-platform', + 'cfgov/teachers_digital_platform', + ], + 'consumer-tools/tdp-activity-search', + ], + [ + [ + 'cfgov/unprocessed/js/routes/on-demand/chart.js', + 'cfgov/unprocessed/css/on-demand/chart.less', + 'cfgov/v1/jinja2/v1/includes/organisms/chart.html', + 'cfgov/v1/atomic_elements/organisms.py', + ], + 'components/cct-charts', + ], + [ + [ + 'cfgov/unprocessed/js/routes/on-demand/email-signup.js', + 'cfgov/v1/jinja2/v1/includes/blocks/email-signup.html', + 'cfgov/v1/blocks.py', + ], + 'components/email-signup', + ], + [ + [ + 'cfgov/unprocessed/js/routes/on-demand/filterable-list-controls.js', + 'cfgov/unprocessed/js/organisms/FilterableListControls.js', + 'cfgov/unprocessed/js/modules/util/FormModel.js', + 'cfgov/unprocessed/css/organisms/filterable-list-controls.less', + 'cfgov/v1/jinja2/v1/includes/organisms/filterable-list-controls.html', + 'cfgov/v1/jinja2/v1/includes/organisms/filterable-list-results.html', + 'cfgov/v1/forms.py', + 'cfgov/v1/models/filterable_page.py', + ], + 'components/filterable-lists', + ], + [ + [ + 'cfgov/unprocessed/js/organisms/Footer.js', + 'cfgov/unprocessed/js/modules/footer-button.js', + 'cfgov/unprocessed/css/organisms/footer.less', + 'cfgov/v1/jinja2/v1/includes/organisms/footer.html', + 'cfgov/v1/atomic_elements/organisms.py', + ], + 'components/footer', + ], + [ + [ + 'cfgov/unprocessed/js/organisms/header.js', + 'cfgov/unprocessed/js/organisms/MegaMenu.js', + 'cfgov/unprocessed/js/organisms/MegaMenuDesktop.js', + 'cfgov/unprocessed/js/organisms/MegaMenuMobile.js', + 'cfgov/unprocessed/js/molecules/GlobalSearch.js', + 'cfgov/unprocessed/css/organisms/header.less', + 'cfgov/unprocessed/css/organisms/mega-menu.less', + 'cfgov/unprocessed/css/molecules/global-eyebrow.less', + 'cfgov/unprocessed/css/molecules/global-header-cta.less', + 'cfgov/unprocessed/css/molecules/global-search.less', + 'cfgov/v1/jinja2/v1/includes/organisms/header.html', + 'cfgov/mega_menu/jinja2/mega_menu', + 'cfgov/v1/jinja2/v1/includes/molecules/global-eyebrow.html', + 'cfgov/v1/jinja2/v1/includes/molecules/global-search.html', + 'cfgov/v1/jinja2/v1/includes/molecules/global-header-cta.html', + 'cfgov/v1/atomic_elements/organisms.py', + 'cfgov/v1/atomic_elements/molecules.py', + ], + 'components/header', + ], + [['cfgov/v1/jinja2/v1/layouts/base.html'], 'components/meta'], + [ + [ + 'cfgov/unprocessed/css/organisms/filterable-list-controls.less', + 'cfgov/unprocessed/js/organisms/FilterableListControls.js', + 'cfgov/v1/jinja2/v1/includes/organisms/filterable-list-controls.html', + 'cfgov/v1/models/filterable_page.py', + ], + 'components/multiselect', + ], + [ + ['cfgov/v1/jinja2/v1/includes/molecules/pagination.html'], + 'components/pagination', + ], + [['cfgov/agreements'], 'data-research/credit-card-agreements-search'], + [ + ['cfgov/unprocessed/apps/prepaid-agreements', 'cfgov/prepaid_agreements'], + 'data-research/prepaid-agreements-search', + ], + [ + [ + 'cfgov/unprocessed/js/routes/on-demand/mortgage-performance-trends.js', + 'cfgov/unprocessed/css/on-demand/mortgage-performance-trends.less', + 'cfgov/unprocessed/css/on-demand/chart.less', + 'cfgov/unprocessed/js/organisms/MortgagePerformanceTrends', + 'cfgov/v1/jinja2/v1/includes/organisms/mortgage-chart.html', + 'cfgov/v1/jinja2/v1/includes/organisms/mortgage-map.html', + 'cfgov/v1/atomic_elements/organisms.py', + 'cfgov/data_research/models.py', + ], + 'data-research/mortgage-performance-trends', + ], + [ + [ + 'cfgov/unprocessed/apps/paying-for-college', + 'cfgov/unprocessed/js/organisms/SecondaryNav.js', + 'cfgov/unprocessed/css/organisms/secondary-nav.less', + 'cfgov/paying_for_college', + ], + 'paying-for-college/disclosures', + ], + [ + [ + 'cfgov/unprocessed/apps/paying-for-college', + 'cfgov/unprocessed/js/organisms/SecondaryNav.js', + 'cfgov/unprocessed/css/organisms/secondary-nav.less', + 'cfgov/paying_for_college', + ], + 'paying-for-college/your-financial-path-to-graduation', + ], + [ + ['cfgov/unprocessed/apps/regulations3k', 'cfgov/regulations3k'], + 'rules-policy', + ], + [['test/cypress/spec-map.js', 'requirements/', /^package.json/], 'all'], +]; + +rl.on('line', (file) => { + console.log('File changed:', file); + for (const [dList, candidate] of directories) { + for (const directory of dList) { + if (file.match(directory)) { + candidates.push(candidate); + break; + } + } + if (file.match('test/cypress/integration/' + candidate)) { + candidates.push(candidate); + } + } +}); + +rl.on('close', () => { + const deduped = new Set(candidates); + if (deduped.has('all')) { + console.log('\nChange requires full Cypress suite.'); + rewriteConfig(FULL_SUITE); + } else { + console.log( + '\nChange requires running Cypress tests in the following directories:\n' + + [...deduped].join('\n'), + ); + rewriteConfig( + JSON.stringify( + [...deduped].map((v) => { + return `test/cypress/integration/${v}/*.cy.{js,jsx,ts,tsx}`; + }), + ), + ); + } +}); + +/** + * @param {string} specPattern - The spec pattern(s) to match + */ +function rewriteConfig(specPattern) { + if (specPattern === '[]') specPattern = "'test/cypress/dummy.cy.js'"; + const tmpl = readFileSync(path.join(__dirname, 'cypress.template.mjs'), { + encoding: 'utf8', + }); + const config = tmpl.replace(FULL_SUITE, specPattern); + writeFileSync(path.join(__dirname, 'cypress.config.mjs'), config); +} From 416e2529ff8aeda989b026ffc876254d1490886b Mon Sep 17 00:00:00 2001 From: Wyatt Pearsall Date: Thu, 13 Jun 2024 08:57:19 -0400 Subject: [PATCH 2/5] Add v1 and core python + base.html to 'all' in spec-map --- test/cypress/spec-map.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/cypress/spec-map.js b/test/cypress/spec-map.js index 4f96fd69b6b..06555579347 100644 --- a/test/cypress/spec-map.js +++ b/test/cypress/spec-map.js @@ -198,7 +198,17 @@ const directories = [ ['cfgov/unprocessed/apps/regulations3k', 'cfgov/regulations3k'], 'rules-policy', ], - [['test/cypress/spec-map.js', 'requirements/', /^package.json/], 'all'], + [ + [ + 'test/cypress/spec-map.js', + 'requirements/', + /^package.json/, + /cfgov\/v1\/.*\.py/, + /cfgov\/core\/.*\.py/, + 'cfgov/v1/jinja2/v1/layouts/base.html', + ], + 'all', + ], ]; rl.on('line', (file) => { From 37fe9dc8c2742b3b5014a5079c844dd2ba68ed7c Mon Sep 17 00:00:00 2001 From: Wyatt Pearsall Date: Thu, 13 Jun 2024 09:36:49 -0400 Subject: [PATCH 3/5] sed over tr --- test/cypress/run-specs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cypress/run-specs.sh b/test/cypress/run-specs.sh index e7258a7699c..dc4b76fcc81 100755 --- a/test/cypress/run-specs.sh +++ b/test/cypress/run-specs.sh @@ -1,4 +1,4 @@ #!/bin/bash echo -n "${CHANGED_FILES:-$(git --no-pager diff --name-only origin/main)}" \ - | tr -s "___" "\n" \ + | sed 's/___/\n/' \ | node "$(git rev-parse --show-toplevel)/test/cypress/spec-map.js" From 35d8623fb71d8afd1077c46cb3c903d0d913df4a Mon Sep 17 00:00:00 2001 From: Wyatt Pearsall Date: Thu, 13 Jun 2024 09:42:55 -0400 Subject: [PATCH 4/5] Call component and admin tests on any v1 python changes --- test/cypress/spec-map.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/cypress/spec-map.js b/test/cypress/spec-map.js index 06555579347..89d9aa268e3 100644 --- a/test/cypress/spec-map.js +++ b/test/cypress/spec-map.js @@ -24,7 +24,7 @@ const directories = [ ], 'compliance/small-business-lending', ], - [[], 'admin'], + [[/cfgov\/v1\/.*\.py/], 'admin'], [ ['cfgov/unprocessed/apps/ask-cfpb', 'cfgov/ask_cfpb'], 'consumer-tools/ask-cfpb', @@ -87,7 +87,7 @@ const directories = [ 'cfgov/unprocessed/js/routes/on-demand/chart.js', 'cfgov/unprocessed/css/on-demand/chart.less', 'cfgov/v1/jinja2/v1/includes/organisms/chart.html', - 'cfgov/v1/atomic_elements/organisms.py', + /cfgov\/v1\/.*\.py/, ], 'components/cct-charts', ], @@ -95,7 +95,7 @@ const directories = [ [ 'cfgov/unprocessed/js/routes/on-demand/email-signup.js', 'cfgov/v1/jinja2/v1/includes/blocks/email-signup.html', - 'cfgov/v1/blocks.py', + /cfgov\/v1\/.*\.py/, ], 'components/email-signup', ], @@ -107,8 +107,7 @@ const directories = [ 'cfgov/unprocessed/css/organisms/filterable-list-controls.less', 'cfgov/v1/jinja2/v1/includes/organisms/filterable-list-controls.html', 'cfgov/v1/jinja2/v1/includes/organisms/filterable-list-results.html', - 'cfgov/v1/forms.py', - 'cfgov/v1/models/filterable_page.py', + /cfgov\/v1\/.*\.py/, ], 'components/filterable-lists', ], @@ -118,7 +117,7 @@ const directories = [ 'cfgov/unprocessed/js/modules/footer-button.js', 'cfgov/unprocessed/css/organisms/footer.less', 'cfgov/v1/jinja2/v1/includes/organisms/footer.html', - 'cfgov/v1/atomic_elements/organisms.py', + /cfgov\/v1\/.*\.py/, ], 'components/footer', ], @@ -139,8 +138,7 @@ const directories = [ 'cfgov/v1/jinja2/v1/includes/molecules/global-eyebrow.html', 'cfgov/v1/jinja2/v1/includes/molecules/global-search.html', 'cfgov/v1/jinja2/v1/includes/molecules/global-header-cta.html', - 'cfgov/v1/atomic_elements/organisms.py', - 'cfgov/v1/atomic_elements/molecules.py', + /cfgov\/v1\/.*\.py/, ], 'components/header', ], @@ -150,12 +148,15 @@ const directories = [ 'cfgov/unprocessed/css/organisms/filterable-list-controls.less', 'cfgov/unprocessed/js/organisms/FilterableListControls.js', 'cfgov/v1/jinja2/v1/includes/organisms/filterable-list-controls.html', - 'cfgov/v1/models/filterable_page.py', + /cfgov\/v1\/.*\.py/, ], 'components/multiselect', ], [ - ['cfgov/v1/jinja2/v1/includes/molecules/pagination.html'], + [ + 'cfgov/v1/jinja2/v1/includes/molecules/pagination.html', + /cfgov\/v1\/.*\.py/, + ], 'components/pagination', ], [['cfgov/agreements'], 'data-research/credit-card-agreements-search'], @@ -171,7 +172,7 @@ const directories = [ 'cfgov/unprocessed/js/organisms/MortgagePerformanceTrends', 'cfgov/v1/jinja2/v1/includes/organisms/mortgage-chart.html', 'cfgov/v1/jinja2/v1/includes/organisms/mortgage-map.html', - 'cfgov/v1/atomic_elements/organisms.py', + /cfgov\/v1\/.*\.py/, 'cfgov/data_research/models.py', ], 'data-research/mortgage-performance-trends', @@ -203,7 +204,6 @@ const directories = [ 'test/cypress/spec-map.js', 'requirements/', /^package.json/, - /cfgov\/v1\/.*\.py/, /cfgov\/core\/.*\.py/, 'cfgov/v1/jinja2/v1/layouts/base.html', ], From 58267570d2de5c484d007220bf1855545c881f62 Mon Sep 17 00:00:00 2001 From: Wyatt Pearsall Date: Thu, 13 Jun 2024 12:37:39 -0400 Subject: [PATCH 5/5] global sed --- test/cypress/run-specs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cypress/run-specs.sh b/test/cypress/run-specs.sh index dc4b76fcc81..a6cb19430cf 100755 --- a/test/cypress/run-specs.sh +++ b/test/cypress/run-specs.sh @@ -1,4 +1,4 @@ #!/bin/bash echo -n "${CHANGED_FILES:-$(git --no-pager diff --name-only origin/main)}" \ - | sed 's/___/\n/' \ + | sed 's/___/\n/g' \ | node "$(git rev-parse --show-toplevel)/test/cypress/spec-map.js"