Skip to content

Added Jest test coverage and refactored demo test to use 'require()'.#2446

Merged
AlexSkrypnyk merged 1 commit intomainfrom
feature/add-jest-coverage
Apr 2, 2026
Merged

Added Jest test coverage and refactored demo test to use 'require()'.#2446
AlexSkrypnyk merged 1 commit intomainfrom
feature/add-jest-coverage

Conversation

@AlexSkrypnyk
Copy link
Copy Markdown
Member

@AlexSkrypnyk AlexSkrypnyk commented Apr 2, 2026

Summary

Added Jest test coverage collection and refactored the demo test to use require() instead of eval() for loading Drupal behaviors. Moved test files to a tests/ subdirectory, added a log() wrapper method to suppress console output during tests, updated ESLint config, functional test assertions, and documentation.

Changes

Jest coverage collection

  • jest.config.js — Added collectCoverageFrom, coverageReporters (text, lcov, HTML, Cobertura), and coverageDirectory targeting .logs/coverage/jest
  • package.json — Added --coverage flag to the test script

Demo test refactoring

  • web/modules/custom/ys_demo/js/tests/ys_demo.test.js — Replaced eval(fs.readFileSync(...)) with jest.resetModules() + require() for loading behaviors; added jest.spyOn(console, 'log') to suppress output during tests; moved from js/ to js/tests/ subdirectory
  • web/modules/custom/ys_demo/js/ys_demo.js — Extracted console.log call into a log() method on the behavior object

ESLint and config

  • .eslintrc.json — Replaced no-eval: off with global-require: off in the *.test.js override

Functional test assertions

  • .vortex/tests/phpunit/Traits/Subtests/SubtestAhoyTrait.php — Updated test file path to js/tests/; added assertions for coverage directory, cobertura.xml file, lcov-report directory, and 100% line/branch rates in Cobertura XML

Documentation

  • .vortex/docs/content/development/jest.mdx — Updated test file structure to show tests/ subdirectory; updated template to use require() pattern; added Coverage section documenting reporters and output locations; updated ESLint and boilerplate sections

Summary by CodeRabbit

  • Tests

    • Enabled automated code coverage collection and reporting in multiple formats (text, HTML, Cobertura XML).
    • Coverage reports now generated to .logs/coverage/jest/ directory when running tests.
  • Documentation

    • Updated Jest testing guidance with new test organization structure and coverage configuration details.
  • Chores

    • Updated test infrastructure configuration to support coverage metrics.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ba5458be-ea75-4443-9549-0c0fe55cfdc4

📥 Commits

Reviewing files that changed from the base of the PR and between ac45c3b and 1261396.

