From b139c7a3106c6dbeeb082e1ab99c65216db57ef5 Mon Sep 17 00:00:00 2001 From: Pedro Pires Date: Sat, 25 Nov 2023 00:22:25 +0000 Subject: [PATCH] Added: Documentation Added: Documentation on routes Added: Documentation on tests Updated: Readme file --- README.md | 102 +++++++++++++++++++++++++++++++++++------- __test__/math.test.ts | 27 ++++++++++- index.ts | 39 ++++++++++++++-- math.handler.ts | 12 ++++- package.json | 8 +++- server.ts | 9 ++++ 6 files changed, 173 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index c1840d4..c2a5083 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,127 @@ # simple-math-api-exercise -Node.js + express + typescript math api +Node.js + Express + TypeScript math api Here's a skeleton for us to clone in the 6th fCC meetup in Ikea +## Development + +This project requires Node.JS installed, a javascript runtime that runs code +inside a v8 engine without a browser. See more on how to install it at +[nodejs.org](https://nodejs.org/en). + Clone it and start from there. ```sh +git clone https://github.com/Unisergius/simple-math-api-exercise.git +# or over ssh +git clone git@github.com:Unisergius/simple-math-api-exercise.git +``` + +To install this project's dependencies, you have to run the following command +from a terminal inside the project's directory. + +```sh +# change into the git's directory if needed +cd simple-math-api-exercise +# install dependencies npm install ``` -Installs node_modules folder, what some may know it for vendors folder. Express, dotenv, typescript and all its dependencies are installed. +This installs the node dependencies into the node_modules directory, what some +may know them as vendors folder. -Useful links: +The dependencies for this project are bellow with a few links on how they work +and their documentaion: * [Express 4 API](https://expressjs.com/en/4x/api.html) +* [TypeScript](https://www.typescriptlang.org/) +* [Jest 29.5 Docs](https://jestjs.io/docs/29.5/getting-started) -Compile typescript to dist folder +Node.js executes JavaScript code, but as you can see this project uses +TypeScript as its scripting language. What this means is that our code is type +checked using TypeScript but needs to be compiled for Node.js to be able to +read our code. + +To compile the code to JavaScript you can run the build command using npm. This +is actually running the TypeScript compiler using `tsc`, the reason to not +directly run the `tsc` command is that you may not have TypeScript installed +globally in your system. This is actually good since it forces your machine to +run the TypeScript compiler for the verison defined in the dependencies. ```sh npm run build ``` -Run test +Our server is written is Express, a Node.js library that facilitates the +handling of http requests to a server in JavaScript. Our handlers are all +inside of the [index.ts](./index.ts) file. Go take a look. + +To start the Express application, run the following command: + ```sh -npm run test +npm start +# or if you need to rebuild and run again +npm run build && npm start ``` -Run test coverage +To change the `port` the web server runs on, you can create a copy of the +`.env.example` file and rename it to `.env`, then write the port into the +variable. -```sh -npm run test:coverage +```dotenv +PORT=8080 ``` -Run our Math API +Antoher way to set the port without the need to create a `.env` file is to +set the enviroment variable like bellow ```sh -npm run start +export PORT=8080 +npm start +# or just +PORT=8080 npm start ``` ----- +## Testing -Based on [Setup node express typescript server](https://blog.logrocket.com/how-to-set-up-node-typescript-express/) +Now that we have the basics of how to run the application, we need to test make +the application bullet-proof. This project includes Jest as a dependency and +has some simple tests inside the [__test__](./__test__) directory to make sure +our math library works like intended. -Start from scratch +To just run the tests, run the following command: ```sh -npm init -y +npm run test ``` +Jest includes a tool to check if you've covered all of your possible use cases +within your code. This type of checking is called Code Coverage, where your +code is analysed by a software that checks every possible coditional path +inside of your code, then checks which paths your tests actually run through +and when it finishes it outputs a percentage value of how much of your code is +actually covered by test cases. To read more about code coverage, you can read +the [wikipedia article](https://en.wikipedia.org/wiki/Code_coverage). + +To run the coverage check, run the following command: + ```sh -npm install express dotenv +npm run test:coverage ``` +## From Scratch + +This project is based on a logrocket article: +[Setup node express typescript server](https://blog.logrocket.com/how-to-set-up-node-typescript-express/), +to start from scratch: + ```sh +# Initialize a npm project +npm init -y +# Install deployment dependencies +npm install express dotenv +# Install development dependencies npm i -D typescript @types/express @types/node -``` \ No newline at end of file +``` diff --git a/__test__/math.test.ts b/__test__/math.test.ts index c55498a..a755294 100644 --- a/__test__/math.test.ts +++ b/__test__/math.test.ts @@ -4,11 +4,36 @@ import { subtractTwoNumbers } from '../math.handler'; +/* +This file includes a battery of test for the math library we created. Using +Jest, we can describe a group of tests and run them. + +@see Jest's Docs: https://jestjs.io/ +*/ + +// 'describe' groups tests so that they appear together when ran describe('test math handler', (): void => { + // The test function will execute the closure given watching for any errors + // thrown test('add two numbers', (): void => { - expect(addTwoNumbers(29, 3)).toBe(32); + // This test is simple, what we want to know is if the number 29 and the + // number 3 using this function will result in the number 32. This is a + // very crude test to test our function as it could just be always giving + // out the number 32! + let a = 29, b = 3; + let result = addTwoNumbers(a, b); + // The expect function will return a Jest object with the result we gave it + // to actually test if the result we gave it is what we want, we need to use + // the `toBe` method of the object to assert equality. If the values are not + // equal, an error will be thrown, shown in the Jest cli + expect(result).toBe(32); + // In reality, the 'add two numbers' test would be a group of tests, for + // edge cases, like adding negative numbers, adding numbers with different + // signs, adding floating point numbers, adding NaN numbers, adding + // infinities, passing strings into the parameters or other types. }); + // The following tests have been collapsed for brevety test('divide two numbers', (): void => { expect(divideTwoNumbers(10, 2)).toBe(5); }); diff --git a/index.ts b/index.ts index ce1dde2..b735177 100644 --- a/index.ts +++ b/index.ts @@ -1,28 +1,61 @@ import express, { Express, Request, Response } from 'express'; +// Import our library import { addTwoNumbers, divideTwoNumbers, subtractTwoNumbers } from './math.handler'; +/* +This file creates and sets up the routes available to the exposed http server +using express.js + +@see Express.js Docs: http://expressjs.com/ +*/ + +// Create the Express application const app: Express = express(); +// This is how you setup a simple GET handler app.get('/', (req: Request, res: Response) => { + // With express, we can respond with JSON directly without having to + // `JSON.stringify()` response. You might want to do this if you're building + // an API res.json({ message: 'Hello World!' }); }); +// This GET route is very flexible, it will answer any request going to +// `/sum/*/*` and assign the wildcards into the parameters with the key given app.get('/sum/:a/:b', (req: Request, res: Response) => { + // Extract the request parameters const { a, b } = { a: req.params.a, b: req.params.b }; + // TODO: Error check `a` and `b` for non-numeric values + // Run our sum function from the math library const sum = addTwoNumbers(Number(a), Number(b)); - res.json({ message: 'Sum Operation', operation: 'success', a, b, sum }); + // Respond in JSON + res.json({ + message: 'Sum Operation', + operation: 'success', + a, + b, + sum + }); }); +// Handler for the division route. app.get('/div/:a/:b', (req: Request, res: Response) => { const { a, b } = { a: req.params.a, b: req.params.b }; - const c = divideTwoNumbers(Number(a), Number(b)); - res.json({ message: 'Div Operation', operation: 'success', a, b, c }); + const division = divideTwoNumbers(Number(a), Number(b)); + res.json({ + message: 'Div Operation', + operation: 'success', + a, + b, + c: division + }); }); +// Handler for the subtraction route app.get('/subtract/:a/:b', (req: Request, res: Response) => { const { a, b } = { a: Number(req.params.a), b: Number(req.params.b) }; const subtraction = subtractTwoNumbers(Number(a), Number(b)); diff --git a/math.handler.ts b/math.handler.ts index 718a49e..6ab3462 100644 --- a/math.handler.ts +++ b/math.handler.ts @@ -1,7 +1,17 @@ +/* +This file contains our wonderful maths library + +@see Math documentation: https://en.wikipedia.org/wiki/Mathematics +*/ + const addTwoNumbers = (a: number, b: number): number => a + b; const divideTwoNumbers = (a: number, b: number): number => a / b; const subtractTwoNumbers = (a: number, b: number): number => a - b; -export { addTwoNumbers, divideTwoNumbers, subtractTwoNumbers }; +export { + addTwoNumbers, + divideTwoNumbers, + subtractTwoNumbers +}; diff --git a/package.json b/package.json index 09967da..5c2c89c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,11 @@ "jest": { "preset": "ts-jest", "testEnvironment": "node", - "setupFilesAfterEnv": [] + "setupFilesAfterEnv": [], + "testPathIgnorePatterns": [ + "node_modules/", + "dist/" + ] }, "repository": { "type": "git", @@ -38,4 +42,4 @@ "ts-jest": "^29.0.5", "typescript": "^5.0.2" } -} \ No newline at end of file +} diff --git a/server.ts b/server.ts index 9496a38..94e5b2a 100644 --- a/server.ts +++ b/server.ts @@ -1,10 +1,19 @@ import dotenv from 'dotenv'; import { app } from './index'; +/* +This file imports the actual routes from our index file + +@see ./index.ts +*/ + +// Import .env file as enviroment variables dotenv.config(); +// Check which port the server should run on const port = process.env.PORT || 8000; +// Listen on the port to accept http connections app.listen(port, () => { console.log(`Server running on port http://localhost:${port}`); });