Start learning free

LESSON 146 OF 173 · BACKEND: TESTS AND RUNNING IT

Project: Test the Checkout

Practice

A test suite is a set of tests that run together, one for each thing that must keep working. The shop's checkout takes real money, so it deserves one. It is loaded for you, hidden, as app: POST /checkout takes a cart like { items: [{ product_id: 1, quantity: 2 }] }, adds up the prices from the database, charges the card through the payment provider and answers 201 with { status: "paid", total: 24 }. The two interfaces at the top of the code describe such a cart: a Cart has items, an array of CartItem objects, each with a product_id and a quantity.

A good suite tests the normal case and the edge cases, where bugs like to hide. Each test sends one request and checks the status code and the whole body. Here is one test of that shape, for a shop's product page:

test("missing product", async () => {
  const response = await client.get("/products/99");
  assert.strictEqual(response.status, 404);
  assert.deepStrictEqual(response.body, { error: "Product not found" });
});

Your suite sends three carts. A Mug (product 1) costs 12, a Pen (product 4) costs 2 and a Gift card (product 8) costs 50. The payment provider's test mode declines every payment over 1000. Work the expected answers out by hand, never with the code you are testing: a test that repeats the code's calculation repeats its bugs too.

POST /checkout  2 Mugs + 5 Pens   →  201  {"status": "paid", "total": 34}
POST /checkout  {"items": []}     →  400  {"error": "The cart is empty"}
POST /checkout  25 Gift cards     →  402  {"error": "Payment declined"}

When you run the code, the check runs your suite on the checkout, where all three tests must pass (3 tests: OK). Then it runs it on three broken copies of the checkout, and each copy must fail at least one test.

Your task: declare a variable client with let, add a test.beforeEach that stores request(app) in client, and write three tests: "checkout succeeds", "empty cart" and "declined card". Each one posts its cart to /checkout and checks the status code and the JSON body; the carts with products go in a constant cart of type Cart.


Assignment
Follow the Coding Tutorial to write a test suite for the checkout: a paid order, an empty cart and a declined card.


Hint
Every test has the same shape: post the cart with await client.post("/checkout").send(cart), then one assert.strictEqual for response.status and one assert.deepStrictEqual for response.body. Write each cart as const cart: Cart = { items: [...] };, and work out each expected total on paper first.


STEP 1 OF 12
    Ctrl + Enter to check