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.
console.log(Number.isInteger(0));
console.log(Number.isInteger("0"));Check your prediction
true
falseA 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 try | What your result should demonstrate |
|---|---|
| Numeric zero quantity | Accept it as a valid amount |
| Text quantity or malformed body | Reject as domain failure |
| Rejected transport or non-success HTTP status | Observe 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
Checkpoint: Stock Adapter: practise
Implement loadStock. Print 0 for a valid body and Invalid stock for a string quantity.
// 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 stockAdd 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?
Completion is saved in this browser only. It does not measure mastery.