CoderX

Full-Stack Practice Challenges

Pick a real-world React & Express challenge, fix buggy code, and execute tests directly in your browser using WebContainers.

1.Rapid Counter — Stale State Updates

#debug#react

The counter contains an Increment by 3 button. A single click should increase the current count by exactly three. The current implementation calls the state setter three times, but the displayed count only increases by one. It also produces incorrect values after repeated clicks. Debug the component so that: - Initial count is 0. - One click increases the count to 3. - Two clicks result in 6. - Updates always use the latest counter value.

3 Testseasy

2.Broken Product Search

#react#debug

The page displays a list of products and provides a search box. The product list is displayed correctly when the component first loads, but entering text into the search field doesn't update the displayed results. Users should be able to search regardless of capitalization. **Fix the implementation so that:** - All products appear initially. - Searching `"lap"` displays only Laptop. - Search is case-insensitive. - Clearing the input restores all products. - A search with no matches displays the empty-state message.

5 Testseasy

3.Todo That Refuses to Update

#react#debug

The Todo application renders several tasks with a Toggle button beside each task. Clicking Toggle is supposed to switch a task between incomplete and completed. The state appears to be modified internally, but the UI doesn't reliably update. Fix the component while preserving the existing functionality. #Requirements: - Three todos should render initially. - Tasks start as incomplete. - Clicking a task's button marks only that task complete. - Clicking the same task again marks it incomplete. - Other tasks must not be affected.

4 Testseasy

4.Resize Listener Gone Wild

#react#debug

This component tracks how many browser resize events have occurred. Initially it seems to work correctly. However, after the component updates, resize events begin increasing the counter more than once per event. For example: ``` First resize -> 1 Second resize -> 3 Third resize -> unexpected... ``` A single browser event should cause exactly one state update. Fix the component so that: - The count starts at 0. - One resize increases it to 1. - Every additional resize increments it by exactly one. - The component doesn't accumulate duplicate event listeners.

3 Testseasy

5.Reordering Items Mixes Up Their State

#react#debug

The application displays three selectable developers. Each row maintains its own selected state. The user can also reverse the order of the developers. Selecting a developer works correctly until the list is reordered. After reversing the list, the selected state can appear on the wrong developer. For example: - Select `Alice`. - Alice correctly shows `Selected`. - Reverse the list. - Alice should still be selected. - Instead, another developer may now appear selected. Fix the rendering logic so component state stays associated with the correct developer when the list order changes.

4 Testsmedium

6.Product Ranking Dashboard

#state#array sorting#immutability

An analytics dashboard displays products with their sales count and rating. Users can sort products using: - Top Selling — highest sales first - Highest Rated — highest rating first The current implementation has a bug: sorting appears to work sometimes, but switching between sorting modes produces incorrect results because the original product array is being mutated. Fix the application so both sorting modes work correctly and repeatedly.

5 Testsmedium

7.Shopping List Manager

#controlled input#state updates#validation

The Shopping List lets users enter an item and add it to their list. There's a bug in the current application: New items replace existing items instead of being appended. Whitespace-only values can also be added. Fix the component so that: - The list starts empty. - New items are appended. - Existing items remain. - The input clears after adding. - Blank or whitespace-only items aren't added.

5 Testseasy

8.Course Navigator

#state#boundaries#navigation

A learning platform displays one lesson at a time. Students can use: - Previous - Next - Start Over The navigation currently contains several off-by-one bugs. Fix it so users cannot navigate outside the available lessons.

6 Testsmedium

9.Debug the Todo REST API

#express#rest-api#routing

You are given an existing Express Todo API that is almost complete, but several bugs are causing incorrect behavior. Your task is to debug the existing implementation so that all Todo endpoints behave correctly and follow proper REST API conventions. The API stores todos in memory. Each todo has the following structure: ```javascript { id: 1, title: "Learn Express", completed: false } ``` The API must support: - `POST /todos` — Create a new todo. - `GET /todos` — Return all todos. - `GET /todos/:id` — Return a specific todo. - `PATCH /todos/:id` — Partially update an existing todo. - `DELETE /todos/:id` — Delete an existing todo. ##Expected behavior `POST /todos` - `title` is required. - An empty or whitespace-only title is invalid. - `completed` is optional and should default to `false`. - A successfully created todo should return 201 Created. - Every newly created todo must receive a unique ID. `GET /todos` - Should return *200 OK*. - The response body should be an array containing all todos. `GET /todos/:id` - Should return *200 OK* when the todo exists. - Should return *404 Not Found* when it does not exist. `PATCH /todos/:id` - Should update only the fields provided in the request body. - Existing values must not be overwritten when a field is omitted. - If `title` is provided, it must not be empty or whitespace-only. - Should return `404 Not Found` when the todo does not exist. `DELETE /todos/:id` - Should remove the todo. - Should return *204 No Content* after successful deletion. - Should return *404 Not Found* when the todo does not exist. Several issues are hidden throughout the existing code. Fix the implementation without modifying the tests.