⛔ Files ignored due to path filters (30)
  • .vortex/installer/tests/Fixtures/handler_process/_baseline/.eslintrc.json is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/_baseline/jest.config.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/_baseline/package.json is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/_baseline/web/modules/custom/sw_demo/js/sw_demo.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/_baseline/web/modules/custom/sw_demo/js/tests/sw_demo.test.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/custom_modules_no_demo/web/modules/custom/sw_demo/js/tests/-sw_demo.test.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/custom_modules_none/web/modules/custom/sw_demo/js/tests/-sw_demo.test.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/hosting_acquia/docroot/modules/custom/sw_demo/js/sw_demo.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/hosting_acquia/docroot/modules/custom/sw_demo/js/tests/sw_demo.test.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/hosting_acquia/jest.config.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/hosting_acquia/package.json is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/hosting_acquia/web/modules/custom/sw_demo/js/tests/-sw_demo.test.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/docroot/modules/custom/sw_demo/js/sw_demo.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/docroot/modules/custom/sw_demo/js/tests/sw_demo.test.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/jest.config.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/package.json is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/web/modules/custom/sw_demo/js/tests/-sw_demo.test.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/names/web/modules/custom/sw_demo/js/tests/-sw_demo.test.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/names/web/modules/custom/the_force_demo/js/tests/the_force_demo.test.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/names/web/modules/custom/the_force_demo/js/the_force_demo.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/tools_no_eslint/package.json is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_circleci/package.json is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_no_theme/package.json is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/tools_no_jest/package.json is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/tools_no_jest/web/modules/custom/sw_demo/js/-sw_demo.test.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/tools_no_jest_circleci/package.json is 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.js is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint/package.json is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_circleci/package.json is excluded by !.vortex/installer/tests/Fixtures/**
  • .vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_no_theme/package.json is excluded by !.vortex/installer/tests/Fixtures/**
📒 Files selected for processing (7)
  • .eslintrc.json
  • .vortex/docs/content/development/jest.mdx
  • .vortex/tests/phpunit/Traits/Subtests/SubtestAhoyTrait.php
  • jest.config.js
  • package.json
  • web/modules/custom/ys_demo/js/tests/ys_demo.test.js
  • web/modules/custom/ys_demo/js/ys_demo.js

Walkthrough

Enabled Jest coverage collection and reports, moved tests into js/tests/, replaced runtime eval loading with jest.resetModules() + require(), added console mocking/restore in tests, added a log(message) helper on the ys_demo behavior, and updated CI/test assertions to verify coverage artifacts under .logs/coverage/jest/.

Changes

Cohort / File(s) Summary
Jest config & scripts
jest.config.js, package.json
Enabled coverage collection for web/modules/custom/**/js/**/*.js (excluding *.test.js); added reporters text, lcov, html, and Cobertura (cobertura.xml); set coverageDirectory to .logs/coverage/jest; updated test npm script to jest --coverage.
ESLint & Docs
.eslintrc.json, .vortex/docs/content/development/jest.mdx
Replaced no-eval allowance with global-require/import/extensions override for tests; documentation updated to describe js/tests/ layout, jest.resetModules() + require() loading, and coverage report locations.
Test harness / assertions
.vortex/tests/phpunit/Traits/Subtests/SubtestAhoyTrait.php
Adjusted expected test path to js/tests/...; added assertions that coverage artifacts exist in .logs/coverage/jest/ (including cobertura.xml and lcov-report) and that cobertura.xml contains coverage metrics.
Module tests
web/modules/custom/ys_demo/js/tests/ys_demo.test.js
Removed fs/eval loading in favor of jest.resetModules() + require('../ys_demo.js'); added console.log spy and jest.restoreAllMocks() in teardown; retained global Drupal cleanup.
Module code
web/modules/custom/ys_demo/js/ys_demo.js
Replaced direct console.log(...) in click handler with new log(message) method on Drupal.behaviors.ysDemo that wraps console.log(message) (ESLint suppression preserved).

Sequence Diagram(s)

sequenceDiagram
  participant Dev as Developer / CLI
  participant Jest as Jest Runner
  participant Loader as Node Module Loader
  participant Module as ys_demo.js
  participant Reporter as Coverage Reporter
  participant FS as Filesystem

  Dev->>Jest: run `npm test` (jest --coverage)
  Jest->>Jest: jest.resetModules()
  Jest->>Loader: require('../ys_demo.js')
  Loader->>Module: load & execute module IIFE
  Module-->>Jest: behavior registered / exports available
  Jest->>Reporter: collect coverage data during tests
  Reporter->>FS: write reports to .logs/coverage/jest/ (text, lcov, html, cobertura.xml)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped through modules, swapped eval for a require,

