Automattic Code Test: Debugging an Existing Plugin and Responding to Review

Prepare for the Automattic code test with an original plugin debugging exercise, regression tests, focused patches, and evidence-based code review replies.

Author: PracHub

Published: 9/9/2026

Automattic Code Test: Debugging an Existing Plugin and Responding to Review

September 9, 2026

Quick Overview

Understand the official practical-test boundary, repair an original plugin selector, prove the regression checks, and respond constructively when review exposes another defect.

Software EngineerFree

For the Automattic code test, prepare to improve unfamiliar code and explain your decisions in writing. A useful rehearsal starts with an existing behavior, exposes a small defect, adds a regression test, and then responds to a reviewer who finds something your first patch missed. Building a large new application is not the only way to demonstrate engineering judgment.

This guide uses an original JavaScript selector from a small plugin-style project. Start with PracHub's pull-request review and improvement exercise to practice tracing code beyond the changed lines, then work through the repair below.

Evidence boundary: Automattic's official hiring page establishes the broad practical-test format. A historical candidate account supplies context, not current rules. All code, fixtures, review comments, and expected outputs here are original practice material, not an Automattic assessment solution.

Automattic code test preparation focuses on reading an existing plugin, making a focused repair, and answering review with evidence

What Automattic says about the practical test

Official information: Automattic describes a paid practical project for some roles. Engineering applicants work through a code test with an assigned buddy who reviews their work and answers questions. The page names modifications to existing code, such as WordPress plugins, and emphasizes problem solving, design, and communication rather than specific platform knowledge. How Automattic hires

The same page describes the later trial separately as a paid project of 5–40 hours. Its indicative practical-test schedule is not your personal deadline. Confirm the scope, delivery method, payment terms, and timing in your invitation; do not combine the two stages into one assumed assignment.

Historical candidate report: Mehedi Hasan Masum's February 2022 account describes an unfamiliar repository, PHP and JavaScript changes, unit tests, and a further fix after review. Its older payment description differs from the current official page. Use the account to understand collaborative iteration, not to predict today's terms. Candidate account

Two independent same-cycle reports were not established for this review. The sections below therefore teach an original preparation method rather than a universal current round sequence or grading rubric.

Read enough of the plugin to locate the contract

Before editing, find the entry point, the function that owns the behavior, its callers, and the nearest tests. Record the supported runtime and the documented test command. Run the baseline before attributing every existing failure to your changes.

Official WordPress context: Scripts are normally registered or enqueued through the appropriate WordPress hooks. The plugin's PHP integration and its browser-side JavaScript are different layers; a pure JavaScript test cannot prove that the script was correctly loaded on the intended page. WordPress script enqueuing

For our original exercise, a plugin asset selects published article cards for a topic. The rendering layer consumes the selected cards, while another component still holds the original array. That second consumer makes input ownership part of correctness even if the visible card list looks right.

Assume each card has a unique integer ID, a finite numeric day, a boolean publication flag, and an exact topic string. The selector should return at most the requested number of matching published cards, newest first. It must not reorder the caller's array. These are exercise requirements, not WordPress-wide data conventions.

Ask about missing requirements before silently choosing behavior. If two cards have the same day, which comes first? Does zero mean no cards or a default number? Questions that change an output or test are more useful than asking for an unrestricted tour of the codebase.

Reproduce a filtering bug with five cards

Use this complete original fixture. The array's initial order is intentional, because a later test will check whether the caller's input is preserved.

IDDayPublishedTopic
29trueguide
112falseguide
311truenews
410trueguide
58trueguide

The request is: select two published guide cards. The correct IDs are [4, 2]. The newest item is a draft, and the next item belongs to another topic, so neither should consume one of the two matching-card slots.

Here is the defective selector:

function selectCards(items, tag, limit = 2) {
  return items.sort((a, b) => b.day - a.day)
    .slice(0, limit)
    .filter(x => x.published && x.tag === tag);
}

It sorts all cards, takes IDs 1 and 3, and then removes both. The returned array is empty even though three matching published cards exist. This input distinguishes “two matching cards” from “matching cards among the first two items.”

An assertion expecting [4, 2] proves the defect more clearly than a screenshot showing an empty area. State the mismatch in behavior before describing the line you plan to change. That gives your reviewer an independent reason to agree with the repair.

Make a first patch, then inspect what it still breaks

Moving the filter before slice repairs the empty-result symptom. But a patch that still calls items.sort(...) first continues to reorder the array supplied by the caller. Another component may now see a different order without having requested a change.

JavaScript behavior: Array.prototype.sort() sorts its array in place. Filtering into a new array before sorting avoids changing the original array's order, though the card objects themselves remain shared references. MDN Array.sort reference

For the exercise, snapshot the input before calling the selector and compare it afterward. This is a separate assertion from checking the returned IDs. A patch can satisfy one contract while violating the other.

Do not respond by deep-cloning every object unless the contract requires independent objects. Here the function selects references and never changes card fields. Creating a new outer array is sufficient for the stated ownership boundary. Explain that limitation so a future caller does not assume edits to returned objects are isolated.

The important review habit is to inspect side effects outside the return value. A formatter, cache, shared object, event listener, or global setting can remain broken even after the visible result becomes correct.