13 Testseasy

10.User CRUD API — Part 1: Create, Update, Delete & Email Uniqueness

#express#rest-api#crud

User CRUD API — Part 1 You're building the core of a **User Management REST API** using Express. There's no real database — user data is stored in an in-memory array that acts as a mock DB for this exercise. The API should let clients **create**, **update**, and **delete** users, while enforcing **email uniqueness** across all users. Endpoints to implement | Method | Route | Description | |--------|----------------|-----------------------------------------------| | GET | `/` | Health check | | POST | `/users` | Create a new user | | GET | `/users/:id` | Fetch a single user by id | | PUT | `/users/:id` | Update a user's name and/or email | | DELETE | `/users/:id` | Delete a user | Business rules - **Create (`POST /users`)** - `name` and `email` are required in the request body. - If either is missing, respond with `400` and `{ "message": "Name and email are required" }`. - If the email is **already registered** by another user, respond with `409` and `{ "message": "Email already registered" }`. - On success, respond with `201` and the newly created user object (`id`, `name`, `email`). - **Read (`GET /users/:id`)** - Return the matching user with `200`. - If no user exists with that id, respond with `404` and `{ "message": "User not found" }`. - **Update (`PUT /users/:id`)** - Accepts `name` and/or `email` in the body — only provided fields should be updated. - If the user doesn't exist, respond with `404`. - If the new email is already taken **by a different user**, respond with `409`. Updating a user with **their own current email** (i.e. no real change) must **not** be treated as a conflict. - On success, respond with `200` and the updated user object. - **Delete (`DELETE /users/:id`)** - Removes the user from the store and responds with `204` (no body). - If the user doesn't exist, respond with `404`. Notes - No database, no auth, no persistence — everything lives in memory for the lifetime of the process. - Email comparisons should be treated as case-insensitive.

6 Testsmedium

11.E-commerce Backend: Broken Checkout Flow

#express#rest-api#authentication

E-commerce Backend: Broken Checkout Flow You've inherited a small e-commerce backend built with Express. It exposes endpoints for user authentication, browsing products, managing a shopping cart, and placing orders — but the checkout flow has been misbehaving in QA, and a few other rough edges have been reported. Your job is **not** to redesign anything. The architecture, routes, and response shapes are all intentional. Find and fix the bugs so the existing test suite (`app.test.js`) passes. Project structure - `index.js` — starts the server (do not modify) - `constants.js` — shared config values (JWT secret, etc.) - `db.js` — in-memory data store (users, products, carts, orders) - `middleware/auth.js` — JWT-based authentication middleware - `app.js` — the Express app: routes for auth, products, cart, and orders - `app.test.js` — the test suite your solution must satisfy (do not modify) Data model **Product** ```json { "id": 1, "name": "Wireless Mouse", "price": 25.99, "stock": 10 } ``` **Cart item** (stored per user) ```json { "productId": 1, "quantity": 2 } ``` **Order** ```json { "id": 1, "userId": 1, "items": [{ "productId": 2, "name": "Mechanical Keyboard", "quantity": 2, "price": 79.99 }], "total": 159.98, "createdAt": "2026-08-21T10:00:00.000Z" } ``` Endpoints Auth - `POST /auth/register` — `{ username, password }` → `201` with `{ id, username }`. `400` if fields are missing, `409` if the username is taken. - `POST /auth/login` — `{ username, password }` → `200` with `{ token }`. `401` on bad credentials. Products - `GET /products` → `200` with `{ products }`. - `GET /products/:id` → `200` with the product, or `404` if it doesn't exist. Cart (requires `Authorization: Bearer <token>`) - `GET /cart` → `200` with `{ cart }` for the authenticated user only. - `POST /cart` — `{ productId, quantity }` → `201` with the updated cart. Adding a product already in the cart should **increase** its quantity, not overwrite it. `404` if the product doesn't exist. - `DELETE /cart/:productId` → `200` with the updated cart, or `404` if the item isn't in the cart. Orders (requires `Authorization: Bearer <token>`) - `POST /orders` — creates an order from the authenticated user's current cart, decrements product stock, and clears the cart. `400` if the cart is empty. **An order must never be created if it would take any product's stock below zero.** - `GET /orders` → `200` with `{ orders }` for the authenticated user only. Notes - Carts and orders are scoped per user — one user should never see or affect another user's cart. - Passwords must never be returned in API responses, and must be verified securely, not compared as plain strings. - Order totals must reflect quantity, not just unit price. - Everything you need is already installed in the environment (`express`, `bcrypt`, `jsonwebtoken`, `jest`, `supertest`). No `package.json` changes needed.