jest.resetModules() made each test retire,
I wrapped a little log and kept the tests neat,
Coverage bloomed in .logs — reports tidy and sweet,
A carrot for CI, and a hop of delight.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main objectives of the changeset: adding Jest coverage collection and refactoring the demo test to use require() instead of eval().

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/add-jest-coverage

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 34: The Jest config writes coverage to coverageDirectory
'.logs/coverage/jest' which CI does not read; update the jest.config.js
coverageDirectory to the CI artifacts path (e.g. '/tmp/artifacts/coverage/jest')
and ensure Jest emits the required formats by adding/updating the
coverageReporters entry to include 'cobertura' and 'text' (so the CI can consume
cobertura.xml and coverage.txt). Modify the coverageDirectory and
coverageReporters entries in jest.config.js accordingly.
- Line 33: The coverageReporters array formatting in jest.config.js violates
Prettier rules; reformat the coverageReporters value so it adheres to project
Prettier settings (e.g., split elements consistently and avoid nested array
line-wrapping that breaks rules) by adjusting the coverageReporters array
declaration (the coverageReporters key and its value that includes
['text','lcov','html', ['cobertura', { file: 'cobertura.xml' }]]) to a
Prettier-compliant layout.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 26ec5fc0-422a-480b-9ac2-4d49c580714f

📥 Commits

Reviewing files that changed from the base of the PR and between c18ca0c and 7c6ad85.

📒 Files selected for processing (2)
  • jest.config.js
  • package.json

],
collectCoverageFrom: ['web/modules/custom/**/js/**/*.js', '!**/*.test.js'],
coverageReporters: ['text', 'lcov', 'html', ['cobertura', { file: 'cobertura.xml' }]],
coverageDirectory: '.logs/coverage/jest',
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Coverage output path is not wired into current CI coverage extraction.

