Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 195 additions & 0 deletions docs/SIMULATION_API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# Developer Error Simulation API

This API module is designed to help frontend and mobile developers test their applications against various failure scenarios. Instead of hoping your app handles errors correctly, you can use these endpoints to force specific errors, delays, or chaotic behavior.

**Base URL**: `/api/v1/simulation`
**Module Location**: `src/services/simulation.service.js`

> **Note**: This API is for **testing and simulation purposes only**. It should NOT be used in production environments as it intentionally generates errors and delays.

---

## 1. Random Error Generator

Get a random realistic error to test your global error handling or specific error screens.

**Endpoint**: `GET /random`

### Query Parameters

| Param | Type | Description |
| :----- | :----- | :-------------------------------------------------------------------------------- |
| `type` | string | _(Optional)_ Filter by category. See [Error Categories](#error-categories) below. |

### Examples

**Request (Any random error):**
`GET /api/v1/simulation/random`

**Response:**

```json
{
"error": true,
"type": "database",
"statusCode": 503,
"message": "DB Connection Timeout",
"hint": "Database is taking a nap (timeout). Check your connection string or network.",
"timestamp": "2026-01-26T07:15:00.000Z"
}
```

**Request (Specific category):**
`GET /api/v1/simulation/random?type=auth`

**Response:**

```json
{
"error": true,
"type": "auth",
"statusCode": 401,
"message": "Token Expired",
"hint": "Your session expired. Hit the refresh endpoint to get a shiny new token.",
"timestamp": "2026-01-26T07:16:00.000Z"
}
```

---

## 2. Custom Status Code

Force the API to return a specific HTTP status code. Useful for testing how your UI handles specific edge cases like 429 (Too Many Requests) or 418 (I'm a teapot).

**Endpoint**: `GET /custom`

### Query Parameters

| Param | Type | Description |
| :----- | :----- | :-------------------------------------------------------------------------- |
| `code` | number | **(Required)** The HTTP status code you want returned (e.g. 404, 500, 201). |

### Example

**Request:**
`GET /api/v1/simulation/custom?code=429`

**Response:**

```json
{
"statusCode": 429,
"error": true,
"type": "custom",
"message": "Simulated 429 Response",
"hint": "You asked for a 429, you got a 429.",
"timestamp": "2026-01-26T07:20:00.000Z"
}
```

---

## 3. Latency Simulation (Delay)

Simulate a slow network connection to test your loading spinners, skeleton screens, and timeout logic.

**Endpoint**: `GET /delay`

### Query Parameters

| Param | Type | Description |
| :---- | :----- | :---------------------------------------------------------------------------- |
| `ms` | number | _(Optional)_ Milliseconds to delay. Defaults to 1000ms. Max limit is 10000ms. |

### Example

**Request (Wait for 3 seconds):**
`GET /api/v1/simulation/delay?ms=3000`

**Response (Returns after 3 seconds):**

```json
{
"error": false,
"message": "Sorry for the wait! I was napping for 3000ms.",
"delay": 3000,
"timestamp": "2026-01-26T07:25:00.000Z"
}
```

---

## 4. Chaos Mode

This endpoint is for stability testing ("Chaos Engineering"). It randomly decides what to return based on a weighted probability distribution.

**Endpoint**: `GET /chaos`

### Behavior Distribution

- **40% Success**: Returns standard 200 OK.
- **40% Error**: Returns a random error from the catalog.
- **20% High Latency**: Waits between 1s and 5s, then returns success.

### Example

**Request:**
`GET /api/v1/simulation/chaos`

**Possible Response (Chaos Error):**

```json
{
"error": true,
"type": "mode_chaos_error",
"originalType": "payment",
"statusCode": 402,
"message": "Payment Required",
"hint": "Card declined or insufficient funds. Money makes the world go round.",
"timestamp": "2026-01-26T07:30:00.000Z"
}
```

**Possible Response (Chaos Success):**

```json
{
"error": false,
"type": "mode_chaos_success",
"statusCode": 200,
"message": "Survived the chaos! Operation successful.",
"timestamp": "2026-01-26T07:31:00.000Z"
}
```

---

## Error Categories

These are the valid values for the `type` parameter in the Random Error endpoint:

- `auth`: Authentication and authorization issues (401, 403).
- `database`: DB connection timeouts, duplicate entries (503, 409).
- `network`: Gateway timeouts, bad gateways (502, 504).
- `validation`: Bad requests, missing fields (400, 422).
- `payment`: Payment required, card errors (402).
- `server`: Generic internal server errors (500).

---

## Quick Test URLs (Localhost)

Copy-paste these into your browser or Postman to test immediately:

- **Random Error**: `http://localhost:3000/api/v1/simulation/random`
- **Auth Error**: `http://localhost:3000/api/v1/simulation/random?type=auth`
- **Database Error**: `http://localhost:3000/api/v1/simulation/random?type=database`
- **Force 418 (Teapot)**: `http://localhost:3000/api/v1/simulation/custom?code=418`
- **Delay (3 Seconds)**: `http://localhost:3000/api/v1/simulation/delay?ms=3000`
- **Chaos Mode**: `http://localhost:3000/api/v1/simulation/chaos`

---

## Author

Implemented by **[TABREZ RABBANI]** as a contribution to the Open Source community.
3 changes: 3 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,15 @@ import userRoutes from './routes/user.routes.js';
import productRoutes from './routes/product.routes.js';
import cartRoutes from './routes/cart.routes.js';
import paymentRoutes from './routes/payment.routes.js';
import simulationRoutes from './routes/simulation.routes.js';

app.use('/api/v1/auth', authRoutes);
app.use('/api/v1/users', userRoutes);
app.use('/api/v1/store/products', productRoutes);
app.use('/api/v1/store/cart', cartRoutes);
app.use('/api/v1/store/cart', cartRoutes);
app.use('/api/v1/payments', paymentRoutes);
app.use('/api/v1/simulation', simulationRoutes);

// // Simple route for checking server status
app.get('/', (req, res) => {
Expand Down
118 changes: 118 additions & 0 deletions src/constants/simulation.constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
export const ERROR_TYPES = {
AUTH: 'auth',
DATABASE: 'database',
NETWORK: 'network',
VALIDATION: 'validation',
PAYMENT: 'payment',
SERVER: 'server',
};

export const ERROR_CATALOG = [
// --- AUTH ERRORS ---
{
type: ERROR_TYPES.AUTH,
statusCode: 401,
message: 'Whoops! Authentication Failed.',
hint: 'Missing or invalid token. did you forget to add "Bearer <token>" in the header?',
},
{
type: ERROR_TYPES.AUTH,
statusCode: 401,
message: 'Token Expired',
hint: 'Your session expired. Hit the refresh endpoint to get a shiny new token.',
},
{
type: ERROR_TYPES.AUTH,
statusCode: 403,
message: 'Access Denied!',
hint: 'You are trying to touch something above your pay grade (insufficient permissions).',
},

// --- DATABASE ERRORS ---
{
type: ERROR_TYPES.DATABASE,
statusCode: 503,
message: 'DB Connection Timeout',
hint: 'Database is taking a nap (timeout). Check your connection string or network.',
},
{
type: ERROR_TYPES.DATABASE,
statusCode: 409,
message: 'Duplicate Entry',
hint: 'This record already exists. Unique constraint violation.',
},
{
type: ERROR_TYPES.DATABASE,
statusCode: 422,
message: 'Invalid ID Format',
hint: "That doesn't look like a valid MongoDB ObjectId.",
},

// --- NETWORK ERRORS ---
{
type: ERROR_TYPES.NETWORK,
statusCode: 504,
message: 'Gateway Timeout',
hint: 'Upstream server is ghosting us. It took too long to respond.',
},
{
type: ERROR_TYPES.NETWORK,
statusCode: 502,
message: 'Bad Gateway',
hint: "Received garbage from the upstream server. Maybe it's down?",
},
{
type: ERROR_TYPES.NETWORK,
statusCode: 503,
message: 'Service Unavailable',
hint: 'Server is overloaded or under maintenance. Try again in a bit.',
},

// --- VALIDATION ERRORS ---
{
type: ERROR_TYPES.VALIDATION,
statusCode: 400,
message: 'Validation Error',
hint: 'You missed some required fields. Check the docs!',
},
{
type: ERROR_TYPES.VALIDATION,
statusCode: 400,
message: 'Invalid Email',
hint: "That doesn't look like a real email address.",
},
{
type: ERROR_TYPES.VALIDATION,
statusCode: 422,
message: 'Weak Password',
hint: 'Password is too weak. Add some spice (special chars, numbers).',
},

// --- PAYMENT ERRORS ---
{
type: ERROR_TYPES.PAYMENT,
statusCode: 402,
message: 'Payment Required',
hint: 'Card declined or insufficient funds. Money makes the world go round.',
},
{
type: ERROR_TYPES.PAYMENT,
statusCode: 422,
message: 'Invalid Card Info',
hint: 'Check the card number, CVV or expiry. Something is off.',
},
{
type: ERROR_TYPES.PAYMENT,
statusCode: 409,
message: 'Double Charge Prevented',
hint: 'Transaction already processed. Idempotency saved you from paying twice.',
},

// --- SERVER ERRORS ---
{
type: ERROR_TYPES.SERVER,
statusCode: 500,
message: 'Internal Server Error',
hint: 'Something exploded on our end. Check the server logs.',
},
];
Loading