diff --git a/assignments/hackyourtemperature/.gitignore b/assignments/hackyourtemperature/.gitignore new file mode 100644 index 000000000..d16f63d9b --- /dev/null +++ b/assignments/hackyourtemperature/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +.env \ No newline at end of file diff --git a/assignments/hackyourtemperature/.idea/.gitignore b/assignments/hackyourtemperature/.idea/.gitignore new file mode 100644 index 000000000..1c2fda565 --- /dev/null +++ b/assignments/hackyourtemperature/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/assignments/hackyourtemperature/.idea/hackyourtemperature.iml b/assignments/hackyourtemperature/.idea/hackyourtemperature.iml new file mode 100644 index 000000000..0b872d82d --- /dev/null +++ b/assignments/hackyourtemperature/.idea/hackyourtemperature.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/assignments/hackyourtemperature/.idea/modules.xml b/assignments/hackyourtemperature/.idea/modules.xml new file mode 100644 index 000000000..51ab5ccc4 --- /dev/null +++ b/assignments/hackyourtemperature/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/assignments/hackyourtemperature/.idea/vcs.xml b/assignments/hackyourtemperature/.idea/vcs.xml new file mode 100644 index 000000000..2e3f6920d --- /dev/null +++ b/assignments/hackyourtemperature/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/assignments/hackyourtemperature/__tests__/app.test.js b/assignments/hackyourtemperature/__tests__/app.test.js new file mode 100644 index 000000000..9adb01e60 --- /dev/null +++ b/assignments/hackyourtemperature/__tests__/app.test.js @@ -0,0 +1,31 @@ +import supertest from "supertest"; +import app from "../app.js"; + +const request = supertest(app); + +describe("POST /weather", () => { + it("case1: (Valid city name) >>> should return weather data", async () => { + const response = await request + .post("/weather") + .send({ cityName: "London" }); + + expect(response.status).toBe(200); + expect(response.body).toContain("London"); + // since the tempruture is not fixed, how should i do check it? + }); + + it("Case2: (Inavalid city name ) >>> should return 500 error", async () => { + const response = await request + .post("/weather") + .send({ cityName: "Incorrect_CityName" }); + + expect(response.status).toBe(500); + expect(response.body).toBe("City is not found"); + }); + + it("Case3: (Empty City Name) should return 400 error", async () => { + const response = await request.post("/weather").send({}); + expect(response.status).toBe(400); + expect(response.body).toContain("Please provide a city name"); + }); +}); diff --git a/assignments/hackyourtemperature/app.js b/assignments/hackyourtemperature/app.js new file mode 100644 index 000000000..b7266d0d0 --- /dev/null +++ b/assignments/hackyourtemperature/app.js @@ -0,0 +1,59 @@ +import express from "express"; +import keys from "./sources/keys.js"; // to access it use keys.API_KEY +import fetch from "node-fetch"; +import dotenv from "dotenv"; + +dotenv.config(); +const app = express(); + +app.use(express.json()); + +//GET request that sends the message [hello from backend to frontend!] to the client +app.get("/", (req, res) => { + res.send("Hello From Backend to Frontend"); +}); + +// --------------5.1 Adding a POST request---------------- +app.post("/weather", (req, res) => { + const { cityName } = req.body; + console.log("City name received", cityName); + + if (!cityName || typeof cityName !== "string" || !cityName.trim()) { + return res.status(400).json({ weatherText: "City name is required" }); + } + + // const cityWeatherUrl = `http://api.openweathermap.org/data/2.5/forecast?q=${cityName}&appid=${keys.API_KEY}`; + + const cityWeatherUrl = `http://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent( + cityName.trim() + )}&appid=${keys.API_KEY}&units=metric`; + + fetchWeather(cityWeatherUrl); + + async function fetchWeather(URL) { + try { + const response = await fetch(URL); + if (!response.ok) { + return res.status(500).json({ weatherText: "Response not ok" }); + } + const data = await response.json(); + console.log("Weather data received", data); + + if (data.cod === "404") { + return res.status(404).json({ weatherText: "City not found" }); + } + + const tempratureInCelsius = data.main.temp; + + res.json({ + weatherText: `Temperature in ${cityName}: ${tempratureInCelsius.toFixed( + 2 + )} °C`, + }); + } catch (error) { + res.status(500).json({ weatherText: error.message }); + } + } +}); + +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 new file mode 100644 index 000000000..7e4698d74 --- /dev/null +++ b/assignments/hackyourtemperature/package.json @@ -0,0 +1,29 @@ +{ + "name": "hackyourtemperature", + "type": "module", + "version": "1.0.0", + "description": "", + "main": "server.js", + "scripts": { + "test": "jest", + "start": "node server.js", + "dev": "nodemon server.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@babel/preset-env": "^7.28.5", + "babel-jest": "^30.2.0", + "jest": "^30.2.0", + "nodemon": "^3.1.10", + "supertest": "^7.1.4" + }, + "dependencies": { + "dotenv": "^17.2.3", + "express-handlebars": "^8.0.3", + "node-fetch": "^3.3.2", + "express": "^5.1.0" + + } +} diff --git a/assignments/hackyourtemperature/server.js b/assignments/hackyourtemperature/server.js new file mode 100644 index 000000000..d1124d49b --- /dev/null +++ b/assignments/hackyourtemperature/server.js @@ -0,0 +1,5 @@ +import app from "./app.js"; + +app.listen(3000, () => { + console.log("Server on Port 3000 is running"); +}); diff --git a/assignments/hackyourtemperature/sources/keys.js b/assignments/hackyourtemperature/sources/keys.js new file mode 100644 index 000000000..e46ad37f7 --- /dev/null +++ b/assignments/hackyourtemperature/sources/keys.js @@ -0,0 +1 @@ +export default { API_KEY: "d63cf1893cfbd168dfb340b341a8c03e" };