You've been tasked with building a new "cards" service for the front-end of the Moonpig website. This exercise requires building a simple REST-like API with two endpoints - one for returning a list of cards and another that returns a single instance of a card.
We have provided three JSON files that serve as source data - you can find them at the following URLs:
- https://moonpig.github.io/tech-test-node-backend/cards.json
- https://moonpig.github.io/tech-test-node-backend/sizes.json
- https://moonpig.github.io/tech-test-node-backend/templates.json
Please treat these as a remote data source, rather than manually downloading and integrating into your application locally.
This endpoint returns a list of cards.
imageUrl
should be the image found on the template that corresponds to the first page for the card.url
should have the format/cards/[id]
Expected JSON response from GET /cards
:
[
{
"title": "card 1 title",
"imageUrl": "/front-cover-portrait-1.jpg",
"url": "/cards/card001"
},
{
"title": "card 2 title",
"imageUrl": "/front-cover-portrait-2.jpg",
"url": "/cards/card002"
},
{
"title": "card 3 title",
"imageUrl": "/front-cover-landscape.jpg",
"url": "/cards/card003"
}
]
This endpoint returns a single card identified by its id
. It takes an optional route parameter sizeId
- the sizing of a card affects its price.
price
is calculated by the multiplying thebasePrice
of the card by thepriceMultiplier
from the selected size. If no size is provided it should default to thebasePrice
. ThebasePrice
is the amount in pence and the result should be formatted as a string e.g."£2.00"
.
Expected JSON response from GET /cards/card001/gt
:
{
"title": "card 1 title",
"size": "gt",
"availableSizes": [
{
"id": "sm",
"title": "Small"
},
{
"id": "md",
"title": "Medium"
},
{
"id": "gt",
"title": "Giant"
}
],
"imageUrl": "/front-cover-portrait-1.jpg",
"price": "£4.00",
"pages": [
{
"title": "Front Cover",
"width": 300,
"height": 600,
"imageUrl": "/front-cover-portrait-1.jpg"
},
{
"title": "Inside Left",
"width": 300,
"height": 600,
"imageUrl": ""
},
{
"title": "Inside Right",
"width": 300,
"height": 600,
"imageUrl": ""
},
{
"title": "Back Cover",
"width": 300,
"height": 600,
"imageUrl": "/back-cover-portrait.jpg"
}
]
}
An app skeleton is provided for your convenience. It consists of the following tools:
- Express
- Jest for unit/integration testing
- Supertest for integration tests
- TypeScript - If you're not familiar with TypeScript you can use JavaScript instead.
Command | Description |
---|---|
yarn dev |
run the server in development (watch) mode on port 7000 |
yarn test |
run tests using Jest watch mode |
We will assess the task based on the following criteria:
- How clean, modular and extensible the code is
- Considerations for performance
- Approach to testing
- Knowledge of Node and its APIs
- Use of Git
We have provided a notes file NOTES.md
for any notes that you wish to add that could help your application such as explaining why you've made certain decisions or any incomplete aspects of your solution.
Please note we appreciate that your free time is important and feel that doing less "well" is preferable to doing more "less well". With this in mind if you feel that your code is unfinished please leave some notes explaining what you'd do given more time. We'll be more than happy to review this.
For your convenience we've made this a template repository so you can easily create a private copy.
Please commit frequently so we can see your approach and ensure you submit the .git folder alongside your code. When it comes to submission please follow the instructions provided in the email you were sent.