From efb9bffbc82aaf024c89e6da3b70c0c526f41a54 Mon Sep 17 00:00:00 2001 From: Alaa Date: Wed, 29 Oct 2025 20:17:39 +0100 Subject: [PATCH 1/6] Add hackYourTemp project --- assignments/hackyourtemperature/package.json | 23 ++++++++++++++++++++ assignments/hackyourtemperature/server.js | 22 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 assignments/hackyourtemperature/package.json create mode 100644 assignments/hackyourtemperature/server.js diff --git a/assignments/hackyourtemperature/package.json b/assignments/hackyourtemperature/package.json new file mode 100644 index 000000000..bcff9364a --- /dev/null +++ b/assignments/hackyourtemperature/package.json @@ -0,0 +1,23 @@ +{ + "name": "hackyourtemperature", + "version": "1.0.0", + "main": "server.js", + "type": "module", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "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": { + "nodemon": "^3.1.10" + } +} diff --git a/assignments/hackyourtemperature/server.js b/assignments/hackyourtemperature/server.js new file mode 100644 index 000000000..8d7f51895 --- /dev/null +++ b/assignments/hackyourtemperature/server.js @@ -0,0 +1,22 @@ +import express from "express"; +const app = express(); +const port = 3000; + +app.use(express.json()); +app.use(express.urlencoded({ extended: false })); + +app.get("/", (req, res) => { + res.send(`hello from backend to frontend!`); +}); + +app.post("/weather", (req, res) => { + const { cityName } = req.body; + if (!cityName) { + return res.status(400).json({ msg: "City name is required." }); + } + res.send(cityName); +}); + +app.listen(port, () => { + console.log(`server is running on port ${port}`); +}); From c836e868785c4622db351d9a8ad6761c36142f13 Mon Sep 17 00:00:00 2001 From: Alaa Date: Wed, 5 Nov 2025 22:10:16 +0100 Subject: [PATCH 2/6] Alaa_Nasher-w2-node.js --- assignments/config-files/jest.config.js | 1 + .../hackyourtemperature/__tests__/app.test.js | 65 +++++++++++++++++++ assignments/hackyourtemperature/app.js | 36 ++++++++++ .../hackyourtemperature/babel.config.cjs | 13 ++++ .../hackyourtemperature/jest.config.js | 8 +++ assignments/hackyourtemperature/package.json | 9 ++- assignments/hackyourtemperature/server.js | 19 +----- .../hackyourtemperature/sources/keys.js | 5 ++ 8 files changed, 137 insertions(+), 19 deletions(-) create mode 100644 assignments/hackyourtemperature/__tests__/app.test.js create mode 100644 assignments/hackyourtemperature/app.js create mode 100644 assignments/hackyourtemperature/babel.config.cjs create mode 100644 assignments/hackyourtemperature/jest.config.js create mode 100644 assignments/hackyourtemperature/sources/keys.js diff --git a/assignments/config-files/jest.config.js b/assignments/config-files/jest.config.js index 19ba9649e..463c210da 100644 --- a/assignments/config-files/jest.config.js +++ b/assignments/config-files/jest.config.js @@ -1,3 +1,4 @@ +console.log("Jest config loaded"); 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: { diff --git a/assignments/hackyourtemperature/__tests__/app.test.js b/assignments/hackyourtemperature/__tests__/app.test.js new file mode 100644 index 000000000..e1c294ffe --- /dev/null +++ b/assignments/hackyourtemperature/__tests__/app.test.js @@ -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 () => { + 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); + }); +}); + +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!" }); + }); +}); diff --git a/assignments/hackyourtemperature/app.js b/assignments/hackyourtemperature/app.js new file mode 100644 index 000000000..312e70e45 --- /dev/null +++ b/assignments/hackyourtemperature/app.js @@ -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." }); + } + + 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!" }); + } + const data = await response.json(); + + return res.json({ main: data.main }); + } catch (error) { + res.send(error); + } +}); + +export default app; diff --git a/assignments/hackyourtemperature/babel.config.cjs b/assignments/hackyourtemperature/babel.config.cjs new file mode 100644 index 000000000..fbb629af6 --- /dev/null +++ b/assignments/hackyourtemperature/babel.config.cjs @@ -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", + }, + }, + ], + ], +}; diff --git a/assignments/hackyourtemperature/jest.config.js b/assignments/hackyourtemperature/jest.config.js new file mode 100644 index 000000000..19ba9649e --- /dev/null +++ b/assignments/hackyourtemperature/jest.config.js @@ -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: [], +}; diff --git a/assignments/hackyourtemperature/package.json b/assignments/hackyourtemperature/package.json index bcff9364a..5ad612975 100644 --- a/assignments/hackyourtemperature/package.json +++ b/assignments/hackyourtemperature/package.json @@ -4,7 +4,7 @@ "main": "server.js", "type": "module", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test": "jest", "start": "node server.js", "dev": "nodemon server.js" }, @@ -18,6 +18,11 @@ "node-fetch": "^3.3.2" }, "devDependencies": { - "nodemon": "^3.1.10" + "@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" } } diff --git a/assignments/hackyourtemperature/server.js b/assignments/hackyourtemperature/server.js index 8d7f51895..7297c6dd8 100644 --- a/assignments/hackyourtemperature/server.js +++ b/assignments/hackyourtemperature/server.js @@ -1,21 +1,6 @@ -import express from "express"; -const app = express(); -const port = 3000; - -app.use(express.json()); -app.use(express.urlencoded({ extended: false })); - -app.get("/", (req, res) => { - res.send(`hello from backend to frontend!`); -}); +import app from "./app.js"; -app.post("/weather", (req, res) => { - const { cityName } = req.body; - if (!cityName) { - return res.status(400).json({ msg: "City name is required." }); - } - res.send(cityName); -}); +const port = 3000; app.listen(port, () => { console.log(`server is running on port ${port}`); diff --git a/assignments/hackyourtemperature/sources/keys.js b/assignments/hackyourtemperature/sources/keys.js new file mode 100644 index 000000000..8f20bf7ef --- /dev/null +++ b/assignments/hackyourtemperature/sources/keys.js @@ -0,0 +1,5 @@ +// export const API_KEY = + +export const keys = { + API_KEY: "956083ea6214eb0860356f86d344277b", +}; From ac88165a2e06cc1eca4dfafdba27f632224138b7 Mon Sep 17 00:00:00 2001 From: Alaa Date: Wed, 5 Nov 2025 22:18:34 +0100 Subject: [PATCH 3/6] Add sources to gitIgnore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b6b402ed9..192219427 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ yarn-error.log *.bkp week3/prep-exercise/server-demo/ +assignments/hackyourtemperature/sources/ From 414c830cee77bc8a3b71fc709b15fcd7c4d48ed1 Mon Sep 17 00:00:00 2001 From: alaa Date: Wed, 5 Nov 2025 22:23:03 +0100 Subject: [PATCH 4/6] Update .gitignore to exclude additional directories --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 192219427..80ca519ca 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,6 @@ npm-debug.log package-lock.json yarn-error.log *.bkp - +sources/ week3/prep-exercise/server-demo/ assignments/hackyourtemperature/sources/ From c94cfee8ec88c293e58d306f0891efb8c43cc482 Mon Sep 17 00:00:00 2001 From: alaa Date: Wed, 5 Nov 2025 22:28:07 +0100 Subject: [PATCH 5/6] Update .gitignore to exclude specific files Removed specific source directories and added keys.js to .gitignore. --- .gitignore | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 80ca519ca..02fe5a078 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,13 @@ .DS_Store bin +sources assignments-solution node_modules npm-debug.log package-lock.json yarn-error.log *.bkp -sources/ + week3/prep-exercise/server-demo/ -assignments/hackyourtemperature/sources/ +assignments/hackyourtemperature/sources/keys.js + From 9f3382283e1fe928383c964a5d21221ef9658884 Mon Sep 17 00:00:00 2001 From: Alaa Date: Wed, 5 Nov 2025 22:24:33 +0100 Subject: [PATCH 6/6] Stop tracking keys.js and ignore sources folder --- assignments/hackyourtemperature/sources/keys.js | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 assignments/hackyourtemperature/sources/keys.js diff --git a/assignments/hackyourtemperature/sources/keys.js b/assignments/hackyourtemperature/sources/keys.js deleted file mode 100644 index 8f20bf7ef..000000000 --- a/assignments/hackyourtemperature/sources/keys.js +++ /dev/null @@ -1,5 +0,0 @@ -// export const API_KEY = - -export const keys = { - API_KEY: "956083ea6214eb0860356f86d344277b", -};