ts-app-env
Version:
A config library for TypeScript.
139 lines (138 loc) • 6.49 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const __1 = require("../");
const pino_1 = __importDefault(require("pino"));
const AppConfig = {
enabled: (0, __1.boolean)(),
flag: (0, __1.boolean)({ default: false }),
name: (0, __1.string)({ env: "NAME", notNeededIn: "development" }),
nameWithDefault: (0, __1.string)({ env: "NAME_NOT_SET", default: "DEFAULT" }),
nameOptional: (0, __1.string)({ env: "NAME_NOT_SET", optional: true }),
port: (0, __1.number)({ env: "PORT" }),
portWithDefault: (0, __1.number)({ env: "PORT_NOT_SET", default: 8081 }),
portOptional: (0, __1.number)({ env: "PORT_NOT_SET", optional: true }),
nameIsEnvName: (0, __1.string)(),
SOME_URL: (0, __1.string)(),
};
/* eslint-disable prefer-destructuring */
describe("AppEnv", () => {
// default test value
const validEnvVars = {
ENABLED: "true",
NAME: "app",
NAME_IS_ENV_NAME: "app2",
PORT: "8080",
SOME_URL: "url",
};
it("can be constructed", () => {
const c = (0, __1.newConfig)(AppConfig, validEnvVars);
const name = c.name;
expect(name).toBe("app");
});
it("cannot be constructed with missing env vars", () => {
expect(() => (0, __1.newConfig)(AppConfig, {})).toThrow(__1.ConfigError);
});
it("can be constructed with missing env vars if skip is set", () => {
const logger = createMockLogger();
const invalidEnvVars = Object.assign({}, validEnvVars);
delete invalidEnvVars.NAME;
const conf = (0, __1.newConfig)(AppConfig, invalidEnvVars, { ignoreErrors: true, logger });
expect(conf.name).toBeUndefined();
expect(logger.info).toHaveBeenCalledWith("Ignoring errors while instantiating config: NAME is not set");
});
it("can be constructed with missing env vars and also not complain about it", () => {
const logger = createMockLogger();
const invalidEnvVars = Object.assign({}, validEnvVars);
delete invalidEnvVars.NAME;
const conf = (0, __1.newConfig)(AppConfig, invalidEnvVars, { ignoreErrors: true, doNotLogErrors: true, logger });
expect(conf.name).toBeUndefined();
expect(logger.error).toHaveBeenCalledTimes(0);
});
it("logs an error if an env var is missing", () => {
const logger = createMockLogger();
const invalidEnvVars = Object.assign({}, validEnvVars);
delete invalidEnvVars.NAME;
delete invalidEnvVars.PORT;
expect(() => (0, __1.newConfig)(AppConfig, invalidEnvVars, { logger })).toThrow();
expect(logger.error).toHaveBeenCalledWith("NAME is not set, PORT is not set");
});
it("can log errors with a custom pino logger", () => {
const pinoLogger = (0, pino_1.default)();
const pinoErrorSpy = jest.spyOn(pinoLogger, "error");
const invalidEnvVars = Object.assign({}, validEnvVars);
delete invalidEnvVars.NAME;
delete invalidEnvVars.PORT;
expect(() => (0, __1.newConfig)(AppConfig, invalidEnvVars, { logger: pinoLogger })).toThrow();
expect(pinoErrorSpy).toHaveBeenCalledWith("NAME is not set, PORT is not set");
});
it("error message contains the name of all missing env vars", () => {
const invalidEnvVars = Object.assign({}, validEnvVars);
delete invalidEnvVars.NAME;
delete invalidEnvVars.PORT;
expect(() => (0, __1.newConfig)(AppConfig, invalidEnvVars)).toThrow("NAME is not set, PORT is not set");
});
it("can ignore unset values in development environments", () => {
const devEnvVars = Object.assign({}, validEnvVars);
delete devEnvVars.NAME;
const conf = (0, __1.newConfig)(AppConfig, devEnvVars, { nodeEnv: "development" });
expect(conf.name).toBeUndefined();
});
it("uses a default value if its given", () => {
const nameWithDefault = (0, __1.newConfig)(AppConfig, validEnvVars).nameWithDefault;
expect(nameWithDefault).toBe("DEFAULT");
});
it("can use the property name as the env variable name", () => {
const name = (0, __1.newConfig)(AppConfig, validEnvVars).nameIsEnvName;
expect(name).toBe("app2");
});
it("can use the property name as if already snake cased", () => {
const url = (0, __1.newConfig)(AppConfig, validEnvVars).SOME_URL;
expect(url).toBe("url");
});
it("allows options to be optional", () => {
const config = (0, __1.newConfig)(AppConfig, validEnvVars);
const nameOptional = config.nameOptional;
expect(nameOptional).toBeUndefined();
});
it("can parse numbers", () => {
const port = (0, __1.newConfig)(AppConfig, validEnvVars).port;
expect(port).toBe(8080);
});
it("can handle invalid numbers", () => {
const vars = Object.assign(Object.assign({}, validEnvVars), { PORT: "invalid" });
expect(() => (0, __1.newConfig)(AppConfig, vars)).toThrow("PORT is not a number");
});
it("can get number default value", () => {
const portWithDefault = (0, __1.newConfig)(AppConfig, validEnvVars).portWithDefault;
expect(portWithDefault).toBe(8081);
});
it("can have optional numbers", () => {
const config = (0, __1.newConfig)(AppConfig, validEnvVars);
const portOptional = config.portOptional;
expect(portOptional).toBeUndefined();
});
it("can have booleans", () => {
const config = (0, __1.newConfig)(AppConfig, validEnvVars);
const enabled = config.enabled;
expect(enabled).toBe(true);
});
it("can have booleans that default to false", () => {
const config = (0, __1.newConfig)(AppConfig, validEnvVars);
expect(config.flag).toBe(false);
});
it("numbers are allowed to be floats", () => {
validEnvVars.PORT = "100.5";
const config = (0, __1.newConfig)(AppConfig, validEnvVars);
expect(config.port).toBe(100.5);
});
it("is frozen", () => {
const config = (0, __1.newConfig)(AppConfig, validEnvVars);
expect(() => (config.name = "something else")).toThrow(new TypeError("Cannot assign to read only property 'name' of object '#<Object>'"));
});
});
function createMockLogger() {
return { info: jest.fn(), warn: jest.fn(), error: jest.fn() };
}