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 edit

Copy and paste the code above into one of the following free online development environments or use your own JavaScript compiler / interpreter / IDE.

See Also edit