Object-Oriented Programming/Unit Testing/JavaScript

temperature.test.js edit

// This module tests the Temperature class.

const Temperature = require("./temperature");

test("Constructor Celsius Undefined", () => {
    let temperature = new Temperature();
    expect(temperature.celsius).toBeUndefined();
});

test("Constructor Fahrenheit Undefined", () => {
    let temperature = new Temperature();
    expect(temperature.fahrenheit).toBeUndefined();
});

test("Constructor Celsius Zero", () => {
    let temperature = new Temperature({celsius: 0});
    expect(temperature.celsius).toBe(0);
});

test("Constructor Fahrenheit Zero", () => {
    let temperature = new Temperature({fahrenheit: 0});
    expect(temperature.fahrenheit).toBe(0);
});

test("toCelsius converts to Celsius", () => {
    let temperature = new Temperature();
    expect(temperature.toCelsius(98.6)).toBe(37);
});

test("toFahrenheit converts to Fahrenheit", () => {
    let temperature = new Temperature({fahrenheit: 0});
    expect(temperature.toFahrenheit(37)).toBe(98.6);
});

test("Constructor Celsius Fahrenheit Value", () => {
    let temperature = new Temperature({celsius: 37});
    expect(temperature.fahrenheit).toBe(98.6);
});

test("Constructor Fahrenheit Celsius Value", () => {
    let temperature = new Temperature({fahrenheit: 98.6});
    expect(temperature.celsius).toBe(37);
});

test("absoluteZeroCelsius is valid", () => {
    let temperature = new Temperature();
    expect(temperature.absoluteZeroCelsius).toBe(-273.15);
});

test("absoluteZeroFahrenheit is valid", () => {
    let temperature = new Temperature({fahrenheit: 0});
    expect(temperature.absoluteZeroFahrenheit).toBe(-459.67);
});

test("Celsius is not a number", () => {
    expect(() => {
        let temperature = new Temperature({celsius: "a"});
    }).toThrow("celsius must be a number. Received 'a'");
});

test("Celsius is below absolute zero", () => {
    expect(() => {
        let temperature = new Temperature({celsius: -500});
    }).toThrow("celsius must not be below absolute zero (-273.15) Received -500");
});

test("Fahrenheit is not a number", () => {
    expect(() => {
        let temperature = new Temperature({fahrenheit: "a"});
    }).toThrow("fahrenheit must be a number. Received 'a'");
});

test("Fahrenheit is below absolute zero", () => {
    expect(() => {
        let temperature = new Temperature({fahrenheit: -500});
    }).toThrow("fahrenheit must not be below absolute zero (-459.67) Received -500");
});

test("Constructor initializes both Celsius and Fahrenheit", () => {
    expect(() => {
        let temperature = new Temperature({celsius: 0, fahrenheit: 0});
    }).toThrow("Only initialize celsius or fahrenheit, not both.");
});

temperature.js edit

// Temperature converter. Provides temperature conversion functions. Supports Fahrenheit and Celsius temperatures.
//
// Examples:
//    let temperature = new Temperature({celsius: 37});
//    console.log(temperature.fahrenheit);
//
//    temperature = new Temperature({fahrenheit: 98.6});
//    console.log(temperature.celsius);
//
//    temperature = new Temperature();
//    temperature.celsius = 37;
//    console.log(temperature.fahrenheit);
//
//    temperature = new Temperature();
//    temperature.fahrenheit = 98.6
//    console.log(temperature.celsius);
//
//    temperature = new Temperature();
//    console.log(temperature.toCelsius(98.6));
//    console.log(temperature.toFahrenheit(37));
//
// References:
//    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
//    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
//    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set
//    https://www.smashingmagazine.com/2016/07/how-to-use-arguments-and-parameters-in-ecmascript-6/
// https://rollbar.com/guides/javascript-throwing-exceptions

class Temperature
{
    _celsius = undefined;
    _fahrenheit = undefined;

    // Creates Temperature object.
    // Throws error if both celsius and fahrenheit are initialized.
    constructor({celsius, fahrenheit} = {}) {
        if (celsius != undefined && fahrenheit != undefined) {
            throw new Error("Only initialize celsius or fahrenheit, not both.");
        }

        if (celsius != undefined) {
            this.celsius = celsius;
        }

        if (fahrenheit != undefined) {
            this.fahrenheit = fahrenheit
        }
    }

    // Returns absolute zero Celsius.
    get absoluteZeroCelsius() {
        return -273.15;
    }

    // Returns absolute zero Fahrenheit.
    get absoluteZeroFahrenheit() {
        return -459.67;
    }

    // Returns Celsius value.
    get celsius() {
        return this._celsius;
    }

    // Sets Celsius value.
    // Throws error if Celius temperature is not a number.
    // Throws error if Celius temperature is below absolute zero.
    set celsius(value) {
        this._celsius = this.validateCelsius(value);
        this._fahrenheit = this.toFahrenheit(value);
    }

    // Returns Fahrenheit value.
    get fahrenheit() {
        return this._fahrenheit;
    }

    // Sets Fahrenheit value.
    // Throws error if Fahrenheit temperature is not a number.
    // Throws error if Fahrenheit temperature is below absolute zero.
    set fahrenheit(value) {
        this._fahrenheit = this.validateFahrenheit(value);
        this._celsius = this.toCelsius(value);
    }

    // Converts Fahrenheit temperature to Celsius.
    toCelsius(fahrenheit) {
        fahrenheit = this.validateFahrenheit(fahrenheit);
        return (fahrenheit - 32) * 5 / 9;
    }

    // Converts Celsius temperature to Fahrenheit.
    toFahrenheit(celsius) {
        celsius = this.validateCelsius(celsius);
        return celsius * 9 / 5 + 32;
    }

    // Validates Celsius temperature.
    // Throws error if Celius temperature is not a number.
    // Throws error if Celius temperature is below absolute zero.
    validateCelsius(celsius) {
        if (isNaN(celsius)) {
            throw new Error("celsius must be a number. Received '" + celsius + "'");
        }

        if (celsius < this.absoluteZeroCelsius) {
            throw new Error("celsius must not be below absolute zero (" +
                this.absoluteZeroCelsius + ") Received " + celsius);
        }

        return celsius;
    }

    // Validates Fahrenheit temperature.
    // Throws error if Fahrenheit temperature is not a number.
    // Throws error if Fahrenheit temperature is below absolute zero.
    validateFahrenheit(fahrenheit) {
        if (isNaN(fahrenheit)) {
            throw new Error("fahrenheit must be a number. Received '" + fahrenheit + "'");
        }

        if (fahrenheit < this.absoluteZeroFahrenheit) {
            throw new Error("fahrenheit must not be below absolute zero (" +
                this.absoluteZeroFahrenheit + ") Received " + fahrenheit);
        }

        return fahrenheit;
    }
}

module.exports = Temperature;

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