I put the code up on GitHub and made some more changes to try to fix the error handling and get the expected output on each error case. But I still have problems.
Here’s the repository: DragonOsman/dragonosman-metricimpconv-proj (github.com)
Right now when I try 3/4/5mi
as the input I get this as the result:
undefined miles converts to 1.609340 kilometers
{"initUnit":"mi","returnNum":"1.609340","returnUnit":"km","string":"undefined miles converts to 1.609340 kilometers"}
Basically, right now it doesn’t say “invalid number and unit” when it should. Same for “invalid number”. It only says “invalid unit” when it should. Someone please help me out here. Thanks.
Edit:
How do I print the error message the way the example app does it? They have it like this:
invalid number and unit
"invalid number and unit"
And why does mine not report “invalid number and unit” like that when both the number and the unit are invalid? What am I missing?
Edit2: Okay, so I just had to do res.json(error.message)
. Now I just need to know why it’s not reporting “invalid number and unit” when both are invalid, like for 3/4/5in
for example.
Here’s my convertHandler.js
:
function ConvertHandler() {
const checkUnit = (unit) => {
if (unit.toLowerCase() !== "gal" && unit.toLowerCase() !== "kg" &&
unit.toLowerCase() !== "mi" && unit.toLowerCase() !== "km" &&
unit.toLowerCase() !== "L" && unit.toLowerCase() !== "lbs") {
return false;
}
return true;
}
const checkNumber = (number) => {
if (Number(number) === Number.isNaN() || /^\d+(?:(\s(\d)+)*)(?:\/\d+){2,}/.test(number)) {
return false;
}
return true;
}
const checkNumberAndUnit = (input) => {
if (!/^\d+/.test(input)) {
input = `1${input}`;
}
const [unit] = input.match(/([a-z]+)/i);
const [number] = input.match(/^\d+(?:(\.\d))(?:(\s(\d)+)*)(?:\/\d+){1}/);
if (!checkNumber(number) && !checkUnit(unit)) {
throw new Error("invalid number and unit");
}
if (!checkNumber(input)) {
throw new Error("invalid number");
}
if (!checkUnit(unit)) {
throw new Error("invalid unit");
}
return true;
}
this.getNum = function(input) {
if (/^[a-z]/i.test(input)) {
// We only got a unit, so the number should be 1
return 1;
} else if (checkNumber(input)) {
// extract number part from string containing number and unit
const [number] = input.match(/(\d+(?:.\d+)?)(?:(\s(\d)+)*)(?:\/\d+){1}/);
const result = Number(number);
return result;
}
};
this.getUnit = function(input) {
const [unit] = input.match(/([a-z]+)/i);
if (checkUnit(unit)) {
return unit;
}
throw new Error("invalid unit");
};
this.getReturnUnit = function(initUnit) {
let result;
if (initUnit) {
switch (initUnit.toString().toLowerCase()) {
case "mi":
result = "km";
break;
case "gal":
result = "L";
break;
case "km":
result = "mi";
break;
case "lbs":
result = "kg";
break;
case "kg":
result = "lbs";
break;
case "L":
result = "gal";
break;
default:
throw new Error("invalid unit");
}
return result;
}
};
this.spellOutUnit = function(unit) {
let result;
if (unit) {
switch (unit.toString().toLowerCase()) {
case "mi":
result = "miles";
break;
case "gal":
result = "gallons";
break;
case "km":
result = "kilometers";
break;
case "lbs":
result = "pounds";
break;
case "kg":
result = "kilograms";
break;
case "L":
result = "liters";
break;
default:
throw new Error("invalid unit");
}
return result;
}
};
this.convert = function(initNum, initUnit) {
let input = `${initNum}${initUnit}`;
if (input.match(/^[a-z]+$/i)) {
initNum = 1;
input = `${initNum}${initUnit}`;
}
if (checkNumberAndUnit(input)) {
const galToL = 3.78541;
const lbsToKg = 0.453592;
const miToKm = 1.60934;
let result;
switch (initUnit.toString().toLowerCase()) {
case "gal":
result = initNum * galToL;
break;
case "lbs":
result = initNum * lbsToKg;
break;
case "mi":
result = initNum = miToKm;
break;
case "L":
result = initNum / galToL;
break;
case "kg":
result = initNum / lbsToKg;
break;
case "km":
result = initNum / miToKm;
break;
}
if (result) {
result = result.toPrecision(7);
return result;
}
}
};
this.getString = function(initNum, initUnit, returnNum, returnUnit) {
let result = `${initNum} ${this.spellOutUnit(initUnit)} converts to ${returnNum} ${this.spellOutUnit(returnUnit)}`;
return result;
};
}
module.exports = ConvertHandler;
and here’s api.js
:
"use strict";
const expect = require("chai").expect;
const ConvertHandler = require("../controllers/convertHandler.js");
module.exports = (app) => {
let convertHandler = new ConvertHandler();
app.route("/api/convert").get((req, res) => {
try {
const inputStr = req.query.input;
const inputNumber = convertHandler.getNum(inputStr);
const inputUnit = convertHandler.getUnit(inputStr);
const returnUnit = convertHandler.getReturnUnit(inputUnit);
const result = convertHandler.convert(inputNumber, inputUnit);
const fullResultStr = convertHandler.getString(inputNumber, inputUnit, result, returnUnit);
res.json({
initNum: inputNumber,
initUnit: inputUnit,
returnNum: result,
returnUnit: returnUnit,
string: fullResultStr
});
} catch (error) {
console.log("routes/api.js:", error.message);
res.json(error.message);
}
});
};
So yeah. What am I missing?