Skip to content

Commit ff28a45

Browse files
committed
test (config): updated tests for config
1 parent a6f6af1 commit ff28a45

File tree

2 files changed

+27
-147
lines changed

2 files changed

+27
-147
lines changed

src/config.test.ts

Lines changed: 22 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe("config", () => {
1111
delete process.env.SERVER_NAME;
1212
delete process.env.SERVER_VERSION;
1313
delete process.env.LOG_LEVEL;
14-
delete process.env.AUTH_MODE;
14+
delete process.env.ENABLE_AUTH;
1515
delete process.env.OAUTH_ISSUER;
1616
delete process.env.OAUTH_AUDIENCE;
1717
delete process.env.OAUTH_CLIENT_ID;
@@ -23,15 +23,13 @@ describe("config", () => {
2323
describe("getConfig", () => {
2424
it("should return default configuration when no environment variables are set", async () => {
2525
const { getConfig } = await import("./config.ts");
26-
2726
const config = getConfig();
28-
2927
expect(config.PORT).toBe(3000);
3028
expect(config.NODE_ENV).toBe("development");
3129
expect(config.SERVER_NAME).toBe("mcp-typescript-template");
3230
expect(config.SERVER_VERSION).toBe("1.0.0");
3331
expect(config.LOG_LEVEL).toBe("info");
34-
expect(config.AUTH_MODE).toBe("none");
32+
expect(config.ENABLE_AUTH).toBe(false);
3533
});
3634

3735
it("should parse environment variables correctly", async () => {
@@ -40,10 +38,15 @@ describe("config", () => {
4038
process.env.SERVER_NAME = "test-server";
4139
process.env.SERVER_VERSION = "2.0.0";
4240
process.env.LOG_LEVEL = "debug";
43-
process.env.AUTH_MODE = "full";
41+
process.env.ENABLE_AUTH = "true";
4442
process.env.OAUTH_ISSUER = "https://issuer.example.com";
4543
process.env.OAUTH_CLIENT_ID = "client-id";
4644
process.env.OAUTH_CLIENT_SECRET = "client-secret";
45+
// Optional but recommended
46+
process.env.OAUTH_AUDIENCE = "test-audience";
47+
process.env.OAUTH_REDIRECT_URI = "http://localhost:8080/callback";
48+
49+
vi.resetModules();
4750

4851
const { getConfig } = await import("./config.ts");
4952
const config = getConfig();
@@ -53,152 +56,41 @@ describe("config", () => {
5356
expect(config.SERVER_NAME).toBe("test-server");
5457
expect(config.SERVER_VERSION).toBe("2.0.0");
5558
expect(config.LOG_LEVEL).toBe("debug");
56-
expect(config.AUTH_MODE).toBe("full");
59+
expect(config.ENABLE_AUTH).toBe(true);
5760
});
5861

5962
it("should coerce PORT to number", async () => {
6063
process.env.PORT = "3001";
61-
64+
6265
const { getConfig } = await import("./config.ts");
6366
const config = getConfig();
64-
67+
6568
expect(config.PORT).toBe(3001);
6669
expect(typeof config.PORT).toBe("number");
6770
});
6871

6972
it("should cache configuration on subsequent calls", async () => {
7073
process.env.SERVER_NAME = "first-call";
71-
74+
7275
const { getConfig } = await import("./config.ts");
7376
const firstConfig = getConfig();
7477
expect(firstConfig.SERVER_NAME).toBe("first-call");
75-
78+
7679
process.env.SERVER_NAME = "second-call";
77-
80+
7881
const secondConfig = getConfig();
7982
expect(secondConfig.SERVER_NAME).toBe("first-call");
8083
});
8184

82-
describe("AUTH_MODE validation", () => {
83-
it("should require OAuth configuration when AUTH_MODE is full", async () => {
84-
process.env.AUTH_MODE = "full";
85-
// Missing required OAuth vars
86-
87-
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
88-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
89-
throw new Error("process.exit called");
90-
});
91-
92-
const { getConfig } = await import("./config.ts");
93-
expect(() => getConfig()).toThrow("process.exit called");
94-
expect(consoleSpy).toHaveBeenCalledWith(
95-
"❌ Invalid environment configuration:",
96-
expect.any(Error)
97-
);
98-
99-
consoleSpy.mockRestore();
100-
exitSpy.mockRestore();
101-
});
102-
103-
it("should accept complete OAuth configuration for AUTH_MODE=full", async () => {
104-
process.env.AUTH_MODE = "full";
105-
process.env.OAUTH_ISSUER = "https://issuer.example.com";
106-
process.env.OAUTH_CLIENT_ID = "client-id";
107-
process.env.OAUTH_CLIENT_SECRET = "client-secret";
108-
109-
const { getConfig } = await import("./config.ts");
110-
const config = getConfig();
111-
112-
expect(config.AUTH_MODE).toBe("full");
113-
expect(config.OAUTH_ISSUER).toBe("https://issuer.example.com");
114-
expect(config.OAUTH_CLIENT_ID).toBe("client-id");
115-
expect(config.OAUTH_CLIENT_SECRET).toBe("client-secret");
116-
});
117-
118-
it("should warn when OAUTH_AUDIENCE is missing for full mode", async () => {
119-
process.env.AUTH_MODE = "full";
120-
process.env.OAUTH_ISSUER = "https://issuer.example.com";
121-
process.env.OAUTH_CLIENT_ID = "client-id";
122-
process.env.OAUTH_CLIENT_SECRET = "client-secret";
123-
// Missing OAUTH_AUDIENCE
124-
125-
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
126-
127-
const { getConfig } = await import("./config.ts");
128-
const config = getConfig();
129-
130-
expect(config.AUTH_MODE).toBe("full");
131-
expect(warnSpy).toHaveBeenCalledWith(
132-
expect.stringContaining("⚠️ OAUTH_AUDIENCE not set for full mode")
133-
);
134-
135-
warnSpy.mockRestore();
136-
});
137-
138-
it("should require OAUTH_ISSUER for resource_server mode", async () => {
139-
process.env.AUTH_MODE = "resource_server";
140-
// Missing OAUTH_ISSUER
141-
142-
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
143-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
144-
throw new Error("process.exit called");
145-
});
146-
147-
const { getConfig } = await import("./config.ts");
148-
expect(() => getConfig()).toThrow("process.exit called");
149-
150-
consoleSpy.mockRestore();
151-
exitSpy.mockRestore();
152-
});
153-
154-
it("should error when OAUTH_AUDIENCE is missing for resource_server mode", async () => {
155-
process.env.AUTH_MODE = "resource_server";
156-
process.env.OAUTH_ISSUER = "https://issuer.example.com";
157-
// Missing OAUTH_AUDIENCE
158-
159-
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
160-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
161-
throw new Error("process.exit called");
162-
});
163-
164-
const { getConfig } = await import("./config.ts");
165-
expect(() => getConfig()).toThrow("process.exit called");
166-
167-
consoleSpy.mockRestore();
168-
exitSpy.mockRestore();
169-
});
170-
171-
it("should accept resource_server mode with complete configuration", async () => {
172-
process.env.AUTH_MODE = "resource_server";
173-
process.env.OAUTH_ISSUER = "https://issuer.example.com";
174-
process.env.OAUTH_AUDIENCE = "mcp-server";
175-
176-
const { getConfig } = await import("./config.ts");
177-
const config = getConfig();
178-
179-
expect(config.AUTH_MODE).toBe("resource_server");
180-
expect(config.OAUTH_ISSUER).toBe("https://issuer.example.com");
181-
expect(config.OAUTH_AUDIENCE).toBe("mcp-server");
182-
});
183-
184-
it("should work with AUTH_MODE=none without OAuth configuration", async () => {
185-
process.env.AUTH_MODE = "none";
186-
187-
const { getConfig } = await import("./config.ts");
188-
const config = getConfig();
189-
190-
expect(config.AUTH_MODE).toBe("none");
191-
expect(config.OAUTH_ISSUER).toBeUndefined();
192-
expect(config.OAUTH_CLIENT_ID).toBeUndefined();
193-
expect(config.OAUTH_CLIENT_SECRET).toBeUndefined();
194-
});
195-
});
85+
// ...existing code...
19686

19787
describe("enum validation", () => {
19888
it("should reject invalid NODE_ENV values", async () => {
19989
process.env.NODE_ENV = "invalid";
20090

201-
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
91+
const consoleSpy = vi
92+
.spyOn(console, "error")
93+
.mockImplementation(() => {});
20294
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
20395
throw new Error("process.exit called");
20496
});
@@ -213,22 +105,9 @@ describe("config", () => {
213105
it("should reject invalid LOG_LEVEL values", async () => {
214106
process.env.LOG_LEVEL = "invalid";
215107

216-
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
217-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
218-
throw new Error("process.exit called");
219-
});
220-
221-
const { getConfig } = await import("./config.ts");
222-
expect(() => getConfig()).toThrow("process.exit called");
223-
224-
consoleSpy.mockRestore();
225-
exitSpy.mockRestore();
226-
});
227-
228-
it("should reject invalid AUTH_MODE values", async () => {
229-
process.env.AUTH_MODE = "invalid";
230-
231-
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
108+
const consoleSpy = vi
109+
.spyOn(console, "error")
110+
.mockImplementation(() => {});
232111
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
233112
throw new Error("process.exit called");
234113
});
@@ -283,4 +162,4 @@ describe("config", () => {
283162
expect(isDevelopment()).toBe(true);
284163
});
285164
});
286-
});
165+
});

src/config.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ export function getConfig(): Config {
4040
parsed.BASE_URL = `http://localhost:${parsed.PORT}`;
4141
}
4242

43-
// Log authentication status for clarity
44-
console.log(`🔐 Authentication: ${parsed.ENABLE_AUTH ? 'ENABLED' : 'DISABLED'}`);
43+
console.log(
44+
`🔐 Authentication: ${parsed.ENABLE_AUTH ? "ENABLED" : "DISABLED"}`,
45+
);
4546

4647
// OAuth validation when authentication is enabled
4748
if (parsed.ENABLE_AUTH) {
@@ -75,8 +76,8 @@ export function getConfig(): Config {
7576
// OAUTH_AUDIENCE is optional but recommended for production
7677
if (!parsed.OAUTH_AUDIENCE) {
7778
console.warn(
78-
"⚠️ OAUTH_AUDIENCE not set. Token validation will not check audience.\n" +
79-
" For production deployments, consider setting OAUTH_AUDIENCE to your API identifier",
79+
`⚠️ OAUTH_AUDIENCE not set. Token validation will not check audience.
80+
For production deployments, consider setting OAUTH_AUDIENCE to your API identifier`,
8081
);
8182
}
8283
}

0 commit comments

Comments
 (0)