Skip to main content

write-block-tests

Write Jest unit tests for Edge Delivery Services (EDS) blocks using jsdom HTML fixtures and decorate assertions. Use when adding or updating block tests, co-locating *.test.js files, mocking /scripts/ imports, or documenting the project's block testing strategy.

Source facts

Repository
adobe/adobe-labs-website
Last source activity
August 24, 2026 at 16:59
Detected SKILL.md language
English
Stars
1
Forks
1

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
write-block-tests
description
Write Jest unit tests for Edge Delivery Services (EDS) blocks using jsdom HTML fixtures and decorate assertions. Use when adding or updating block tests, co-locating *.test.js files, mocking /scripts/ imports, or documenting the project's block testing strategy.
# EDS Block Testing ## Stack - Jest with `jsdom` (`npm test`) - `@testing-library/jest-dom` matchers (via `tests/setupTests.js`) - `@testing-library/dom` queries for behavioral tests (`getByRole`, `getByLabelText`, etc.) ## Pattern 1. Co-locate: `blocks/<block>/<block>.test.js` 2. Build an HTML fixture matching the markup `decorate` receives (block element after authoring/EDS processing) 3. Call `decorate(block)` with that fixture 4. Assert DOM changes (`classes`, structure, attributes, text, ARIA) ## What to test - Conditional logic (e.g. cases where a class is added or not added) - Structural changes (e.g. moved/replaced nodes, added semantic markup) - Content rendering (e.g. the content is rendered in the correct node) - Behaviors: after `decorate`, query controls with `@testing-library/dom` (`getByRole`, `getByLabelText`) and drive interactions with native DOM APIs (`.click()`, `dispatchEvent`) - e.g. `within(block).getByRole('button', { name: 'Open navigation' }).click()` - e.g. Escape / focusout closes an open menu - Append the decorated block to `document.body` when handlers use `document.getElementById` or other global lookups - Always try to query elements by accessible roles first. Fall back to block selectors only when the control has no accessible role or name. ## Mocking Mock `/scripts/` and cross-block helpers so tests stay unit-scoped (no network, no full page bootstrap). Prefer `jest.mock` on the module the block imports. - **`getMetadata`** (`scripts/aem.js`): return authored meta strings (or `''`) so path/feature branches are covered without `<meta>` tags. Vary return values per test for default vs custom paths (e.g. footer/nav). - **`loadFragment`** (`blocks/fragment/fragment.js`): resolve to a minimal DOM fragment (`DocumentFragment` or element with the children decorate expects). Do not hit real fragment URLs. - **Other `aem.js` helpers** (`createOptimizedPicture`, `loadCSS`, etc.): stub to simple passthroughs or no-ops when decorate calls them. - Assert the block called mocks with the expected args when the contract matters (path, meta name); otherwise only assert decorate’s DOM output. - Keep mocks local to the test file; reset with `jest.clearAllMocks()` in `beforeEach` when return values change per case. - Do not reference `document` (or other out-of-scope values) inside a `jest.mock` factory — Jest hoists factories and rejects that. Stub with `jest.fn()` and set DOM return values in `beforeEach`. Example shape: ```js jest.mock('../../scripts/aem.js', () => ({ getMetadata: jest.fn(() => ''), })); jest.mock('../fragment/fragment.js', () => ({ loadFragment: jest.fn(), })); function createFragment(html) { const wrap = document.createElement('div'); wrap.innerHTML = html; return wrap; } beforeEach(() => { jest.clearAllMocks(); getMetadata.mockReturnValue(''); loadFragment.mockResolvedValue( createFragment('<div class="section"><p>Footer</p></div>'), ); }); ``` ## Test style - Jest + `@testing-library/jest-dom` matchers - Imperative test names: "adds columns-img-col when …" (not "should …" / "correctly …") ## Examples ### Decorate When testing the `decorate` function, assert that the DOM has been modified as expected: ```js it('adds a class to the paragraph', () => { const block = document.createElement('div'); block.innerHTML = '<p>Hello</p>'; decorate(block); expect(block.querySelector('p')).toHaveClass('decorated-class'); }); ``` ### Behavior Mock deps and set up fixtures in `beforeEach` (see Mocking). Append to `document.body` when handlers use global lookups. Query by role or accessible name; scope queries with `within(block)`. ```js import { within } from '@testing-library/dom'; it('toggles the mobile menu on hamburger click', async () => { const block = document.createElement('div'); await decorate(block); within(block).getByRole('button', { name: 'Open navigation' }).click(); expect(within(block).getByRole('navigation')).toHaveAttribute('aria-expanded', 'true'); }); ``` ## Checklist ``` - [ ] Test file co-located with the block - [ ] Fixture mirrors decorate input markup - [ ] decorate(block) called under test - [ ] Conditional rendering logic for block is covered - [ ] Assertions target decoration outcomes - [ ] /scripts/ deps mocked when needed - [ ] npm test passes ```
View on GitHub