-
Notifications
You must be signed in to change notification settings - Fork 10
Alaa nasher w2 node.js #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
efb9bff
c836e86
ac88165
414c830
c94cfee
9f33822
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import app from "../app.js"; | ||
| import supertest from "supertest"; | ||
| import fetch from "node-fetch"; | ||
|
|
||
| jest.mock("node-fetch"); | ||
| const request = supertest(app); | ||
|
|
||
| describe("POST /", () => { | ||
| it("Quick test", () => { | ||
| expect(1).toBe(1); | ||
| }); | ||
| }); | ||
|
|
||
| describe("Test GET /", () => { | ||
| test("Send hello to backend", async () => { | ||
| const res = await request.get("/"); | ||
|
|
||
| expect(res.statusCode).toBe(200); | ||
| expect(res.text).toBe("hello from backend to frontend!"); | ||
| }); | ||
| }); | ||
|
|
||
| describe("Test POST /weather", () => { | ||
| test("Return city name is required.", async () => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really like how this test is using the AAA principle. This makes it very readable, great! |
||
| const city = " "; | ||
|
|
||
| const res = await request.post("/weather").send({ cityName: city }); | ||
|
|
||
| expect(res.statusCode).toBe(400); | ||
| expect(res.body).toEqual({ msg: "City name is required." }); | ||
| }); | ||
| }); | ||
|
|
||
| //test the happy path: when the user sends a valid city name, the API returns weather data. | ||
| describe("Test POST /weather", () => { | ||
| test("Return temperature data", async () => { | ||
| const city = "amsterdam"; | ||
| fetch.mockResolvedValue({ | ||
| ok: true, | ||
| json: async () => ({ | ||
| name: "Amsterdam", | ||
| main: { temp: 286.78 }, | ||
| }), | ||
| }); | ||
| const res = await request.post("/weather").send({ cityName: city }); | ||
|
|
||
| expect(res.statusCode).toBe(200); | ||
| expect(res.body.main.temp).toBe(286.78); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could also test for the city name here, to make sure we get all the correct data. |
||
| }); | ||
| }); | ||
|
|
||
| describe("Test POST /weather", () => { | ||
| test("Return city not found", async () => { | ||
| const city = "amsterddam"; | ||
|
|
||
| fetch.mockResolvedValue({ | ||
| ok: false, | ||
| json: async () => ({}), | ||
| }); | ||
| const res = await request.post("/weather").send({ cityName: city }); | ||
|
|
||
| expect(res.statusCode).toBe(400); | ||
| expect(res.body).toEqual({ weatherText: "City is not found!" }); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import express from "express"; | ||
| import fetch from "node-fetch"; | ||
| import { keys } from "./sources/keys.js"; | ||
|
|
||
| const app = express(); | ||
| app.use(express.json()); | ||
| app.use(express.urlencoded({ extended: false })); | ||
|
|
||
| app.get("/", (req, res) => { | ||
| res.status(200).send(`hello from backend to frontend!`); | ||
| }); | ||
|
|
||
| app.post("/weather", async (req, res) => { | ||
| const { cityName } = req.body; | ||
| if (!cityName || cityName.trim() === "") { | ||
| return res.status(400).json({ msg: "City name is required." }); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice guard clause! |
||
| } | ||
|
|
||
| const url = `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent( | ||
| cityName.trim() | ||
| )}&appid=${keys.API_KEY}`; | ||
|
|
||
| try { | ||
| const response = await fetch(url); | ||
| if (!response.ok) { | ||
| return res.status(400).json({ weatherText: "City is not found!" }); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we're already in a |
||
| } | ||
| const data = await response.json(); | ||
|
|
||
| return res.json({ main: data.main }); | ||
| } catch (error) { | ||
| res.send(error); | ||
| } | ||
| }); | ||
|
|
||
| export default app; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| module.exports = { | ||
| presets: [ | ||
| [ | ||
| // This is a configuration, here we are telling babel what configuration to use | ||
| "@babel/preset-env", | ||
| { | ||
| targets: { | ||
| node: "current", | ||
| }, | ||
| }, | ||
| ], | ||
| ], | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| export default { | ||
| // Tells jest that any file that has 2 .'s in it and ends with either js or jsx should be run through the babel-jest transformer | ||
| transform: { | ||
| "^.+\\.jsx?$": "babel-jest", | ||
| }, | ||
| // By default our `node_modules` folder is ignored by jest, this tells jest to transform those as well | ||
| transformIgnorePatterns: [], | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| { | ||
| "name": "hackyourtemperature", | ||
| "version": "1.0.0", | ||
| "main": "server.js", | ||
| "type": "module", | ||
| "scripts": { | ||
| "test": "jest", | ||
| "start": "node server.js", | ||
| "dev": "nodemon server.js" | ||
| }, | ||
| "keywords": [], | ||
| "author": "", | ||
| "license": "ISC", | ||
| "description": "", | ||
| "dependencies": { | ||
| "express": "^5.1.0", | ||
| "express-handlebars": "^8.0.1", | ||
| "node-fetch": "^3.3.2" | ||
| }, | ||
| "devDependencies": { | ||
| "@babel/core": "^7.28.5", | ||
| "@babel/preset-env": "^7.28.5", | ||
| "babel-jest": "^30.2.0", | ||
| "jest": "^30.2.0", | ||
| "nodemon": "^3.1.10", | ||
| "supertest": "^7.1.4" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import app from "./app.js"; | ||
|
|
||
| const port = 3000; | ||
|
|
||
| app.listen(port, () => { | ||
| console.log(`server is running on port ${port}`); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good test suite, well done! One small thing you could change is the order and grouping of the tests. You can put multiple tests into one
describeblock, which makes it easier to see which tests belong together, and cleans up your test logs a bit. It's also good to pick an order for tests, group them by end point and then either start with the happy path test and then error cases, or the other way around.