Applied Programming/Testing/JavaScript
temperature.test.js
edit/* This module tests temperature.js.
Run using:
jest temperature.test.js
References:
https://jestjs.io/
https://stephencharlesweiss.com/jest-testing-spyon-consoles/
*/
const readline_sync = require("readline-sync")
const temperature = require('./temperature');
test("ABSOLUTE_ZERO is valid", () => {
expect(temperature.ABSOLUTE_ZERO).toBe(-459.67);
});
test("getFahrenheit returns fahrenheit", () => {
const question = jest.spyOn(readline_sync, "question").mockImplementation();
question.mockReturnValueOnce("100");
expect(temperature.getFahrenheit()).toBe(100);
});
test("getFahrenheit returns empty string", () => {
const question = jest.spyOn(readline_sync, "question").mockImplementation();
question.mockReturnValueOnce("");
expect(temperature.getFahrenheit()).toBe("");
});
test("getFahrenheit rejects non-numeric value", () => {
const question = jest.spyOn(readline_sync, "question").mockImplementation();
question.mockReturnValueOnce("x");
question.mockReturnValueOnce("");
const log = jest.spyOn(console, "log").mockImplementation();
expect(temperature.getFahrenheit()).toBe("");
expect(log).toHaveBeenLastCalledWith(
"TypeError: 'x' is not a number.");
});
test("calculateCelsius converts to Celsius", () => {
expect(temperature.calculateCelsius(98.6)).toBe(37);
});
test("calculateCelsius throws TypeError", () => {
expect(() => {
temperature.calculateCelsius("a");
}).toThrow("'a' is not a number.");
});
test("calculateCelsius throws RangeError", () => {
expect(() => {
temperature.calculateCelsius(-1000);
}).toThrow("'-1000' is below absolute zero.");
});
test("displayResult displays temperatures", () => {
const log = jest.spyOn(console, "log").mockImplementation();
temperature.displayResults(98.6, 37);
expect(log).toHaveBeenLastCalledWith(
"98.6° Fahrenheit is 37° Celsius");
});
temperature.js
edit/* This program converts a Fahrenheit temperature to Celsius.
Input:
Fahrenheit temperature
Output:
Fahrenheit temperature
Celsius temperature
Example:
Enter Fahrenheit temperature: 100
100° Fahrenheit is 37.77777777777778° Celsius
...
Enter Fahrenheit temperature or press <Enter> to quit:
References:
* http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html
* https://javascript.info/comments
* http://www.mathsisfun.com/temperature-conversion.html
* https://nodejs.org/api/process.html#processexitcode
* https://javascript.info/try-catch
* https://javascript.info/types
*/
const TEMPERATURE_DIFFERENCE = 32;
const TEMPERATURE_RATIO = 5 / 9;
const ABSOLUTE_ZERO = -459.67;
if (typeof module != "undefined" && !module.parent) {
main();
}
/**
* Runs main program logic.
*/
function main() {
try {
while (true) {
let fahrenheit = getFahrenheit();
if (fahrenheit === "") {
break;
}
let celsius = calculateCelsius(fahrenheit);
displayResults(fahrenheit, celsius);
displayTable(fahrenheit);
}
} catch (error) {
console.log("Unexpected error:");
console.log(`${error.name}: ${error.message}`);
}
}
/**
* Gets Fahrenheit temperature.
*
* @returns {number} Fahrenheit temperature or empty string
*/
function getFahrenheit() {
while (true) {
let fahrenheit = prompt("Enter Fahrenheit temperature or press <Enter> to quit: ");
if (fahrenheit === "") {
return fahrenheit;
}
if (isNaN(fahrenheit)) {
console.log("Fahrenheit temperature must be a number.");
console.log(`TypeError: '${fahrenheit}' is not a number.`);
continue;
}
fahrenheit = Number(fahrenheit);
if (fahrenheit < ABSOLUTE_ZERO) {
console.log("Fahrenheit temperature cannot be below absolute zero.");
console.log(`RangeError: ${fahrenheit} is less than ${ABSOLUTE_ZERO}.`);
continue;
}
return fahrenheit;
}
}
/**
* Converts Fahrenheit temperature to Celsius.
*
* @param {number} Fahrenheit temperature
* @returns {number} Celsius temperature
* @throws TypeError if fahrenheit is not numeric.
* @throws RangeError if fahrenheit is below absolute zero.
*/
function calculateCelsius(fahrenheit) {
if (typeof fahrenheit != "number") {
throw(new TypeError(`'${fahrenheit}' is not a number.`))
}
if (fahrenheit < ABSOLUTE_ZERO) {
throw(new RangeError(`'${fahrenheit}' is below absolute zero.`))
}
let celsius = (fahrenheit - TEMPERATURE_DIFFERENCE) * TEMPERATURE_RATIO;
return celsius;
}
/**
* Displays Fahrenheit and Celsius temperatures.
*
* @param {number} Fahrenheit temperature
* @param {number} Celsius temperature
*/
function displayResults(fahrenheit, celsius) {
console.assert(typeof fahrenheit == "number");
console.assert(typeof celsius == "number");
console.log(`${fahrenheit}° Fahrenheit is ${celsius}° Celsius`);
}
/**
* Displays nearest multiples of 10 Fahrenheit and Celsius temperatures.
*
* @param {number} Fahrenheit temperature
*/
function displayTable(fahrenheit) {
console.assert(typeof fahrenheit == "number");
console.log("");
console.log("F\tC")
let start = Math.floor(fahrenheit / 10) * 10
for (let fahrenheit = start; fahrenheit < start + 11; fahrenheit++) {
let celsius = calculateCelsius(fahrenheit);
console.log(`${fahrenheit.toFixed(1)}\t${celsius.toFixed(1)}`)
}
console.log("");
}
/**
* Input function to get input in Node environment.
*
* @param {string} text prompt
* @returns {string} input
*/
function prompt(text) {
const rls = require('readline-sync');
let value = rls.question(text);
return value;
}
module.exports = {
ABSOLUTE_ZERO, getFahrenheit, calculateCelsius, displayResults, displayTable
};
Try It
editCopy and paste the code above into one of the following free online development environments or use your own JavaScript compiler / interpreter / IDE.