Checkpoint: Stock Adapter

The Course
•
4 min read

A small external boundary

Write loadStock(request). Request /stock, reject a non-ok response with an HTTP status message, parse its JSON, require a non-array object with nonnegative integer quantity, and return that quantity. Reject malformed data with “Invalid stock”. Do not coerce numeric strings.

Test valid zero, a normal quantity, an HTTP failure, wrong-shaped JSON, and a request rejection. Your request double must expose the fields your adapter uses. It does not have to reimplement the entire browser Response class.

Plan the three stages before coding. Keep existing stock in the caller until the complete adapter succeeds. This is the same safety rule as book loading, transferred to a different domain. Use the 15-minute block for a first attempt and tests; revisit validation if your type guards are still guesses.

Predict and trace

Write the output before running. Follow the values through each call; if your prediction differs, identify the first step that surprised you.

Predict, then run JavaScript
console.log(Number.isInteger(0));
console.log(Number.isInteger("0"));
Check your prediction
true
false

A numeric-looking string is not the numeric quantity promised by this contract.

Acceptance cases before you code

Write a small test plan before implementing injected stock boundary. These cases extend the brief; they are not a second worked solution. Predict the expected behavior independently, then test through the public function. A good ordinary example and a good boundary example should catch different possible mistakes.

Case to tryWhat your result should demonstrate
Numeric zero quantityAccept it as a valid amount
Text quantity or malformed bodyReject as domain failure
Rejected transport or non-success HTTP statusObserve the correct service boundary

After the core task passes, deliberately break one rule and identify the case that notices it. Restore the implementation and explain the failure in terms of the contract, not the number of assertions. If a case requires a concept you have not recalled, revisit the relevant lesson before opening the solution.

Build it yourself

Exercise

Checkpoint: Stock Adapter: practise

Implement loadStock. Print 0 for a valid body and Invalid stock for a string quantity.

Your working space JavaScript
// The request function returns a response-shaped object.
Hint 1: the idea

Check response.ok before consuming its body; validate the parsed value before returning quantity.

Hint 2: a first step

Reuse the null/object/array/type guard pattern from today.

Show one solution
async function main() {
  async function loadStock(request) {
    const response = await request("/stock");

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }

    const body = await response.json();

    if (
      body === null ||
      typeof body !== "object" ||
      Array.isArray(body) ||
      !Number.isInteger(body.quantity) ||
      body.quantity < 0
    ) {
      throw new Error("Invalid stock");
    }

    return body.quantity;
  }

  console.log(
    await loadStock(async () => ({
      ok: true,
      json: async () => ({ quantity: 0 })
    }))
  );

  try {
    await loadStock(async () => ({
      ok: true,
      json: async () => ({ quantity: "0" })
    }));
  } catch (error) {
    console.log(error.message);
  }
}

main();
0
Invalid stock

Add the remaining cases from the brief. Make a 503 double whose json method throws if called; your adapter should report HTTP 503 without reading that body.

Test a changed requirement

Add the remaining cases from the brief. Make a 503 double whose json method throws if called; your adapter should report HTTP 503 without reading that body.

Explain before moving on

Which failure paths are asynchronous? What guarantees does successful status alone not provide?

Was this article helpful?

Your response is saved on this device.