MW
Tutorial

Testing and Debugging Blocks

Use @wordpress/scripts test, React DevTools, and block validation to catch issues before they hit production — including the dreaded yellow validation warning.

intermediate 30 min May 13, 2026
A complete block plugin from Part 10

TESTING AND DEBUGGING BLOCKS

Block bugs cluster in three places: edit/save mismatches, stale attributes after schema changes, and styles that look right in the editor but wrong on the front-end. This tutorial covers the tools and habits that catch them.

Block validation — the yellow warning

When you load a post, WordPress parses the saved HTML and reconstructs blocks. If the reconstruction doesn’t match what your Save function would produce now, you get a “Block validation failed” warning with options to “Attempt block recovery” or “Convert to HTML”.

Causes, in order of frequency:

  1. You changed the Save function without registering a deprecation
  2. Save uses different markup than what the parser expects (whitespace, attribute order, missing classes)
  3. An attribute changed sources (was in comment, now in HTML, or vice versa)

The fix is always one of:

  • Register a deprecation for the old version
  • Make your Save function output identical HTML to what’s saved
  • Force re-save by editing and saving the post

React DevTools

Install the React Developer Tools browser extension. With it:

  • Inspect the Edit component tree for any selected block
  • See current attribute values in the Props panel
  • Trigger re-renders to confirm state updates
  • Profile editor performance

WordPress ships React in development mode, so DevTools just works — no config needed.

Unit tests with @wordpress/scripts

@wordpress/scripts includes Jest pre-configured. Write tests for pure functions inside your block — attribute transformers, utility functions, render helpers:

// src/utils.js
export function classNameForType(type) {
  return `my-callout-${type}`;
}

// src/utils.test.js
import { classNameForType } from './utils';

test('classNameForType prepends my-callout-', () => {
  expect(classNameForType('warning')).toBe('my-callout-warning');
});
Terminal — run tests
$ npm test
PASS src/utils.test.js ✓ classNameForType prepends my-callout- Tests: 1 passed, 1 total Time: 0.84s

End-to-end tests with Playwright

For full block-in-editor flows, @wordpress/e2e-test-utils-playwright provides helpers. These tests run a real WordPress + Chrome:

import { test, expect } from '@wordpress/e2e-test-utils-playwright';

test('Callout block inserts and saves', async ({ admin, editor }) => {
  await admin.createNewPost();
  await editor.insertBlock({ name: 'my-first-block/callout' });
  await editor.setBlockAttribute('title', 'Test title');
  await editor.publishPost();

  await expect(editor.canvas.getByText('Test title')).toBeVisible();
});

E2E tests are slow but catch the issues unit tests miss — actual editor interactions, attribute persistence, save/load cycles.

Common pitfalls + fixes

SymptomLikely cause
Yellow “Block validation failed”Save function changed since content was saved. Add a deprecation.
Block disappears after saveSave returned null without render callback set. Either return JSX or wire dynamic render.
Styles look right in editor, wrong on front-endeditor.scss styles aren’t loaded on front-end (correct), but you put real styles there. Move to style.scss.
attributes is undefinedForgot to declare in block.json. Add it.
setAttributes is not a functionTypo or trying to call from Save. Save doesn’t have setAttributes.
Block doesn’t appear in inserterBuild didn’t run, or stale browser cache. npm run build + hard refresh.
Editor crashes when block is selectedReact error inside Edit. Open browser console for the stack trace.
Edit looks like raw text, not the componentindex.js didn’t register the block. Check npm run start output for errors.

Debugging workflow

When something breaks:

  1. Open browser DevTools console — most block errors throw there before they affect the UI
  2. Check npm run start output — webpack errors show up here, not in the browser
  3. Inspect the block in the React DevTools — confirm attributes match what you expect
  4. Switch to Code editor view (top-right menu) — see the actual saved HTML
  5. Try with all other plugins deactivated — to rule out conflicts
  6. Diff the rendered HTML against what Save would output now — for validation issues

What’s next

Part 12 is the finale — publishing your block plugin to wordpress.org so other people can install it.

You've completed this tutorial!

Get the next one in your inbox. Practical tips, no fluff.

Subscribe

Get weekly notes in your inbox

Practical tips, tutorials and resources. No spam.