-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathenv.test.ts
More file actions
124 lines (96 loc) · 5.58 KB
/
env.test.ts
File metadata and controls
124 lines (96 loc) · 5.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { afterEach, describe, expect, it } from "vitest";
import { FRONTEND_API_CONTRACT } from "../lib/frontendApiContract";
import {
resolveDashboardApiBase,
resolveDashboardOperatorRoleEnv,
resolveDashboardPmCopyVariantEnv,
resolveDashboardPublicDocsBaseUrl,
resolveDashboardPublicDocsHref,
} from "../lib/env";
const ORIGINAL_API_BASE = process.env.NEXT_PUBLIC_API_BASE;
const ORIGINAL_CORTEXPILOT_API_BASE = process.env.NEXT_PUBLIC_CORTEXPILOT_API_BASE;
const ORIGINAL_CORTEXPILOT_PUBLIC_DOCS_BASE_URL = process.env.NEXT_PUBLIC_CORTEXPILOT_PUBLIC_DOCS_BASE_URL;
const ORIGINAL_CORTEXPILOT_OPERATOR_ROLE = process.env.NEXT_PUBLIC_CORTEXPILOT_OPERATOR_ROLE;
const ORIGINAL_PM_COPY_VARIANT = process.env.NEXT_PUBLIC_PM_COPY_VARIANT;
function restoreEnv(): void {
if (ORIGINAL_API_BASE === undefined) delete process.env.NEXT_PUBLIC_API_BASE;
else process.env.NEXT_PUBLIC_API_BASE = ORIGINAL_API_BASE;
if (ORIGINAL_CORTEXPILOT_API_BASE === undefined) delete process.env.NEXT_PUBLIC_CORTEXPILOT_API_BASE;
else process.env.NEXT_PUBLIC_CORTEXPILOT_API_BASE = ORIGINAL_CORTEXPILOT_API_BASE;
if (ORIGINAL_CORTEXPILOT_PUBLIC_DOCS_BASE_URL === undefined) delete process.env.NEXT_PUBLIC_CORTEXPILOT_PUBLIC_DOCS_BASE_URL;
else process.env.NEXT_PUBLIC_CORTEXPILOT_PUBLIC_DOCS_BASE_URL = ORIGINAL_CORTEXPILOT_PUBLIC_DOCS_BASE_URL;
if (ORIGINAL_CORTEXPILOT_OPERATOR_ROLE === undefined) delete process.env.NEXT_PUBLIC_CORTEXPILOT_OPERATOR_ROLE;
else process.env.NEXT_PUBLIC_CORTEXPILOT_OPERATOR_ROLE = ORIGINAL_CORTEXPILOT_OPERATOR_ROLE;
if (ORIGINAL_PM_COPY_VARIANT === undefined) delete process.env.NEXT_PUBLIC_PM_COPY_VARIANT;
else process.env.NEXT_PUBLIC_PM_COPY_VARIANT = ORIGINAL_PM_COPY_VARIANT;
}
describe("dashboard env helpers", () => {
afterEach(() => {
restoreEnv();
});
it("prefers NEXT_PUBLIC_CORTEXPILOT_API_BASE and trims trailing slashes", () => {
process.env.NEXT_PUBLIC_CORTEXPILOT_API_BASE = " https://cortexpilot.example/api/// ";
process.env.NEXT_PUBLIC_API_BASE = "https://fallback.example";
expect(resolveDashboardApiBase()).toBe("https://cortexpilot.example/api");
});
it("falls back to NEXT_PUBLIC_API_BASE when the product-specific env is absent", () => {
process.env.NEXT_PUBLIC_API_BASE = "https://fallback.example";
expect(resolveDashboardApiBase()).toBe("https://fallback.example");
});
it("falls back to NEXT_PUBLIC_API_BASE when the preferred env is blank", () => {
process.env.NEXT_PUBLIC_CORTEXPILOT_API_BASE = " ";
process.env.NEXT_PUBLIC_API_BASE = "https://fallback.example/base//";
expect(resolveDashboardApiBase()).toBe("https://fallback.example/base");
});
it("uses the frontend contract default when both env values are absent", () => {
delete process.env.NEXT_PUBLIC_CORTEXPILOT_API_BASE;
delete process.env.NEXT_PUBLIC_API_BASE;
expect(resolveDashboardApiBase()).toBe(FRONTEND_API_CONTRACT.defaultApiBase);
});
it("falls through to the final default return when every candidate is empty", () => {
delete process.env.NEXT_PUBLIC_CORTEXPILOT_API_BASE;
delete process.env.NEXT_PUBLIC_API_BASE;
const previousDefault = FRONTEND_API_CONTRACT.defaultApiBase;
try {
(FRONTEND_API_CONTRACT as { defaultApiBase: string }).defaultApiBase = "";
expect(resolveDashboardApiBase()).toBe("");
} finally {
(FRONTEND_API_CONTRACT as { defaultApiBase: string }).defaultApiBase = previousDefault;
}
});
it("returns the PM copy variant verbatim after trimming", () => {
process.env.NEXT_PUBLIC_PM_COPY_VARIANT = " b ";
expect(resolveDashboardPmCopyVariantEnv()).toBe("b");
});
it("uses the default public docs base when the env override is absent", () => {
delete process.env.NEXT_PUBLIC_CORTEXPILOT_PUBLIC_DOCS_BASE_URL;
expect(resolveDashboardPublicDocsBaseUrl()).toBe("https://xiaojiou176-open.github.io/OpenVibeCoding");
expect(resolveDashboardPublicDocsHref("/ai-surfaces/")).toBe(
"https://xiaojiou176-open.github.io/OpenVibeCoding/ai-surfaces/"
);
});
it("uses a configured public docs base and trims trailing slashes", () => {
process.env.NEXT_PUBLIC_CORTEXPILOT_PUBLIC_DOCS_BASE_URL = " https://docs.example/cortexpilot/// ";
expect(resolveDashboardPublicDocsBaseUrl()).toBe("https://docs.example/cortexpilot");
expect(resolveDashboardPublicDocsHref("/builders/")).toBe("https://docs.example/cortexpilot/builders/");
expect(resolveDashboardPublicDocsHref("/compatibility/")).toBe("https://docs.example/cortexpilot/compatibility/");
expect(resolveDashboardPublicDocsHref("/integrations/")).toBe("https://docs.example/cortexpilot/integrations/");
expect(resolveDashboardPublicDocsHref("/skills/")).toBe("https://docs.example/cortexpilot/skills/");
});
it("allows same-origin public docs routes when the override is slash", () => {
process.env.NEXT_PUBLIC_CORTEXPILOT_PUBLIC_DOCS_BASE_URL = "/";
expect(resolveDashboardPublicDocsBaseUrl()).toBe("");
expect(resolveDashboardPublicDocsHref("/mcp/")).toBe("/mcp/");
});
it("leaves non-public-docs href values untouched", () => {
process.env.NEXT_PUBLIC_CORTEXPILOT_PUBLIC_DOCS_BASE_URL = "https://docs.example/cortexpilot";
expect(resolveDashboardPublicDocsHref("/pm")).toBe("/pm");
expect(resolveDashboardPublicDocsHref("https://github.com/xiaojiou176-open/OpenVibeCoding")).toBe(
"https://github.com/xiaojiou176-open/OpenVibeCoding"
);
});
it("uses NEXT_PUBLIC_CORTEXPILOT_OPERATOR_ROLE and normalizes casing", () => {
process.env.NEXT_PUBLIC_CORTEXPILOT_OPERATOR_ROLE = " tech_lead ";
expect(resolveDashboardOperatorRoleEnv()).toBe("TECH_LEAD");
});
});