168 lines
5.7 KiB
TypeScript
168 lines
5.7 KiB
TypeScript
import { describe, test, expect, beforeEach, afterEach } from "bun:test";
|
|
import { loadConfig, parseConfig } from "../src/config/index.ts";
|
|
|
|
describe("Configuration Loader (HTTP & Stdio Support)", () => {
|
|
const originalEnv = { ...process.env };
|
|
const originalArgv = [...process.argv];
|
|
|
|
beforeEach(() => {
|
|
process.env = { ...originalEnv };
|
|
process.argv = [...originalArgv.slice(0, 2)];
|
|
});
|
|
|
|
afterEach(() => {
|
|
process.env = originalEnv;
|
|
process.argv = originalArgv;
|
|
});
|
|
|
|
test("loads stdio configuration when PORT is unset and OPENPROJECT_API_KEY is provided", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
process.env.OPENPROJECT_API_KEY = "test-key";
|
|
delete process.env.PORT;
|
|
|
|
const config = loadConfig();
|
|
expect(config.baseUrl).toBe("https://openproject.example.com");
|
|
expect(config.apiKey).toBe("test-key");
|
|
expect(config.readOnly).toBe(false);
|
|
expect(config.port).toBeUndefined();
|
|
});
|
|
|
|
test("throws error if OPENPROJECT_API_KEY is missing in stdio mode", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
delete process.env.OPENPROJECT_API_KEY;
|
|
delete process.env.PORT;
|
|
|
|
expect(() => loadConfig()).toThrow();
|
|
});
|
|
|
|
test("throws error if OPENPROJECT_API_KEY is whitespace in stdio mode", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
process.env.OPENPROJECT_API_KEY = " ";
|
|
delete process.env.PORT;
|
|
|
|
expect(() => loadConfig()).toThrow();
|
|
});
|
|
|
|
test("throws error if OPENPROJECT_BASE_URL is invalid", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "not-a-valid-url";
|
|
process.env.OPENPROJECT_API_KEY = "test-key";
|
|
delete process.env.PORT;
|
|
|
|
expect(() => loadConfig()).toThrow();
|
|
});
|
|
|
|
test("normalizes baseUrl by stripping trailing slashes", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com///";
|
|
process.env.OPENPROJECT_API_KEY = "test-key";
|
|
delete process.env.PORT;
|
|
|
|
const config = loadConfig();
|
|
expect(config.baseUrl).toBe("https://openproject.example.com");
|
|
});
|
|
|
|
test("loads HTTP configuration when PORT environment variable is set without API key", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
delete process.env.OPENPROJECT_API_KEY;
|
|
process.env.PORT = "3000";
|
|
|
|
const config = loadConfig();
|
|
expect(config.baseUrl).toBe("https://openproject.example.com");
|
|
expect(config.port).toBe(3000);
|
|
expect(config.apiKey).toBeUndefined();
|
|
});
|
|
|
|
test("loads HTTP configuration with PORT=0 for dynamic assignment", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
delete process.env.OPENPROJECT_API_KEY;
|
|
process.env.PORT = "0";
|
|
|
|
const config = loadConfig();
|
|
expect(config.baseUrl).toBe("https://openproject.example.com");
|
|
expect(config.port).toBe(0);
|
|
expect(config.apiKey).toBeUndefined();
|
|
});
|
|
|
|
test("loads HTTP configuration when HOST_PORT is set as fallback without PORT", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
delete process.env.OPENPROJECT_API_KEY;
|
|
delete process.env.PORT;
|
|
process.env.HOST_PORT = "3000";
|
|
|
|
const config = loadConfig();
|
|
expect(config.baseUrl).toBe("https://openproject.example.com");
|
|
expect(config.port).toBe(3000);
|
|
expect(config.apiKey).toBeUndefined();
|
|
});
|
|
|
|
test("loads HTTP configuration with API key when provided", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
process.env.OPENPROJECT_API_KEY = "test-key";
|
|
process.env.PORT = "3000";
|
|
|
|
const config = loadConfig();
|
|
expect(config.baseUrl).toBe("https://openproject.example.com");
|
|
expect(config.port).toBe(3000);
|
|
expect(config.apiKey).toBe("test-key");
|
|
});
|
|
|
|
test("parses --port and --host CLI arguments", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
delete process.env.OPENPROJECT_API_KEY;
|
|
delete process.env.PORT;
|
|
process.argv.push("--port", "8080", "--host", "127.0.0.1", "--read-only");
|
|
|
|
const config = loadConfig();
|
|
expect(config.port).toBe(8080);
|
|
expect(config.host).toBe("127.0.0.1");
|
|
expect(config.readOnly).toBe(true);
|
|
});
|
|
|
|
test("parses --port=value and --host=value CLI arguments", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
delete process.env.OPENPROJECT_API_KEY;
|
|
delete process.env.PORT;
|
|
process.argv.push("--port=9090", "--host=0.0.0.0");
|
|
|
|
const config = loadConfig();
|
|
expect(config.port).toBe(9090);
|
|
expect(config.host).toBe("0.0.0.0");
|
|
});
|
|
|
|
test("CLI arguments take precedence over environment variables", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
process.env.PORT = "3000";
|
|
process.env.HOST = "127.0.0.1";
|
|
process.argv.push("--port", "4000", "--host", "0.0.0.0");
|
|
|
|
const config = loadConfig();
|
|
expect(config.port).toBe(4000);
|
|
expect(config.host).toBe("0.0.0.0");
|
|
});
|
|
|
|
test("throws error if port is non-numeric", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
process.env.PORT = "not-a-port";
|
|
|
|
expect(() => loadConfig()).toThrow();
|
|
});
|
|
|
|
test("throws error if port is out of range", () => {
|
|
process.env.OPENPROJECT_BASE_URL = "https://openproject.example.com";
|
|
process.env.PORT = "70000";
|
|
|
|
expect(() => loadConfig()).toThrow();
|
|
});
|
|
|
|
test("parseConfig alias works identically to loadConfig", () => {
|
|
const config = parseConfig(
|
|
{
|
|
OPENPROJECT_BASE_URL: "https://openproject.example.com",
|
|
OPENPROJECT_API_KEY: "alias-key",
|
|
},
|
|
[]
|
|
);
|
|
expect(config.baseUrl).toBe("https://openproject.example.com");
|
|
expect(config.apiKey).toBe("alias-key");
|
|
});
|
|
});
|