22 Testshard

12.HTTP Key-Value Store

#rest api#key-value store#classes

Build a simple **in-memory key-value store** and expose it through an Express HTTP API. The goal of this challenge is to practice: - Creating and using JavaScript classes - Designing REST-style HTTP endpoints - Working with Express route parameters - Handling JSON request bodies - Returning appropriate HTTP status codes - Connecting a simple frontend interface to an API --- Requirements 1. KeyValueStore Class Create a `KeyValueStore` class inside `store.js`. Each instance should maintain its own in-memory collection of key-value pairs. Implement the following methods: `set(key, value)` Stores a value under the provided key. If the key already exists, its value should be replaced. ```js store.set("name", "Alice"); ```` --- `get(key)` Returns the value associated with the key. If the key does not exist, return `undefined`. ```js store.get("name"); ``` --- `delete(key)` Deletes the key from the store. Return: * `true` if the key existed and was deleted * `false` if the key did not exist --- `has(key)` Returns `true` if the key exists and `false` otherwise. --- `getAll()` Returns an object containing every key-value pair currently stored. Example: ```json { "name": "Alice", "language": "JavaScript" } ``` --- HTTP API Create an Express application in `app.js`. The server must support the following endpoints. Set a value `PUT /store/:key` Request body: ```json { "value": "Alice" } ``` Successful response: **Status:** `200` ```json { "key": "name", "value": "Alice" } ``` The `value` property is required. If it is missing, return: **Status:** `400` ```json { "error": "Value is required" } ``` --- Get a value `GET /store/:key` If the key exists: **Status:** `200` ```json { "key": "name", "value": "Alice" } ``` If the key does not exist: **Status:** `404` ```json { "error": "Key not found" } ``` --- Delete a value `DELETE /store/:key` If the key exists and is deleted: **Status:** `200` ```json { "message": "Key deleted" } ``` If the key does not exist: **Status:** `404` ```json { "error": "Key not found" } ``` --- Get all values `GET /store` Return all currently stored key-value pairs. **Status:** `200` Example: ```json { "name": "Alice", "language": "JavaScript" } ``` --- Web Interface A frontend interface is provided in `index.html`. Your Express application must serve this file when a user visits: `GET /` The page interacts with the API that you build. --- Important Notes * Store all data **in memory**. * Do not use a database. * Your key-value store must be implemented using a **class**. * Export the `KeyValueStore` class from `store.js`. * Export the Express application from `app.js`. * Do not call `app.listen()` inside `app.js`. * `index.js` already starts the server for you. * Data does not need to survive a server restart.

6 Testsmedium

13.Persistent Tab Form

#react#hooks#usestate

Persistent Tab Form Build a reusable React tabbed form where users can switch between multiple tabs without losing the information they have already entered. The form contains multiple tabs representing different sections of a profile: - **Personal** — Name and email - **Address** — City and postal code - **Preferences** — Job title and experience Users should be able to freely switch between tabs while filling out the form. Any information entered into one tab must remain intact when the user navigates to another tab and then returns. Current Problems The existing implementation has several bugs related to React state management and controlled form inputs. Your task is to debug the implementation so that: 1. Switching between tabs does not reset the fields in the previous tab. 2. Text entered into each field remains available after switching tabs. 3. Each input correctly reflects its current value. 4. Updating a field does not accidentally overwrite values from other fields. 5. Switching tabs only changes the visible section and does not reset the form state. 6. The active tab is correctly highlighted. 7. The correct tab content is displayed after switching. 8. All form fields remain controlled React inputs. 9. Empty fields are preserved when navigating between tabs. Expected Behavior For example: 1. Open the **Personal** tab. 2. Enter `John` into the name field. 3. Enter `john@example.com` into the email field. 4. Switch to **Address**. 5. Enter `Hyderabad` as the city. 6. Switch back to **Personal**. 7. `John` and `john@example.com` should still be present. 8. Switch back to **Address**. 9. `Hyderabad` should still be present. The same behavior should work for every tab and every form field. Requirements - Use React state to maintain the form data. - Keep the form state at a level that survives tab switching. - Do not rely on the DOM to preserve input values. - Do not use page reloads or browser storage to solve the problem. - Switching tabs must not reset previously entered values. - The component should remain reusable and maintainable. Files to Modify Modify the provided React component implementation to fix the broken behavior. Do **not** modify the test files. Acceptance Criteria The solution is correct when: - All tabs can be switched between freely. - No previously entered value is lost. - Each field maintains its own value. - Editing one field does not clear or overwrite unrelated fields. - The active tab always displays the correct content. - All provided tests pass.

9 Testsmedium

14.React Pagination

#react#pagination#state

**You are building an admin dashboard view that displays a large set of mock inventory items. The current implementation fetches/loads all 32 items at once and renders them in a raw list, leading to poor visual organization.** Your task is to implement full client-side pagination inside `src/PaginatedList.jsx`. **Current Problems & Requirements:** 1. **Page Sizing & Slicing**: * Calculate total pages using `Math.ceil(items.length / pageSize)`. * Display only the items belonging to the current page. * Items are 1-indexed for display. Page `1` with `pageSize = 5` should show items from index `0` to `4`. 2. **Page Controls**: * Render **Previous** and **Next** buttons. * Disable the **Previous** button when on the first page (`page === 1`). * Disable the **Next** button when on the last page (`page === totalPages`). * Render numbered page buttons from `1` to `totalPages`. The active page button must have the class `active`. 3. **Page Size Selector**: * Render a `<select>` dropdown with options `[5, 10, 20]`. * Changing the page size should reset the current page back to `1`. 4. **State Boundaries & Edge Cases**: * Display a message reading `"No items found"` when the `items` prop array is empty. * Handle page navigation bounds cleanly so users cannot navigate to invalid page numbers. **Files to Edit:** * `src/PaginatedList.jsx` **Acceptance Criteria:** * Only the sliced items for the current page are rendered inside `ul.item-list`. * Changing pages via Previous/Next or numbered buttons updates the items correctly. * Adjusting the page size dropdown resets current page state back to `1` and updates items shown. * Buttons reflect correct `disabled` attributes at lower and upper page boundaries.

7 Testsmedium

15.Implement an In-Memory Redis Server with Expiration & LRU Eviction

#express#backend#cache

Mini Redis API (LRU Cache & TTL Engine) You are tasked with building a lightweight, in-memory **Mini Redis API** using Express. The application should act as a key-value store supporting string operations, Time-To-Live (TTL) expiration, and Least Recently Used (LRU) capacity eviction. Currently, the server routing, storage engine, and command handlers are non-functional or incomplete. None of the test cases are passing. Requirements Implement the API endpoints in `src/cacheEngine.js` and `src/app.js` to satisfy the following requirements: 1. Basic Key-Value Operations - **`POST /api/set`**: Accepts `{ "key": string, "value": string, "ttl": number (optional) }`. - Stores the key-value pair. - If optional `ttl` (in seconds) is provided, sets an expiration timer for that key. - Returns status `200` with `{ "success": true, "key": string }`. - Returns status `400` if `key` or `value` is missing/invalid. - **`GET /api/get/:key`**: - If the key exists and is **not expired**, returns status `200` with `{ "key": string, "value": string }`. - Reading a key marks it as **recently used** (updates LRU order). - If the key does not exist or has expired, returns status `404` with `{ "error": "Key not found" }`. - **`DELETE /api/del/:key`**: - Removes the key from the cache. - Returns status `200` with `{ "success": true, "deleted": true }` if key existed, or `{ "success": false, "deleted": false }` if key was not found. 2. TTL & Expiration Handling - **`POST /api/expire`**: Accepts `{ "key": string, "seconds": number }`. - Sets/updates expiration timeout on an existing key. - Returns status `200` with `{ "success": true }` if key exists. - Returns status `404` with `{ "error": "Key not found" }` if key does not exist or is already expired. - **`GET /api/ttl/:key`**: - Returns remaining TTL in seconds: status `200` with `{ "key": string, "ttl": number }`. - If key exists but has no expiration, return `{ "key": string, "ttl": -1 }`. - If key does not exist or is expired, return status `404` with `{ "error": "Key not found" }`. 3. LRU Eviction Policy - The cache has a fixed capacity limit configured via environment variable `CACHE_CAPACITY` (default to **3** if not set or invalid). - When a new key is inserted via `/api/set` and capacity is reached, the **Least Recently Used (LRU)** non-expired key must be evicted. - Updating an existing key's value via `/api/set` updates its value/TTL and marks it as recently used, but does **not** increase total count or trigger eviction. - Any access (`GET /api/get/:key`) marks the key as recently used. --- Instructions 1. Edit **`src/cacheEngine.js`** to build the underlying `LRUCache` data structure and expiration logic. 2. Edit **`src/app.js`** to hook up the HTTP routes to your cache engine. 3. Ensure all tests in `tests/redis.test.js` pass. Files to Edit - `src/cacheEngine.js` - `src/app.js`

8 Testshard
Showing 15 of 64 challenges
Scroll down to automatically load more