Skip to content

Testing

phil/block-editor-bundle

The bundle's tests

tests/Unit covers the toolsets and presets, the suggestions and uploaded images, DocumentReferences, the normalizers of each toolset, the transformer, the form type and its options, the endpoints — the access attribute granted or refused, trusted requests, the CSRF tokens accepted and refused, URLs, every answer of the upload and search controllers — and the bundle's configuration, services and prepended Twig, CSRF and AssetMapper settings. tests/Functional boots a kernel with FrameworkBundle, SecurityBundle with a lazy firewall open to anonymous visitors, TwigBundle, phil/ujo-bundle and the bundle, renders the field and its label through the form theme, and calls the endpoints through the routes, signed in or not, with and without their token and its cookie. Installed on its own, where the event dispatcher is a development requirement, the functional suite is skipped.

tests/js runs the pure modules under Node's test runner: the sanitizer against the output of phil/ujo, pasted HTML of pages, Word and Google Docs, the document model, the tools and conversions, the menus, the keyboard, the labels and the double-submitted CSRF token.

From the monorepo root, then from the bundle:

vendor/bin/phpunit packages/block-editor-bundle/tests
node --import ./tests/js/register.mjs --test tests/js     # from packages/block-editor-bundle

Every line of src/ is held by the mutation bar of the monorepo: each mutant is killed.

Checks in a browser

The controller and the two modules that need the DOM — caret.js and view.js — are checked by hand in a browser, on a page with Stimulus, the stylesheet and a document holding a heading, a paragraph, a nested list, a toggle, columns and a block of another type. Each check below states what to do and what must happen.

AreaDoExpect
OpeningLoad the pageEvery block drawn; the foreign block as a card naming its type; in read-only mode no gutter
SplittingAt the end of a paragraph, EnterA new paragraph below, the caret in it, the placeholder shown
Slash menuType /tit, ↓, EnterThe menu lists the headings, the second becomes the block, the caret in it
MarksIn a new paragraph type -, a space, one, Enter, Tab, twoA bulleted list, two nested under one
Leaving a listEnter twice in an empty nested itemThe item moves out, then the list ends with a paragraph after it
ToolbarDouble-click a word, click B, click the link button, type an address, EnterThe word bold and linked, the toolbar above the selection, the input's JSON holding <b><a href="…">
Block menuClick a handle, ↓ to Quote, EnterThe menu opens on its first entry, the arrows move in it, the block becomes a quote with an author field
Undo⌘ZThe quote is a paragraph again
DragDrag a block of the toggle by its handle onto the empty columnThe block moves into the column and is selected; the toggle shows its empty button
MentionsType @a with a mention search answering two peopleA menu of the two after Searching…, Enter inserts @Ada Lovelace as a mention, typing goes on after it
PastePaste HTML with a heading, a list and a bold spanA heading, a list and a paragraph with <b> after the current block
SelectionEscape, ⌘⇧↓, ⌘D, BackspaceThe block outlined, moved down, duplicated, the copy deleted and the neighbour selected, Block deleted. announced
ImagesInsert an image block, paste an address, Insert; or drop a file with an uploaderThe image shown with its caption field; while uploading, Uploading…
SavingSubmit the formThe input holds the document without empty blocks
Writing togetherWith phil/edit-lock-bundle, two writers on one page; one types in a paragraph, then adds oneThe other sees the paragraph closed with the writer's name, its text changing, the new paragraph inserted after it, the caret of their own block untouched

Testing a form that holds a document

Submit the JSON the editor would write, and assert on the canonical form:

$form = static::getContainer()->get('form.factory')->create(ArticleType::class);
$form->submit(['body' => '{"blocks":[{"id":"a","type":"paragraph","data":{"text":"<strong>Hi</strong> <mark>x</mark>"}}]}']);

self::assertTrue($form->isValid());
self::assertSame('{"blocks":[{"id":"a","type":"paragraph","data":{"text":"<b>Hi</b> x"}}]}', $form->getData()->body); // reduced toolset

To test an uploader or a search, call it directly, or the endpoint with the editor's header:

$client->request('GET', '/_block-editor/mentions?q=ad', server: ['HTTP_X_PHIL_BLOCK_EDITOR' => '1']);