-
-
Notifications
You must be signed in to change notification settings - Fork 28
[#2394] Added Jest for JavaScript unit testing. #2418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
73e1401
[#2394] Added Jest for JavaScript unit testing.
AlexSkrypnyk 1d73987
[#2394] Fixed missing 'jest' in expected default tools list in Abstra…
AlexSkrypnyk 536b605
Updated baseline.
AlexSkrypnyk 11c5bd1
[#2394] Moved Jest CI step to build job and fixed duplicate yarn inst…
AlexSkrypnyk 61a33df
Updated snapshots.
AlexSkrypnyk 473be89
[#2394] Fixed Jest config for CI: explicit jsdom environment and core…
AlexSkrypnyk 5d2f196
Updated snapshots.
AlexSkrypnyk da3180c
[#2394] Fixed jsdom docblock and core exclusion pattern for CI.
AlexSkrypnyk 36c71ba
Updated snapshots.
AlexSkrypnyk 8987347
[#2394] Added modulePathIgnorePatterns to exclude Drupal core from Jest.
AlexSkrypnyk 10ae309
Updated snapshots.
AlexSkrypnyk c9e5020
[#2394] Fixed testPathIgnorePatterns for core exclusion and ESLint js…
AlexSkrypnyk f0eff21
Updated snapshots.
AlexSkrypnyk 1600374
[#2394] Used explicit testMatch pattern to restrict Jest to custom mo…
AlexSkrypnyk 71ddb2a
Updated snapshots.
AlexSkrypnyk 1f8c6d8
[#2394] Added modulePathIgnorePatterns to prevent Jest scanning Drupa…
AlexSkrypnyk 227c31d
Updated snapshots.
AlexSkrypnyk d6fecee
[#2394] Added debug logging to jest.config.js for CI investigation.
AlexSkrypnyk a88e2aa
[#2394] Used testRegex to strictly match only custom module test files.
AlexSkrypnyk 225e62f
Updated snapshots.
AlexSkrypnyk 58c8d91
[#2394] Added explicit --config flag to Jest command.
AlexSkrypnyk c0086e6
Updated snapshots.
AlexSkrypnyk 7eacfc6
[#2394] Moved Jest config into package.json for Docker CI compatibility.
AlexSkrypnyk a93acde
Updated snapshots.
AlexSkrypnyk 0f7475a
[#2394] Restored jest.config.js and added to .dockerignore whitelist.
AlexSkrypnyk 202b7a2
t
AlexSkrypnyk 0399e35
Updated snapshots.
AlexSkrypnyk 9033e55
[#2394] Regenerated CircleCI test config.
AlexSkrypnyk 26732e7
[#2394] Added Jest documentation for tools and development sections.
AlexSkrypnyk 88f3776
[#2394] Added Jest workflow test for pass, path pattern, and failure …
AlexSkrypnyk a201945
[#2394] Added test-by-name scenario to Jest workflow test.
AlexSkrypnyk cbfa260
[#2394] Refocused development Jest docs on writing tests, linked to t…
AlexSkrypnyk eea6d1f
[#2394] Renamed CI var to VORTEX_CI_JEST_IGNORE_FAILURE and cross-lin…
AlexSkrypnyk 0c4482e
Updated snapshots.
AlexSkrypnyk 1296604
[#2394] Added VORTEX_CI_JEST_IGNORE_FAILURE to CI variables and updat…
AlexSkrypnyk fb0d465
[#2394] Fixed broken doc links to use /docs/ prefix.
AlexSkrypnyk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| --- | ||
| sidebar_label: Jest | ||
| sidebar_position: 6 | ||
| --- | ||
|
|
||
| # Jest | ||
|
|
||
| **Vortex** uses [Jest](https://jestjs.io/) as a framework for JavaScript unit | ||
| testing. Jest tests verify that JavaScript behaviors in custom Drupal modules | ||
| work correctly in isolation, without requiring a browser or Drupal bootstrap. | ||
|
|
||
| For running tests, configuration, and CI settings, see the | ||
| [Jest tool reference](/docs/tools/jest). | ||
|
|
||
| ## Test file structure | ||
|
|
||
| Test files are co-located with source files in the `js/` directory of each | ||
| custom module: | ||
|
|
||
| ```text | ||
| web/modules/custom/my_module/ | ||
| └── js/ | ||
| ├── my_module.js # Source file (Drupal behavior) | ||
| └── my_module.test.js # Jest test file | ||
| ``` | ||
|
|
||
| Jest automatically discovers `*.test.js` files in `web/modules/custom/*/js/` | ||
| directories. Adding a new module with tests requires no configuration changes. | ||
|
|
||
| ## Writing tests | ||
|
|
||
| Drupal JavaScript uses the IIFE pattern `((Drupal) => { ... })(Drupal)` where | ||
| `Drupal` is a global object. Tests load these source files using `eval()` after | ||
| setting up the required globals. | ||
|
|
||
| ### Test template | ||
|
|
||
| ```javascript | ||
| /** | ||
| * @jest-environment jsdom | ||
| */ | ||
|
|
||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
|
|
||
| describe('Drupal.behaviors.myModule', () => { | ||
| beforeEach(() => { | ||
| localStorage.clear(); | ||
| global.Drupal = { behaviors: {} }; | ||
|
|
||
| const filePath = path.resolve(__dirname, 'my_module.js'); | ||
| const code = fs.readFileSync(filePath, 'utf8'); | ||
| eval(code); | ||
| }); | ||
|
|
||
| afterEach(() => { | ||
| delete global.Drupal; | ||
| }); | ||
|
|
||
| it('should attach behavior to the context', () => { | ||
| document.body.innerHTML = '<div data-my-module></div>'; | ||
| Drupal.behaviors.myModule.attach(document); | ||
|
|
||
| const el = document.querySelector('[data-my-module]'); | ||
| expect(el.classList.contains('processed')).toBe(true); | ||
| }); | ||
| }); | ||
| ``` | ||
|
|
||
| ### Loading Drupal behaviors | ||
|
|
||
| The `eval(fs.readFileSync(...))` pattern executes the source file's IIFE, which | ||
| receives `global.Drupal` as its `Drupal` parameter and registers the behavior. | ||
| After `eval()`, the behavior is accessible via `Drupal.behaviors.myModule`. | ||
|
|
||
| ### Mocking globals | ||
|
|
||
| Set globals in `beforeEach` and clean them up in `afterEach`: | ||
|
|
||
| | Global | Setup | When needed | | ||
| |--------|-------|-------------| | ||
| | `Drupal` | `global.Drupal = { behaviors: {} }` | Always — required by all Drupal behaviors | | ||
| | `jQuery` | `global.jQuery = require('jquery')` or a mock | When the source file uses `jQuery` or `$` | | ||
| | `drupalSettings` | `global.drupalSettings = { path: { baseUrl: '/' } }` | When the source file reads `drupalSettings` | | ||
| | `localStorage` | Provided by jsdom; call `localStorage.clear()` | When the source file uses `localStorage` | | ||
|
|
||
| ### Testing DOM interactions | ||
|
|
||
| The `jsdom` environment provides `document` and `window`. Set up HTML before | ||
| each test: | ||
|
|
||
| ```javascript | ||
| document.body.innerHTML = ` | ||
| <div data-my-widget> | ||
| <button data-action="save">Save</button> | ||
| <span data-status></span> | ||
| </div> | ||
| `; | ||
|
|
||
| Drupal.behaviors.myModule.attach(document); | ||
| document.querySelector('[data-action="save"]').click(); | ||
|
|
||
| expect(document.querySelector('[data-status]').textContent).toBe('Saved'); | ||
| ``` | ||
|
|
||
| ### Testing timed behavior | ||
|
|
||
| Use Jest fake timers for `setTimeout` and `setInterval`: | ||
|
|
||
| ```javascript | ||
| jest.useFakeTimers(); | ||
|
|
||
| Drupal.behaviors.myModule.startPolling(); | ||
| jest.advanceTimersByTime(5000); | ||
|
|
||
| expect(fetchSpy).toHaveBeenCalledTimes(5); | ||
|
|
||
| jest.useRealTimers(); | ||
| ``` | ||
|
|
||
| ### ESLint compatibility | ||
|
|
||
| The `.eslintrc.json` includes an override for `*.test.js` files that enables | ||
| the `jest` environment and allows `eval()`. No additional ESLint configuration | ||
| is needed for test files. | ||
|
|
||
| ## Boilerplate | ||
|
|
||
| **Vortex** provides a Jest test boilerplate for the [demo module](https://github.com/drevops/vortex/blob/main/web/modules/custom/ys_demo/js/ys_demo.test.js) | ||
| that demonstrates testing a counter block with DOM manipulation, localStorage | ||
| interaction, and event handling. | ||
|
|
||
| This boilerplate test runs in continuous integration pipeline when you install | ||
| **Vortex** and can be used as a starting point for writing your own JavaScript | ||
| tests. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.