[#2394] Added Jest for JavaScript unit testing.#2418
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdd Jest-based JS unit testing: introduce Jest config and deps, new Changes
Sequence Diagram(s)sequenceDiagram
participant Dev as Developer
participant CI as CI (GitHub Actions / CircleCI)
participant CLI as cli container
participant Yarn as Yarn/Jest
Dev->>CI: push / open PR
CI->>CLI: start job & install deps (composer + yarn) #;< TOOL_JEST
CLI->>Yarn: yarn install --frozen-lockfile
CLI->>Yarn: yarn test
Yarn-->>CI: return test results
CI-->>Dev: status / artifacts
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.vortex/installer/src/Prompts/Handlers/Tools.php (1)
214-214:⚠️ Potential issue | 🔴 CriticalTypo:
'goups'should be'groups'.This typo will cause
processGroup()to always receive an empty array fromgetToolDefinitions(), making group processing ineffective.🐛 Proposed fix
protected function processGroup(string $name): void { - $config = static::getToolDefinitions('goups')[$name]; + $config = static::getToolDefinitions('groups')[$name]; $selected_tools = $this->getResponseAsArray();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.vortex/installer/src/Prompts/Handlers/Tools.php at line 214, There's a typo when fetching tool definitions: change the key passed to static::getToolDefinitions from 'goups' to 'groups' so processGroup() receives the correct definitions; locate the call in Tools.php where $config = static::getToolDefinitions('goups')[$name]; and replace the string with 'groups' to ensure getToolDefinitions($key) returns the intended group data for subsequent processing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.circleci/config.yml:
- Around line 154-156: The CI runs the same "yarn install --frozen-lockfile"
command under both TOOL_ESLINT_STYLELINT and TOOL_JEST markers, causing
duplicate installs; update the config so the docker compose exec ... "yarn
install --frozen-lockfile" line is executed only once by either consolidating
the markers into a single combined marker (e.g., TOOL_NODE or
TOOL_ESLINT_STYLELINT_JEST) or by adding conditional logic to run that install
when any of TOOL_ESLINT_STYLELINT or TOOL_JEST is active; modify the marker
names and/or conditional blocks around the existing docker compose exec command
to reference the new combined marker (or an OR-style condition) so the install
step is deduplicated.
In @.eslintrc.json:
- Around line 64-73: The override currently disables "no-eval" globally for test
files; to minimize scope, remove the "no-eval": "off" entry from the overrides
block and instead add an inline eslint disable comment (//
eslint-disable-next-line no-eval) at the specific eval usage in ys_demo.test.js
(around the eval at line 11); if you prefer to keep the blanket rule, leave
"no-eval": "off" inside the overrides (under "files", "rules") as-is — pick one
approach and update either .eslintrc.json or the specific test file accordingly.
In @.github/workflows/build-test-deploy.yml:
- Around line 134-139: The pipeline runs the same "docker compose exec ... yarn
install --frozen-lockfile" command under both TOOL_ESLINT_STYLELINT and
TOOL_JEST tokens causing duplicate installs; update the workflow to perform a
single install guarded by a consolidated token (e.g., use the existing
frontend_all group or combine conditions) and remove the duplicate block so only
one docker compose exec ... "yarn install --frozen-lockfile" is emitted when
either linting or testing tools are enabled; locate the two occurrences of the
docker compose exec line and replace them with one conditional that references
TOOL_ESLINT_STYLELINT || TOOL_JEST or frontend_all as the gate.
In `@jest.config.js`:
- Around line 7-19: The current discovery only scans the dirs array (initialized
as dirs = ['web/modules/custom']) and pushes found js directories into roots;
update the dirs initialization to include your custom theme path(s) (e.g., add
'web/themes/custom' or other theme directories) so the forEach loop that checks
fs.existsSync(dir) and inspects each name will also discover theme/js folders;
ensure any added theme paths follow the same resolution logic used by the
existing roots population so existing code that references roots continues to
work.
In `@web/modules/custom/ys_demo/js/ys_demo.test.js`:
- Around line 1-12: The test currently reads ys_demo.js and executes it via eval
(see ys_demo.test.js where fs.readFileSync + eval is used and global.Drupal is
set), which hampers source maps, strict mode handling, and coverage; change the
test to load the module without eval—either refactor the module to export its
behavior and require/import it in the test, or use Node's vm module to run the
file in a controlled context that preserves source mapping and isolation; ensure
tests still set global.Drupal and call the module initializer (or imported
function) instead of eval-ing the file content so coverage and debugging work
properly.
- Around line 222-242: Test currently only checks processed class for multiple
counters but not that each counter operates independently; update the test in
ys_demo.test.js to clear localStorage at start, query each block via
document.querySelectorAll('[data-ys-demo-counter]'), find its own button
(data-counter-action="increment") and value span (data-counter-value), simulate
clicking each block's increment button separately and assert that only the
corresponding span text increments (e.g., first block's span becomes "1" after
its click while second remains "0", then vice versa); keep using
Drupal.behaviors.ysDemo.initCounterBlock to initialize and reference the
behavior and DOM attribute selectors to locate elements.
---
Outside diff comments:
In @.vortex/installer/src/Prompts/Handlers/Tools.php:
- Line 214: There's a typo when fetching tool definitions: change the key passed
to static::getToolDefinitions from 'goups' to 'groups' so processGroup()
receives the correct definitions; locate the call in Tools.php where $config =
static::getToolDefinitions('goups')[$name]; and replace the string with 'groups'
to ensure getToolDefinitions($key) returns the intended group data for
subsequent processing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 37e8d514-fa13-448c-8859-02d4a6ca955d
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (13)
.ahoy.yml.circleci/config.yml.eslintrc.json.github/workflows/build-test-deploy.yml.vortex/installer/src/Prompts/Handlers/Tools.php.vortex/installer/tests/Functional/Handlers/ToolsHandlerProcessTest.php.vortex/installer/tests/Unit/Handlers/AbstractHandlerDiscoveryTestCase.php.vortex/installer/tests/Unit/Handlers/ToolsHandlerDiscoveryTest.phpAGENTS.mdjest.config.jspackage.jsonweb/modules/custom/ys_demo/js/ys_demo.jsweb/modules/custom/ys_demo/js/ys_demo.test.js
.circleci/config.yml
Outdated
| #;< TOOL_JEST | ||
| docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" | ||
| #;> TOOL_JEST |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Potential duplicate yarn install when both TOOL_ESLINT_STYLELINT and TOOL_JEST are enabled.
When both tool markers are active, yarn install --frozen-lockfile will execute twice (lines 152 and 155). Since both tools share the same package.json and node_modules, a single install suffices.
Consider consolidating under a single marker (e.g., TOOL_NODE or TOOL_ESLINT_STYLELINT_JEST) or restructuring to avoid redundancy.
♻️ Alternative: use a combined marker or conditional logic
One option is to have a shared frontend/Node marker that covers any Node-based tooling:
- #;< TOOL_ESLINT_STYLELINT
- docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile"
- #;> TOOL_ESLINT_STYLELINT
- #;< TOOL_JEST
- docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile"
- #;> TOOL_JEST
+ #;< TOOL_NODE
+ docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile"
+ #;> TOOL_NODEThis would require corresponding changes in the installer's tool definitions.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.circleci/config.yml around lines 154 - 156, The CI runs the same "yarn
install --frozen-lockfile" command under both TOOL_ESLINT_STYLELINT and
TOOL_JEST markers, causing duplicate installs; update the config so the docker
compose exec ... "yarn install --frozen-lockfile" line is executed only once by
either consolidating the markers into a single combined marker (e.g., TOOL_NODE
or TOOL_ESLINT_STYLELINT_JEST) or by adding conditional logic to run that
install when any of TOOL_ESLINT_STYLELINT or TOOL_JEST is active; modify the
marker names and/or conditional blocks around the existing docker compose exec
command to reference the new combined marker (or an OR-style condition) so the
install step is deduplicated.
| #;< TOOL_ESLINT_STYLELINT | ||
| docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" | ||
| #;> TOOL_ESLINT_STYLELINT | ||
| #;< TOOL_JEST | ||
| docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" | ||
| #;> TOOL_JEST |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Potential duplicate yarn install execution when both ESLint/Stylelint and Jest are enabled.
When both TOOL_ESLINT_STYLELINT and TOOL_JEST tokens are retained, yarn install --frozen-lockfile executes twice. While functionally harmless (second run is a no-op), this adds unnecessary CI time.
Consider consolidating these into a single conditional block or relying on the frontend_all group token from the installer to gate a single install step.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/build-test-deploy.yml around lines 134 - 139, The pipeline
runs the same "docker compose exec ... yarn install --frozen-lockfile" command
under both TOOL_ESLINT_STYLELINT and TOOL_JEST tokens causing duplicate
installs; update the workflow to perform a single install guarded by a
consolidated token (e.g., use the existing frontend_all group or combine
conditions) and remove the duplicate block so only one docker compose exec ...
"yarn install --frozen-lockfile" is emitted when either linting or testing tools
are enabled; locate the two occurrences of the docker compose exec line and
replace them with one conditional that references TOOL_ESLINT_STYLELINT ||
TOOL_JEST or frontend_all as the gate.
| const fs = require('fs'); | ||
| const path = require('path'); | ||
|
|
||
| describe('Drupal.behaviors.ysDemo', () => { | ||
| beforeEach(() => { | ||
| localStorage.clear(); | ||
| global.Drupal = { behaviors: {} }; | ||
|
|
||
| const filePath = path.resolve(__dirname, 'ys_demo.js'); | ||
| const code = fs.readFileSync(filePath, 'utf8'); | ||
| eval(code); | ||
| }); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Using eval() to load the module is functional but consider alternatives.
The fs.readFileSync + eval approach works but has limitations:
- No source map support for debugging
- Potential issues with strict mode
- Harder to track code coverage
Consider using Jest's vm module or restructuring the module to export for testing. However, given ESLint overrides are configured and this works with the existing IIFE pattern, this is acceptable for the current scope.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/modules/custom/ys_demo/js/ys_demo.test.js` around lines 1 - 12, The test
currently reads ys_demo.js and executes it via eval (see ys_demo.test.js where
fs.readFileSync + eval is used and global.Drupal is set), which hampers source
maps, strict mode handling, and coverage; change the test to load the module
without eval—either refactor the module to export its behavior and
require/import it in the test, or use Node's vm module to run the file in a
controlled context that preserves source mapping and isolation; ensure tests
still set global.Drupal and call the module initializer (or imported function)
instead of eval-ing the file content so coverage and debugging work properly.
| it('should handle multiple counter blocks', () => { | ||
| document.body.innerHTML = ` | ||
| <div data-ys-demo-counter> | ||
| <span data-counter-value>0</span> | ||
| <button data-counter-action="increment">+</button> | ||
| </div> | ||
| <div data-ys-demo-counter> | ||
| <span data-counter-value>0</span> | ||
| <button data-counter-action="increment">+</button> | ||
| </div> | ||
| `; | ||
| Drupal.behaviors.ysDemo.initCounterBlock(document); | ||
|
|
||
| const blocks = document.querySelectorAll('[data-ys-demo-counter]'); | ||
| expect(blocks[0].classList.contains('ys-demo-counter-processed')).toBe( | ||
| true, | ||
| ); | ||
| expect(blocks[1].classList.contains('ys-demo-counter-processed')).toBe( | ||
| true, | ||
| ); | ||
| }); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider testing independent counter operation for multiple blocks.
The current test verifies both blocks are marked as processed, but doesn't verify they operate independently (each incrementing its own display). This might be intentional given the current shared localStorage implementation, but worth noting for future consideration.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/modules/custom/ys_demo/js/ys_demo.test.js` around lines 222 - 242, Test
currently only checks processed class for multiple counters but not that each
counter operates independently; update the test in ys_demo.test.js to clear
localStorage at start, query each block via
document.querySelectorAll('[data-ys-demo-counter]'), find its own button
(data-counter-action="increment") and value span (data-counter-value), simulate
clicking each block's increment button separately and assert that only the
corresponding span text increments (e.g., first block's span becomes "1" after
its click while second remains "0", then vice versa); keep using
Drupal.behaviors.ysDemo.initCounterBlock to initialize and reference the
behavior and DOM attribute selectors to locate elements.
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.circleci/config.yml (1)
366-390:⚠️ Potential issue | 🟠 MajorGuard the Jest path with
CIRCLE_NODE_INDEX.This job has
parallelism: 2, but Line 367 and Line 389 execute the Jest install/test path on every node. Unlike PHPUnit below, that duplicates the same suite and doubles the Node setup cost.♻️ Suggested change
- run: name: Install development dependencies command: | docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" #;< TOOL_JEST - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + if [ "${CIRCLE_NODE_TOTAL:-1}" -eq 1 ] || [ "${CIRCLE_NODE_INDEX:-0}" -eq 0 ]; then + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + fi #;> TOOL_JEST @@ #;< TOOL_JEST - run: name: Test with Jest - command: docker compose exec -T cli bash -c "yarn test" || [ "${VORTEX_CI_NODEJS_TEST_IGNORE_FAILURE:-0}" -eq 1 ] + command: | + [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 + docker compose exec -T cli bash -c "yarn test" || [ "${VORTEX_CI_NODEJS_TEST_IGNORE_FAILURE:-0}" -eq 1 ] #;> TOOL_JEST🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.circleci/config.yml around lines 366 - 390, The Jest install/test steps (the TOOL_JEST blocks that run the yarn install and yarn test commands) are executed on every parallel node; wrap both TOOL_JEST sections with a conditional that only runs them on a single parallel index (e.g., guard with if [ "${CIRCLE_NODE_INDEX:-0}" -eq "0" ]; then ... fi) so only one parallel worker performs the Jest setup and tests, leaving other nodes to run their existing suites (mirror how PHPUnit is handled).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/build-test-deploy.yml:
- Around line 410-412: The install step currently wrapped by the TOOL_JEST
markers (the docker compose exec ... "yarn install --frozen-lockfile" command)
runs on all build matrix jobs; mirror the Jest guard by adding the same matrix
condition (matrix.instance == 0) so only the job that runs Jest performs the
install. Locate the TOOL_JEST block around the docker compose exec command and
wrap or annotate that step with the same conditional used for the Jest run
(matrix.instance == 0) to avoid running yarn install on the second matrix leg.
In @.vortex/installer/src/Prompts/Handlers/Tools.php:
- Around line 368-371: The cleanup currently only glob-matches modules' Jest
tests in the 'files' closure (the array returned by 'files' => fn(): array =>
[...]) and misses theme test files; update that closure to also include a glob
for themes (e.g. $this->tmpDir . '/' . $this->webroot .
'/themes/custom/*/js/*.test.js') alongside the existing
modules/custom/*/js/*.test.js entry so deselecting Jest removes theme tests as
well.
---
Outside diff comments:
In @.circleci/config.yml:
- Around line 366-390: The Jest install/test steps (the TOOL_JEST blocks that
run the yarn install and yarn test commands) are executed on every parallel
node; wrap both TOOL_JEST sections with a conditional that only runs them on a
single parallel index (e.g., guard with if [ "${CIRCLE_NODE_INDEX:-0}" -eq "0"
]; then ... fi) so only one parallel worker performs the Jest setup and tests,
leaving other nodes to run their existing suites (mirror how PHPUnit is
handled).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: ca447bf7-92d6-49e8-bf3f-cc01717ff44c
⛔ Files ignored due to path filters (8)
.vortex/installer/tests/Fixtures/handler_process/_baseline/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/_baseline/.eslintrc.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/_baseline/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/_baseline/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/_baseline/jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/_baseline/package.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/_baseline/web/modules/custom/sw_demo/js/sw_demo.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/_baseline/web/modules/custom/sw_demo/js/sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**
📒 Files selected for processing (3)
.circleci/config.yml.github/workflows/build-test-deploy.yml.vortex/installer/src/Prompts/Handlers/Tools.php
This comment has been minimized.
This comment has been minimized.
3 similar comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@jest.config.js`:
- Around line 21-26: The fallback roots array in module.exports is using a
relative path while discovered roots are resolved to absolute paths; update the
fallback to an absolute path (e.g., use path.resolve('web/modules/custom')) so
the ternary expression roots.length > 0 ? roots : [ ... ] returns absolute paths
consistently, and ensure the file imports/uses path.resolve where roots are
constructed so both branches produce the same absolute-form paths (refer to the
roots variable and the module.exports block).
- Around line 4-15: The comment incorrectly claims symlinks are resolved but the
code uses path.resolve (which does not follow symlinks) when building jsDir;
update the code or comment: either replace path.resolve(dir, name, 'js') with
fs.realpathSync(path.join(dir, name, 'js')) (guarded with exists checks or
try/catch because realpathSync throws) so jsDir uses the real path, or if
symlink resolution is not required, change the comment to remove the symlink
claim and keep path.resolve; locate the logic around dirs/roots, the forEach
that computes jsDir, and adjust accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: e77ebe4f-742c-4faa-8d6f-2d2f59e5d329
⛔ Files ignored due to path filters (150)
.vortex/installer/tests/Fixtures/handler_process/.!!k2C/.docker/cli.dockerfileis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/.docker/nginx-drupal.dockerfileis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/.env.local.exampleis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/phpunit.xmlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/-autoload.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/-sw_demo.deploy.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/-sw_demo.info.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/-sw_demo.libraries.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/-sw_demo.moduleis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/config/install/-views.view.sw_demo_articles.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/css/-sw_demo.cssis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/js/-sw_demo.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/src/Plugin/Block/-CounterBlock.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/src/Plugin/GeneratedContent/Node/-Article.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/src/Plugin/GeneratedContent/Taxonomy/-Tags.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/templates/-sw-demo-counter-block.html.twigis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/tests/src/FunctionalJavascript/-CounterBlockTest.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/tests/src/Kernel/-CounterBlockTest.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/modules/custom/sw_demo/tests/src/Unit/-CounterBlockTest.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/-default.services.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/-default.settings.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/-example.services.local.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/-example.settings.local.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/-services.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/-settings.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.automated_cron.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.clamav.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.config_split.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.environment_indicator.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.fast404.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.redis.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.robotstxt.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.seckit.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.shield.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.stage_file_proxy.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.sw_base.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.system.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.trusted_hosts.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/modules/-settings.xmlsitemap.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/providers/-settings.container.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/.!!k2C/web/sites/default/includes/providers/-settings.gha.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/_baseline/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/_baseline/jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/ciprovider_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/custom_modules_no_demo/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/custom_modules_none/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/deploy_types_all_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_gha/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/deps_updates_provider_ci_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/docroot/modules/custom/sw_demo/js/sw_demo.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/docroot/modules/custom/sw_demo/js/sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/package.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/docroot/modules/custom/sw_demo/js/sw_demo.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/docroot/modules/custom/sw_demo/js/sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/package.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/migration_disabled_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/migration_download_source_acquia/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/migration_download_source_ftp/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/migration_download_source_lagoon/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/migration_download_source_s3/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/migration_download_source_url/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/migration_enabled/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/migration_enabled_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/migration_enabled_lagoon/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/names/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/names/web/modules/custom/the_force_demo/js/the_force_demo.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/names/web/modules/custom/the_force_demo/js/the_force_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/provision_profile/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/timezone_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests_circleci/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests_circleci/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint/-jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/-jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme/-jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/-jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_behat/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_behat/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_behat/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_behat_circleci/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_behat_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_behat_circleci/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint/package.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_circleci/package.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_no_theme/package.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest/-jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest/package.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/-jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/.circleci/post-coverage-comment.shis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/.github/workflows/-build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/README.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/docs/ci.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/package.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/tests/phpunit/CircleCiConfigTest.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/tests/phpunit/Drupal/EnvironmentSettingsTest.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/web/sites/default/includes/providers/-settings.gha.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/web/sites/default/includes/providers/settings.circleci.phpis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit_circleci/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit_circleci/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_rector_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint/package.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_circleci/.circleci/config.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_circleci/package.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_no_theme/package.jsonis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_none/-jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_none/.ahoy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_none/.github/workflows/build-test-deploy.ymlis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_none/AGENTS.mdis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/tools_none/web/modules/custom/sw_demo/js/-sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**
📒 Files selected for processing (1)
jest.config.js
| // Discover js/ directories in custom modules, resolving symlinks to real | ||
| // paths. Jest resolves symlinks internally, so roots must use real paths | ||
| // for test files to be matched. | ||
| const dirs = ['web/modules/custom']; | ||
| const roots = []; | ||
|
|
||
| dirs.forEach((dir) => { | ||
| if (fs.existsSync(dir)) { | ||
| fs.readdirSync(dir).forEach((name) => { | ||
| const jsDir = path.resolve(dir, name, 'js'); | ||
| if (fs.existsSync(jsDir)) { | ||
| roots.push(jsDir); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Comment claims symlink resolution, but path.resolve() does not resolve symlinks.
The comment states that symlinks are resolved to real paths, but path.resolve() only converts relative paths to absolute paths—it does not follow symlinks. If symlink resolution is actually needed (as the comment suggests), use fs.realpathSync() instead.
If symlink resolution isn't actually required and the current behavior is correct, consider updating the comment to avoid confusion.
♻️ Option A: If symlink resolution is needed
dirs.forEach((dir) => {
if (fs.existsSync(dir)) {
fs.readdirSync(dir).forEach((name) => {
- const jsDir = path.resolve(dir, name, 'js');
+ const jsDir = fs.realpathSync(path.join(dir, name, 'js'));
if (fs.existsSync(jsDir)) {
roots.push(jsDir);
}
});
}
});Note: fs.realpathSync() will throw if the path doesn't exist, so you'd need to wrap it in a try-catch or check existence first.
♻️ Option B: If current behavior is correct, fix the comment
-// Discover js/ directories in custom modules, resolving symlinks to real
-// paths. Jest resolves symlinks internally, so roots must use real paths
-// for test files to be matched.
+// Discover js/ directories in custom modules, converting to absolute paths.
+// Jest resolves symlinks internally, so roots must use absolute paths for
+// test files to be matched correctly.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Discover js/ directories in custom modules, resolving symlinks to real | |
| // paths. Jest resolves symlinks internally, so roots must use real paths | |
| // for test files to be matched. | |
| const dirs = ['web/modules/custom']; | |
| const roots = []; | |
| dirs.forEach((dir) => { | |
| if (fs.existsSync(dir)) { | |
| fs.readdirSync(dir).forEach((name) => { | |
| const jsDir = path.resolve(dir, name, 'js'); | |
| if (fs.existsSync(jsDir)) { | |
| roots.push(jsDir); | |
| // Discover js/ directories in custom modules, converting to absolute paths. | |
| // Jest resolves symlinks internally, so roots must use absolute paths for | |
| // test files to be matched correctly. | |
| const dirs = ['web/modules/custom']; | |
| const roots = []; | |
| dirs.forEach((dir) => { | |
| if (fs.existsSync(dir)) { | |
| fs.readdirSync(dir).forEach((name) => { | |
| const jsDir = path.resolve(dir, name, 'js'); | |
| if (fs.existsSync(jsDir)) { | |
| roots.push(jsDir); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@jest.config.js` around lines 4 - 15, The comment incorrectly claims symlinks
are resolved but the code uses path.resolve (which does not follow symlinks)
when building jsDir; update the code or comment: either replace
path.resolve(dir, name, 'js') with fs.realpathSync(path.join(dir, name, 'js'))
(guarded with exists checks or try/catch because realpathSync throws) so jsDir
uses the real path, or if symlink resolution is not required, change the comment
to remove the symlink claim and keep path.resolve; locate the logic around
dirs/roots, the forEach that computes jsDir, and adjust accordingly.
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@jest.config.js`:
- Line 25: testPathIgnorePatterns has inconsistent pattern formats: change the
'web/core/' entry to use a leading slash so it matches the others and anchors at
a path boundary (update the testPathIgnorePatterns array to use '/web/core/');
ensure you only modify the string inside testPathIgnorePatterns so patterns
remain ['/node_modules/', '/vendor/', '/web/core/'].
In `@web/modules/custom/ys_demo/js/ys_demo.test.js`:
- Around line 208-224: The test "should add updated class on click for visual
feedback" uses jest.useFakeTimers() and calls jest.useRealTimers() at the end
but can leak when it fails; update this test to ensure timers are always
restored by either moving jest.useFakeTimers() to a beforeEach and
jest.useRealTimers() to an afterEach for the describe containing this spec, or
wrap the body of the it block in a try/finally so jest.useRealTimers() is called
in finally; reference the test name and the existing
removeUpdatedClassAfterDelay tests as a pattern to implement the hooks or
try/finally around the calls to jest.useFakeTimers(),
jest.advanceTimersByTime(300) and jest.useRealTimers().
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: ec641f2c-c5f5-42a5-928a-1eeaec2215ef
⛔ Files ignored due to path filters (7)
.vortex/installer/tests/Fixtures/handler_process/_baseline/jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/_baseline/web/modules/custom/sw_demo/js/sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/docroot/modules/custom/sw_demo/js/sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/docroot/modules/custom/sw_demo/js/sw_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/jest.config.jsis excluded by!.vortex/installer/tests/Fixtures/**.vortex/installer/tests/Fixtures/handler_process/names/web/modules/custom/the_force_demo/js/the_force_demo.test.jsis excluded by!.vortex/installer/tests/Fixtures/**
📒 Files selected for processing (2)
jest.config.jsweb/modules/custom/ys_demo/js/ys_demo.test.js
jest.config.js
Outdated
| testEnvironment: 'jest-environment-jsdom', | ||
| roots: roots.length > 0 ? roots : ['web/modules/custom'], | ||
| testMatch: ['**/*.test.js'], | ||
| testPathIgnorePatterns: ['/node_modules/', '/vendor/', 'web/core/'], |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Inconsistent pattern format in testPathIgnorePatterns.
The first two patterns use leading slashes (/node_modules/, /vendor/) while web/core/ omits it. For consistency and precision:
- testPathIgnorePatterns: ['/node_modules/', '/vendor/', 'web/core/'],
+ testPathIgnorePatterns: ['/node_modules/', '/vendor/', '/web/core/'],The leading slash ensures the pattern matches at a path boundary, preventing potential false matches like someweb/core/.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| testPathIgnorePatterns: ['/node_modules/', '/vendor/', 'web/core/'], | |
| testPathIgnorePatterns: ['/node_modules/', '/vendor/', '/web/core/'], |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@jest.config.js` at line 25, testPathIgnorePatterns has inconsistent pattern
formats: change the 'web/core/' entry to use a leading slash so it matches the
others and anchors at a path boundary (update the testPathIgnorePatterns array
to use '/web/core/'); ensure you only modify the string inside
testPathIgnorePatterns so patterns remain ['/node_modules/', '/vendor/',
'/web/core/'].
| it('should add updated class on click for visual feedback', () => { | ||
| jest.useFakeTimers(); | ||
| document.body.innerHTML = createCounterBlockHtml(); | ||
| Drupal.behaviors.ysDemo.initCounterBlock(document); | ||
|
|
||
| const incrementBtn = document.querySelector( | ||
| '[data-counter-action="increment"]', | ||
| ); | ||
| incrementBtn.click(); | ||
|
|
||
| const value = document.querySelector('[data-counter-value]'); | ||
| expect(value.classList.contains('updated')).toBe(true); | ||
|
|
||
| jest.advanceTimersByTime(300); | ||
| expect(value.classList.contains('updated')).toBe(false); | ||
| jest.useRealTimers(); | ||
| }); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider moving fake timer setup to beforeEach/afterEach for robustness.
If this test fails before line 223, jest.useRealTimers() won't execute, potentially affecting subsequent tests. For consistency with the approach used in removeUpdatedClassAfterDelay tests (lines 82-88):
♻️ Suggested approach
Either wrap this test in its own nested describe block with timer setup hooks, or use a try/finally pattern:
it('should add updated class on click for visual feedback', () => {
jest.useFakeTimers();
try {
document.body.innerHTML = createCounterBlockHtml();
Drupal.behaviors.ysDemo.initCounterBlock(document);
// ... rest of test
jest.advanceTimersByTime(300);
expect(value.classList.contains('updated')).toBe(false);
} finally {
jest.useRealTimers();
}
});🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/modules/custom/ys_demo/js/ys_demo.test.js` around lines 208 - 224, The
test "should add updated class on click for visual feedback" uses
jest.useFakeTimers() and calls jest.useRealTimers() at the end but can leak when
it fails; update this test to ensure timers are always restored by either moving
jest.useFakeTimers() to a beforeEach and jest.useRealTimers() to an afterEach
for the describe containing this spec, or wrap the body of the it block in a
try/finally so jest.useRealTimers() is called in finally; reference the test
name and the existing removeUpdatedClassAfterDelay tests as a pattern to
implement the hooks or try/finally around the calls to jest.useFakeTimers(),
jest.advanceTimersByTime(300) and jest.useRealTimers().
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
a2a0510 to
a201945
Compare
This comment has been minimized.
This comment has been minimized.
2 similar comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
2 similar comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Code coverage (threshold: 90%) Per-class coverage |
This comment has been minimized.
This comment has been minimized.
2 similar comments
This comment has been minimized.
This comment has been minimized.
|
Code coverage (threshold: 90%) Per-class coverage |
Closes #2394
Summary
Added Jest as a first-class JavaScript unit testing tool in Vortex. This includes a
jest.config.jsthat auto-discovers test files in custom modulejs/directories,jestandjest-environment-jsdomdependencies inpackage.json, and a newtest-jsahoy command. CI pipelines for both GitHub Actions and CircleCI were updated to run Jest tests as a separate step, controlled by aVORTEX_CI_NODEJS_TEST_IGNORE_FAILUREflag.The
ys_demomodule's JavaScript was refactored to extract logic into testable methods (applyAction,getCounterValue) and a comprehensive test suite (ys_demo.test.js) was added to demonstrate and validate the pattern.The installer's
Toolshandler was extended to support Jest as a selectable tool with proper discovery, removal logic, and group membership. Thefrontend_lintinggroup was split intofrontend_linting(ESLint/Stylelint only) and a newfrontend_allgroup (ESLint + Stylelint + Jest) that controls sharedyarn installandpackage.json/yarn.lockfile removal.Changes
Jest tooling
jest.config.js— new config that discoversjs/directories insideweb/modules/custom/*/as Jest roots, usingjsdomenvironment and matching*.test.jsfilespackage.json— addedjestandjest-environment-jsdomdevDependencies; added"test": "jest"scriptyarn.lock— updated with new Jest dependency treeAhoy command
.ahoy.yml— removedtest-jsalias fromtest-functional-javascript; added newtest-jscommand underTOOL_JESTtoken that runsyarn testCI pipelines
.circleci/config.yml— addedyarn installstep underTOOL_JESTtoken in install phase; added "Test module code with Jest" run step.github/workflows/build-test-deploy.yml— same additions for GitHub Actions; Jest step usescontinue-on-errorcontrolled byVORTEX_CI_NODEJS_TEST_IGNORE_FAILUREESLint config
.eslintrc.json— addedoverridesblock for*.test.jsfiles: enablesjestenv globals, disablesno-eval, relaxesmax-nested-callbacksDemo module refactor
web/modules/custom/ys_demo/js/ys_demo.js— extracted inline switch intoapplyAction()method; extractedstorageKeyto a behaviour property; refactored arrow functions for testabilityweb/modules/custom/ys_demo/js/ys_demo.test.js— new 270-line test suite coveringstorageKey,getCounterValue,applyAction, and full DOM interaction tests for counter blocksInstaller
.vortex/installer/src/Prompts/Handlers/Tools.php— addedJESTconstant; registered Jest in tool definitions withpresentdetection,package.jsonremoval callbacks, file list, andAGENTS.mdlines; splitfrontend_lintinggroup into separatefrontend_linting,frontend_testing, andfrontend_allgroups; updatedfrontend_allcheck to controlyarn installremoval.vortex/installer/tests/Functional/Handlers/ToolsHandlerProcessTest.php— addedtools_no_jestandtools_no_jest_circlecitest cases; updated existing no-FE-lint cases to also exclude Jest.vortex/installer/tests/Unit/Handlers/ToolsHandlerDiscoveryTest.php— added Jest to expected default/installed tool lists; addedjestandjest.config.jsdiscovery test casesDocs
AGENTS.md— added# Jest testingsection withahoy test-jscommandBefore / After
Tool group structure
ahoy test-js command
Summary by CodeRabbit
New Features
Tests
CI
Refactor
Lint
Docs