This is an exercise from a company interview process for Junior full-stack developers apply.
The goal of this exercise is to create a backend module for a phone company
to list products and create orders from them.
- Retrieve the list of products present in the database.
- Retrieve a specific product.
- Place an order of products.
- Display the list of orders.
- Handle non-passing cases: what to do if the requested product does not exist ? What if the order contains products not present in the database ?
- Qualitatives tests and documentation should be written.
npm install
to install depencies.npm start
to run the PhoneCorp system. The server will listen port:4000
.npm run test
to run tests.- You can create a
.env
file and placeMONGODB_URL=
followed by your connection string provided by MongoDB to interact with your database.
- I decided to create this project trying to build some layers to be able to have a clean and maintenable code.
- I found
services
-->utils
-->controllers
-->routes
a good path to design the project pattern. - Created a
config
folder to storemongoose
connection module exports andenv
withPORT
config. - Decided to create my
services
andutils
folders intodatabase
because it interacts directly with it. - Defined my tests in two differents folders
functions
androutes
, both containsorder
andproduct
.
Routes | Methods | Function |
---|---|---|
/product/create |
POST | Create a product |
/product/stock |
GET | List all existing products sorted by brand |
/product/:id |
GET | Retrieve a product with :id |
/product/ |
GET | Handle error if :id not provided |
/order/create |
POST | Pass an order |
/order/history |
GET | List all orders sorted by date |
-
For
/product/stock
,product/
andorder/history
routes, you just have to send aGET
request.
//example body to send to create a product
{
"brand": "iPhone", // string
"model": "15 Pro Max", // string
"sku": 123456, // number
"price": 1599, // number
"quantity": 3 // number
}
http://localhost:4008/product/ folloed by existing database ID
//example body to send to create an order
// replace examples Id by existing database ID, anyway if you provide a wrong ID the response will alert you.
{
"order": [
{
"productId": "64bed8f2687ae0df0d3675fd",
"quantity": 2
},
{
"productId": "64bed8f2687ae0df0d3675fd", "quantity": 2
},
{
"productId": "64bf01c275bc8f6ff962ae34", "quantity": 2
}
]
}
- Sent all my request with
Postman
when working on the project and set up all my environment to be comfortable.
- When I created my routes i decided to handle some errors handlers :
-product/create => 400(at least 1 product information not provided / quantity ordered is < 1)
409(SKU already exists)
500(errors)
product/stock => 500(errors)
product/:id => 404(ID not found in DB)
500(error)
product/ => 400(product/:id not provided)
order/create => 400(0 product placed on order / negative product quantity ordered)
500(errors)
alert(Object.JSON response: ID doesnt exists and cannot be placed in order)
order/history => 500(errors)
- I decided to use
Jest
,SuperTest
andmongodb-memory-server
to deal with testing. - This setup is pretty efficient and not that hard to use.
- I defined 33 tests which covers all the functions / API calls and DB interactions that i found relevant to test.
- As explained you can run all tests by running
npm run test
or you can do this separately with the commands i created inpackage.json
:
npm run test:getOrder
npm run test:createOrder
npm run test:createProduct
npm run test:getProductStock
npm run test:getProductById
npm run test:productFunc
npm run test:orderFunc
- Create independents functions to handle errors in API calls.
- Upgrading the module with
product/delete
andproduct/update/:id
paths. - Create an
assets
folder containing ajson
file to store all the reusablestring
messages. - Edit the project config to be able to import with
@/whatever
instead of../../../whatever
. - Move all the functions contained in
getOrder.ts
to keep code cleaner and more maintenable. - Refactoring some parts of my code to be clearer and more modular.
- Use a Schema Validator like
Zod
to avoid some possibles issues if the app growth. - Add an Auth, Login, Register and Roles.
- Add a customer ID to track who passed orders.
- Frontend interface.
- I Improved my TypeScript's knowledges.
- I improved my vision of project architecture.
- I learned how to run tests properly and to test what seemed relevant to me.
- I learned how to write and structure a well documented
README
file. - I discovered mongodb-memory-server which is pretty good for testing interaction with database.
- Had troubles with
Jest
andTypeScript
compatibility, my tests crashed everytime. - After some investigations
i discovered that i needed to install :
babel/core
babel/preset-env
babel/preset-typescript
- Create a
babel.config.js
file and put this inside :
module.exports = {
presets: [
["@babel/preset-env", { targets: { node: "current" } }],
"@babel/preset-typescript",
],
};
- Also create a
jest.config.ts
and put this inside :
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
testEnvironment: "node",
preset: "ts-jest --config=jest.config.ts",
transformIgnorePatterns: ["/node_modules/(?!(uuid)/)"],
};
- Had troubles running
npm run test
because tests failed with this error message :
listen EADDRINUSE: address already in use :::4008
- After some investigations i discovered that i needed to mention
(require.main === module) &&
condition in myindex.ts
:
require.main === module &&
server.listen(config.port, () => {
console.log(
`โก๏ธ[server]: Server started ๐ running at http://localhost:${config.port}`
);
});
- With this condition the server won't force listening on port 4008 between each tests.
- Encountered some issues with
order/create
API Response when an order was passed. - I created a new branch, reworked my schemas and made it works properly.
- Merged it when properly fixed.
- Also had trouble trying to export functions outside of
getOrder.ts
, had a lot ofTypeScript
errors
and bugs and i lost too much time trying to clean this. - It works well like that but it's kind of dirty part of my code, i should rework this later on !
- Working on this project was really exciting !
- I tried my best but can do way better if i restart from scratch a second time.
- But I had to make choices because i lost a lot of times trying to refactor and deal with errors.
- I started by establishing a little sketch on
Excalidraw
and took some notes to define the logic, structure and path i wanted to create. - I improved my skills working on this project and i consider this as a really good point for me.
- A little bit frustrated to had no time to create a little frontend interface to have something to show.