Respond to a reviewer with a testable revision

Original reviewer comment: “The returned IDs are now correct, but this still sorts the input array. Another view owns that ordering. Also, please define the tie order and reject invalid limits rather than silently accepting a negative slice.”

A useful response identifies the oversight and names the verification you added. “Thanks, fixed” forces the reviewer to reconstruct your reasoning. A defensive explanation of why the original test did not mention mutation does not resolve the ownership problem.

Original author response: “I missed that the caller retains the input array. I moved filtering before sorting so the selector sorts a new array, added a no-mutation regression, and clarified ascending ID as the tie-breaker. Negative and fractional limits now raise an error; zero remains a valid request for no cards.”

Tie-breaking is a clarified exercise requirement, not an arbitrary production change. If the reviewer has not established that policy, ask before implementing it. A new deterministic order can be a behavior change for existing consumers even when it looks cleaner.

Original plugin review distinguishes correct selected IDs from preserved input order and defined edge cases

Read the final selector as a set of promises

The revised function makes its responsibilities visible:

function selectCards(items, tag, limit = 2) {
  if (!Number.isInteger(limit) || limit < 0) {
    throw new RangeError(
      "limit must be a nonnegative integer"
    );
  }
  return items
    .filter(x => x.published && x.tag === tag)
    .sort((a, b) => b.day - a.day || a.id - b.id)
    .slice(0, limit);
}

For the supplied fixture, it returns IDs [4, 2] and preserves the original ID sequence [2, 1, 3, 4, 5]. With two matching cards on the same day, IDs 8 and 6 return as [6, 8]. With a limit of zero, it returns an empty array.

The comparator relies on the stated numeric-field assumptions. This is not a complete validator for arbitrary API payloads. If data crosses an untrusted boundary, determine which layer validates shape and types; do not imply that a limit check validates the entire record.

For n input cards and m matches, filtering scans the input and sorting operates on the matches. It uses additional array storage rather than sorting the caller's array in place. Do not redesign it around a heap unless data size or measured performance justifies the extra complexity.

A small patch should make the behavior easier to inspect. Adding a general query language or unrelated rendering framework would make this particular repair harder to review.

Choose regression tests that can reject a bad patch

Executed practice checks: The final JavaScript implementation passed five test groups covering filtering before limiting, unchanged input order, the ID tie-breaker, empty and unmatched inputs with zero limit, and rejection of negative or fractional limits. The test runner used Node's built-in test API. Node test runner

The original and intermediate implementations are retained as negative examples. The original fails the matching-card assertion. The intermediate repair returns the expected cards but still fails the no-mutation check. Keeping those results demonstrates that the tests discriminate between the two defects.

Do not compute the expected answer by calling the production selector again. Expected IDs are small enough to derive directly from the fixture. Likewise, an input-preservation check needs a snapshot taken before the call, not a reference to the same array afterward.

These are unit-level checks of an original plugin asset. The minimal PHP enqueue skeleton was not executed inside WordPress, so this article does not claim a fully validated plugin installation. Actual integration review must still cover activation, page scoping, asset loading, rendering, and any relevant server-side boundaries.

That distinction is useful in an assessment submission: state exactly what passed, what you inspected, and what remains untested. “All tests pass” is incomplete if the only tests exercise a pure helper while the visible feature depends on other layers.

Package the work so review can continue asynchronously

Your submission should let another engineer reproduce the problem and understand the repair without arranging a call. Give the initial failing input, the intended behavior, the changed responsibility, the test command, and the remaining limitations.

Original submission note: “The card selector limited the unfiltered list and could return no matches despite eligible cards. Filtering now precedes sorting and limiting. Sorting occurs on the filtered array, preserving caller order. Tests cover the original empty result, mutation, ties, and limit boundaries. PHP activation and browser integration are not covered by this unit run.”

When review arrives, address each substantive point and distinguish completed changes from open questions. If a suggestion expands the task, explain the trade-off and ask whether it belongs in this patch. Preserve a coherent diff instead of mixing the repair with unrelated formatting or dependency upgrades.

Follow the actual invitation's rules for documentation, external help, and AI tools. A role page's general enthusiasm for tools is not permission to use them during an assessment. If assistance is allowed, you still need to understand and verify every submitted change.

Five PracHub questions for the next rehearsal

These records develop review, debugging, testing, and feedback skills across companies. They are not Automattic test questions or evidence of a guaranteed assessment format.

PracHub questionPractice focus
Review and Improve Four AI-Assisted TypeScript Pull RequestsTrace intent and surrounding code before improving a patch.
Debug and Harden a Ticketing Backend APIConnect a reproduced bug to a focused repair.
Respond Constructively to Negative FeedbackTurn a criticism into observable improvement.
Implement a simple service with testsSeparate core behavior from clarified extensions.
Validate Unit-Test Coverage and Identify Missing ScenariosIdentify what a passing test does not establish.

Use the pull-request improvement exercise to write one evidence-backed review comment and implement its smallest justified correction. Include the test that would reject your previous version.

Sources and Further Reading

Sources checked September 9, 2026. Your own invitation controls the assignment, timing, compensation, and permitted tools.


Comments (0)