Line 34 writes reports to .logs/coverage/jest, but CI currently extracts and enforces coverage from /tmp/artifacts/coverage/phpunit/cobertura.xml and /tmp/artifacts/coverage/phpunit/coverage.txt (.circleci/config.yml Lines 400-437). As-is, Jest coverage won’t be included in the coverage summary/threshold flow.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@jest.config.js` at line 34, The Jest config writes coverage to
coverageDirectory '.logs/coverage/jest' which CI does not read; update the
jest.config.js coverageDirectory to the CI artifacts path (e.g.
'/tmp/artifacts/coverage/jest') and ensure Jest emits the required formats by
adding/updating the coverageReporters entry to include 'cobertura' and 'text'
(so the CI can consume cobertura.xml and coverage.txt). Modify the
coverageDirectory and coverageReporters entries in jest.config.js accordingly.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Jest coverage output at .logs/coverage/jest follows the project convention where all coverage reports live under .logs/coverage/<tool>. The CI PHPUnit coverage paths are specific to PHPUnit — Jest coverage collection is new and its CI integration will be handled separately when coverage thresholds are configured for JavaScript.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexSkrypnyk, understood — the .logs/coverage/<tool> layout is the project-wide convention, and the PHPUnit CI paths are specific to that tool's existing integration. I'll keep this in mind for future reviews so I don't flag Jest coverage paths as misaligned with the PHPUnit CI setup.


✏️ Learnings added
Learnt from: AlexSkrypnyk
Repo: drevops/vortex PR: 2446
File: jest.config.js:34-34
Timestamp: 2026-04-02T07:57:34.712Z
Learning: In the drevops/vortex repository, all coverage reports follow the convention `.logs/coverage/<tool>` (e.g. `.logs/coverage/jest` for Jest, `.logs/coverage/phpunit` for PHPUnit). The CI PHPUnit coverage extraction paths (e.g. `/tmp/artifacts/coverage/phpunit/cobertura.xml`) are specific to PHPUnit. Jest CI coverage integration is separate and will be configured independently. Do not flag `.logs/coverage/jest` as misaligned with PHPUnit CI artifact paths.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@github-actions

This comment has been minimized.

@AlexSkrypnyk

This comment has been minimized.

2 similar comments
@AlexSkrypnyk

This comment has been minimized.

@AlexSkrypnyk

This comment has been minimized.

@AlexSkrypnyk AlexSkrypnyk changed the title Added test coverage collection for Jest. Added Jest test coverage and refactored demo test to use 'require()'. Apr 2, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 @.vortex/tests/phpunit/Traits/Subtests/SubtestAhoyTrait.php:
- Around line 545-551: The tests currently use
assertFileContainsString('.logs/coverage/jest/cobertura.xml', 'line-rate="1"')
and similar for branch-rate, which forces 100% coverage; change these to instead
verify the attributes exist with any numeric value by reading the file (e.g.,
via file_get_contents) and using a regex-based assertion (e.g.,
assertMatchesRegularExpression or assertFileMatchesRegularExpression) against
patterns like /line-rate="\d+(\.\d+)?"/ and /branch-rate="\d+(\.\d+)?"/; update
the assertions in the test method that calls logSubstep('Assert Jest coverage
files are present') and syncToHost('.logs') to use these regex checks instead of
exact '="1"' matches so the test asserts coverage metadata presence without
requiring perfect coverage.

In `@web/modules/custom/ys_demo/js/tests/ys_demo.test.js`:
- Line 14: The test require statement require('../ys_demo.js') triggers an
ESLint import/extensions warning; either remove the extension in the test to use
Node's default resolution (change the require call in ys_demo.test.js to
require('../ys_demo')) or add an ESLint override to disable import/extensions
for tests (update .eslintrc.json to include an override for the test glob that
sets "import/extensions": "off"); locate the require in ys_demo.test.js and
apply one of these two fixes consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6792b438-5feb-4d08-b549-14d44766ec61

📥 Commits

Reviewing files that changed from the base of the PR and between 7c6ad85 and ac45c3b.

📒 Files selected for processing (5)
  • .eslintrc.json
  • .vortex/docs/content/development/jest.mdx
  • .vortex/tests/phpunit/Traits/Subtests/SubtestAhoyTrait.php
  • web/modules/custom/ys_demo/js/tests/ys_demo.test.js
  • web/modules/custom/ys_demo/js/ys_demo.js

@github-actions

This comment has been minimized.

@AlexSkrypnyk

This comment has been minimized.

2 similar comments
@AlexSkrypnyk

This comment has been minimized.

@AlexSkrypnyk

This comment has been minimized.

@AlexSkrypnyk AlexSkrypnyk force-pushed the feature/add-jest-coverage branch from ac45c3b to 1261396 Compare April 2, 2026 07:33
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

Code coverage (threshold: 90%)

  Classes: 100.00% (1/1)
  Methods: 100.00% (2/2)
  Lines:   98.53% (201/204)
Per-class coverage
Drupal\ys_demo\Plugin\Block\CounterBlock
  Methods: 100.00% ( 2/ 2)   Lines: 100.00% ( 10/ 10)

@AlexSkrypnyk

This comment has been minimized.

2 similar comments
@AlexSkrypnyk

This comment has been minimized.

@AlexSkrypnyk
Copy link
Copy Markdown
Member Author

Code coverage (threshold: 90%)

  Classes: 100.00% (1/1)
  Methods: 100.00% (2/2)
  Lines:   98.53% (201/204)
Per-class coverage
Drupal\ys_demo\Plugin\Block\CounterBlock
  Methods: 100.00% ( 2/ 2)   Lines: 100.00% ( 10/ 10)

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.42%. Comparing base (7f3fb56) to head (1261396).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2446      +/-   ##
==========================================
- Coverage   79.78%   79.42%   -0.36%     
==========================================
  Files         127      121       -6     
  Lines        6825     6702     -123     
  Branches       44        3      -41     
==========================================
- Hits         5445     5323     -122     
+ Misses       1380     1379       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@AlexSkrypnyk AlexSkrypnyk merged commit b6e739e into main Apr 2, 2026
30 checks passed
@AlexSkrypnyk AlexSkrypnyk deleted the feature/add-jest-coverage branch April 2, 2026 08:54
@github-project-automation github-project-automation bot moved this from BACKLOG to Release queue in Vortex Apr 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Release queue

Development

Successfully merging this pull request may close these issues.

1 participant