Build a Chainable Rectangle Manipulation API

Quick Overview

Build a chainable JavaScript API that selects page rectangles, changes color, waits, and shifts them in the order written. Examine fluent state, ordered asynchronous effects, chain error behavior, DOM isolation, cancellation choices, and deterministic testing.

Build a Chainable Rectangle Manipulation API

Company: Robinhood

Role: Frontend Engineer

Category: Software Engineering Fundamentals

Difficulty: medium

Interview Round: Technical Screen

## Build a Chainable Rectangle Manipulation API You are given a page containing a 3-by-3 grid of rectangle elements and a JavaScript class whose methods are empty. Implement a fluent API that can select a rectangle, change its color, wait, and shift it horizontally while preserving the order written in the chain. Representative usage: ```javascript const rectangles = new RectanglesClass(document); rectangles .selectById(13) .color("red") .afterDelay(500) .shiftByPx(10) .color("green"); await rectangles.finished(); ``` Assume each rectangle has a unique `data-rectangle-id` attribute. `shiftByPx(delta)` adds `delta` to that rectangle's accumulated horizontal shift. `finished()` is a test hook that returns a promise for all actions appended so far. ### Constraints & Assumptions - `selectById`, `color`, `afterDelay`, and `shiftByPx` must return the same class instance immediately so calls remain chainable. - Actions execute in chain order. The delay pauses later actions in this chain but does not block the browser's main thread. - A later `selectById` changes the target only when that queued selection step executes. - A missing rectangle or an action with no selected rectangle rejects the chain; later queued actions do not run. - Separate class instances must not share queue or selection state. ### Clarifying Questions to Ask - Should a failed chain be reusable, or should the caller create a new instance? - May two independent chains manipulate the same rectangle, and if so, which ordering guarantee is expected between them? - Should shifting preserve other CSS transforms, or may this exercise own the element's horizontal transform? ### Part 1 — Define the Fluent State Choose the minimal instance state needed to track the selected rectangle, accumulated shifts, and unfinished work. Explain why every mutating method returns synchronously even though its action may run later. #### What This Part Should Cover - Per-instance selection and promise-tail state. - A small helper that appends one action and returns `this`. - Selection evaluated in queue order rather than at method-call time. ```hint Distinguish building from running Each method call records one future step; the returned object and the eventual completion value serve different purposes. ``` ### Part 2 — Preserve Delay and Mutation Order Implement the four chainable methods so the example turns the rectangle red, waits about 500 milliseconds, shifts it, and only then turns it green. #### What This Part Should Cover - Promise composition or another non-blocking serial queue. - A delay represented as a queued promise, not an independent timer around one mutation. - DOM reads and writes performed when their step reaches the head of the queue. ```hint Attach every step to one tail A timer that is launched separately can finish after a later color call; make it part of the same dependency chain. ``` ### Part 3 — Handle Errors and Make It Testable Show how `finished()` reports success or failure. Describe tests for immediate actions, delayed order, repeated shifts, changing selections, missing elements, and isolation between instances. #### What This Part Should Cover - Rejection propagation through later queued work. - Deterministic tests using a short or fake timer and observable DOM state. - A documented policy for whether an instance can recover after failure. ```hint Observe intermediate state The strongest delay test checks the color before the timer resolves as well as the final state afterward. ``` ### What a Strong Answer Covers - A genuinely chainable API whose asynchronous execution order matches source order. - DOM mutations applied to the selection active at each queued step. - Non-blocking delay handling, cumulative movement, explicit failures, and instance isolation. - Tests that would catch detached timers, eager selection, and swallowed promise rejections. ### Follow-up Questions 1. How would you add cancellation without leaving half of a chain running? 2. What changes if several chains must share one global ordering for a rectangle? 3. How would you preserve an element's existing rotate or scale transform while shifting it? 4. How would you expose progress without allowing callers to mutate the internal queue?

Quick Answer: Build a chainable JavaScript API that selects page rectangles, changes color, waits, and shifts them in the order written. Examine fluent state, ordered asynchronous effects, chain error behavior, DOM isolation, cancellation choices, and deterministic testing.

|Home/Software Engineering Fundamentals/Robinhood
Robinhood logo
Robinhood
Jul 18, 2026, 12:00 AM
mediumFrontend EngineerTechnical ScreenSoftware Engineering Fundamentals
1
0

Build a Chainable Rectangle Manipulation API

You are given a page containing a 3-by-3 grid of rectangle elements and a JavaScript class whose methods are empty. Implement a fluent API that can select a rectangle, change its color, wait, and shift it horizontally while preserving the order written in the chain.

Representative usage:

const rectangles = new RectanglesClass(document);

rectangles
  .selectById(13)
  .color("red")
  .afterDelay(500)
  .shiftByPx(10)
  .color("green");

await rectangles.finished();

Assume each rectangle has a unique data-rectangle-id attribute. shiftByPx(delta) adds delta to that rectangle's accumulated horizontal shift. finished() is a test hook that returns a promise for all actions appended so far.

Constraints & Assumptions

  • selectById , color , afterDelay , and shiftByPx must return the same class instance immediately so calls remain chainable.
  • Actions execute in chain order. The delay pauses later actions in this chain but does not block the browser's main thread.
  • A later selectById changes the target only when that queued selection step executes.
  • A missing rectangle or an action with no selected rectangle rejects the chain; later queued actions do not run.
  • Separate class instances must not share queue or selection state.

Clarifying Questions to Ask Guidance

  • Should a failed chain be reusable, or should the caller create a new instance?
  • May two independent chains manipulate the same rectangle, and if so, which ordering guarantee is expected between them?
  • Should shifting preserve other CSS transforms, or may this exercise own the element's horizontal transform?

Part 1 — Define the Fluent State

Choose the minimal instance state needed to track the selected rectangle, accumulated shifts, and unfinished work. Explain why every mutating method returns synchronously even though its action may run later.

What This Part Should Cover Guidance

  • Per-instance selection and promise-tail state.
  • A small helper that appends one action and returns this .
  • Selection evaluated in queue order rather than at method-call time.

Part 2 — Preserve Delay and Mutation Order

Implement the four chainable methods so the example turns the rectangle red, waits about 500 milliseconds, shifts it, and only then turns it green.

What This Part Should Cover Guidance

  • Promise composition or another non-blocking serial queue.
  • A delay represented as a queued promise, not an independent timer around one mutation.
  • DOM reads and writes performed when their step reaches the head of the queue.

Part 3 — Handle Errors and Make It Testable

Show how finished() reports success or failure. Describe tests for immediate actions, delayed order, repeated shifts, changing selections, missing elements, and isolation between instances.

What This Part Should Cover Guidance

  • Rejection propagation through later queued work.
  • Deterministic tests using a short or fake timer and observable DOM state.
  • A documented policy for whether an instance can recover after failure.

What a Strong Answer Covers Guidance

  • A genuinely chainable API whose asynchronous execution order matches source order.
  • DOM mutations applied to the selection active at each queued step.
  • Non-blocking delay handling, cumulative movement, explicit failures, and instance isolation.
  • Tests that would catch detached timers, eager selection, and swallowed promise rejections.

Follow-up Questions Guidance

  1. How would you add cancellation without leaving half of a chain running?
  2. What changes if several chains must share one global ordering for a rectangle?
  3. How would you preserve an element's existing rotate or scale transform while shifting it?
  4. How would you expose progress without allowing callers to mutate the internal queue?
Loading comments...