I have timeboxed myself to 90 minutes for this challenge. I have implemented the core requirements and had just enough time left over to implement the bonus requirement of not adding duplicate task titles and validating due date in the future, as well as tests for them. I opted for implementing validation in a middleware, as that should make it easier for adding validations to routes in future. I also added a quick .prettierrc file to ensure code formatting is consistent.
If I had more time for this, I would have spent more time focusing on code clean up, mainly around the testing structure. I feel like I could have added more tests around the validation middleware specifically. I did not have enough time to focus too much on the tests, and would like to have made sure all the edge-cases were covered, but I was able to get the core tests passing. I also noticed there were helper functions that were not being used. I also did not get to add rate limiting, or improved messaging for errors, which I feel like would be important to add in a production environment.
- π Important
- π Project Overview
- π Quick Start Guide
- π οΈ Implementation Requirements
- π§ͺ Testing Guide
- π‘ Tips for Success
- π§ AI Use
**After you complete your work, please publish it to your own git repository and share the link with the talent team. **
Welcome to the TypeScript/NodeJS interview challenge! This is a 90-minute coding exercise where you'll implement a Task Management API with CRUD operations, validation, error handling, and testing.
- Following Instructions: Complete the requirements as specified
- Clean Code: Write readable, maintainable TypeScript code
- Testing: All provided tests must pass after implementation
- NodeJS Skills: Demonstrate solid understanding of NodeJS/Express concepts
This project includes comprehensive unit and integration tests that MUST pass when you complete your implementation. The tests serve as both validation and specification for expected behavior.
If you have questions about requirements during the interview, ask your interviewer for clarification.
Good luck! π
npm install# Run the server
npm run dev
# In another terminal, test the health endpoint
curl http://localhost:3000/health
# Should return: {"status":"OK","timestamp":"..."}# Run all tests (most will fail initially - that's expected!)
npm test
# Run tests in watch mode (recommended during development)
npm run test:watch- Complete the Task interface in
src/types/task.ts - Implement one endpoint - Start with POST /api/tasks
- Run tests frequently - They guide your implementation
- Build incrementally - Make tests pass one by one
After you complete your work, please publish it to a public git repository and share the link with us.
src/
βββ types/task.ts # Complete the Task interface here
βββ controllers/ # Implement your API endpoints
βββ services/ # Business logic goes here
βββ validation/ # Joi validation schemas
βββ routes/ # Route definitions (mostly done)
βββ middleware/ # Error handling
βββ utils/ # Helper functions
βββ __tests__/ # Test files (MUST PASS!)
Complete the Task interface in src/types/task.ts:
interface Task {
id: string; // UUID
title: string; // Required, max 100 chars
description?: string; // Optional, max 500 chars
priority: 'low' | 'medium' | 'high';
status: 'pending' | 'in-progress' | 'completed';
createdAt: Date;
updatedAt: Date;
dueDate?: Date; // Optional
}Implement these endpoints in src/controllers/taskController.ts:
-
GET /api/tasks- Get all tasks- Support query parameters:
status,priority - Return tasks sorted by priority (high β medium β low) then by createdAt
- Support query parameters:
-
POST /api/tasks- Create new task- Validate input using Joi
- Auto-generate ID and timestamps
- Default status should be 'pending'
Implement input validation in src/validation/taskValidation.ts:
- Use Joi for schema validation
- Proper error messages for validation failures
Implement proper error handling:
- 400 for validation errors
- 404 for not found
- 500 for server errors
- Use the error middleware in
src/middleware/errorHandler.ts
If you finish early, you can:
Add more sophisticated validation rules:
- Prevent duplicate task titles
- Validate that due dates are in the future
- Add custom error messages for different validation failures
- Add comprehensive error logging
- Implement request rate limiting
- Add API documentation comments
- Improve the error handler with more specific error types
The project includes four test files that must all pass:
src/__tests__/validation.test.ts- Joi validation schema testssrc/__tests__/taskService.test.ts- Business logic unit testssrc/__tests__/task.test.ts- API endpoint integration testssrc/__tests__/utils.test.ts- Utility function tests
# Run all tests (must pass!)
npm test
# Watch mode for development (recommended)
npm run test:watch
# Run specific test file
npm test -- validation.test.ts
# Run with coverage
npm test -- --coverage- Start by running tests - see what's failing
- Read test names and expectations - they tell you exactly what to implement
- Implement one feature at a time - watch tests turn from red to green
- Use tests as your specification - if a test expects specific behavior, implement that exactly
// Core operations
static async createTask(data: CreateTaskRequest): Promise<Task>
static async getAllTasks(query?: TaskQueryParams): Promise<Task[]>// All should be async and use (req: Request, res: Response, next: NextFunction)
export const getAllTasks = async (req, res, next) => { ... }
export const createTask = async (req, res, next) => { ... }export const isValidUUID = (uuid: string): boolean => { ... }
export const formatDate = (date: Date): string => { ... }
export const calculateDaysDifference = (date1: Date, date2: Date): number => { ... }
export const isDateWithin24Hours = (date: Date): boolean => { ... }- Generate UUID for new tasks
- Set default status to
'pending' - Set
createdAtandupdatedAtto current timestamp - Validate all input data
- Filter by
statusandpriorityquery parameters - Sort by priority (high β medium β low) then by
createdAt - Return empty array if no tasks match filters
200- Successful GET201- Successful POST (creation)400- Validation errors500- Server errors
- Make sure you've run
npm install - Check that your import/export statements match expected interfaces
- Complete the interface definitions in
src/types/task.ts - Make sure all required properties are included
- Replace
throw new Error('Not implemented')with actual implementation - Make sure function signatures match exactly
- Check you're returning correct status codes (200, 201, 204, 400, 404)
- Make sure error responses include proper error objects
The integration tests assume you implement a way to clear test data between tests:
- Add a test-only endpoint like
DELETE /api/tasks/test-clear-all - Or modify your service to have a
clearAllTasks()method for testing - Or reset your in-memory storage between tests
β
All tests pass - This is the minimum requirement
β
Clean test output - No skipped tests, no console errors
β
Fast execution - Tests should run quickly (under 10 seconds total)
- 0-15 min: Read requirements, understand structure, plan approach
- 15-45 min: Core operations implementation (GET and POST endpoints)
- 45-75 min: Validation, error handling, make tests pass
- 75-90 min: Polish code and bonus features
- Run tests first - See what needs to be implemented
- Read test names carefully - They describe exactly what should happen
- Start with the Task interface - Many tests depend on this
- Implement validation early - Validation tests are often easiest to fix
- Use TypeScript effectively - Leverage type safety and interfaces
- Keep it simple - Focus on making tests pass with clean code
- Test frequently - Use
npm run test:watchfor immediate feedback
We are aware of what AI solutions look like, please don't submit an AI generated solution.