validateEnv.test.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import { describe, it, expect } from "vitest";
  2. import { validateEnv, MIN_SESSION_SECRET_LENGTH } from "./validateEnv.js";
  3. function validSecret() {
  4. return "x".repeat(MIN_SESSION_SECRET_LENGTH);
  5. }
  6. describe("validateEnv", () => {
  7. it("returns normalized config for a valid env", () => {
  8. const cfg = validateEnv({
  9. MONGODB_URI: "mongodb://localhost:27017/rhl",
  10. SESSION_SECRET: validSecret(),
  11. NAS_ROOT_PATH: "/mnt/niederlassungen/",
  12. // NODE_ENV intentionally omitted -> defaults to "development"
  13. PORT: "3000",
  14. });
  15. expect(cfg.mongodbUri).toBe("mongodb://localhost:27017/rhl");
  16. expect(cfg.sessionSecret).toBe(validSecret());
  17. expect(cfg.nasRootPath).toBe("/mnt/niederlassungen"); // trailing slash removed
  18. expect(cfg.nodeEnv).toBe("development");
  19. expect(cfg.port).toBe(3000);
  20. });
  21. it("throws with a clear error if required vars are missing", () => {
  22. try {
  23. validateEnv({});
  24. throw new Error("Expected validateEnv to throw");
  25. } catch (err) {
  26. expect(err.code).toBe("ENV_INVALID");
  27. expect(err.missing).toEqual([
  28. "MONGODB_URI",
  29. "SESSION_SECRET",
  30. "NAS_ROOT_PATH",
  31. ]);
  32. expect(String(err.message)).toContain(
  33. "Missing required environment variables:"
  34. );
  35. expect(String(err.message)).toContain("- MONGODB_URI");
  36. expect(String(err.message)).toContain("- SESSION_SECRET");
  37. expect(String(err.message)).toContain("- NAS_ROOT_PATH");
  38. }
  39. });
  40. it("rejects invalid MONGODB_URI schemes", () => {
  41. expect(() =>
  42. validateEnv({
  43. MONGODB_URI: "http://localhost:27017/rhl",
  44. SESSION_SECRET: validSecret(),
  45. NAS_ROOT_PATH: "/mnt/niederlassungen",
  46. NODE_ENV: "production",
  47. })
  48. ).toThrow(/MONGODB_URI/i);
  49. });
  50. it("rejects too-short SESSION_SECRET", () => {
  51. expect(() =>
  52. validateEnv({
  53. MONGODB_URI: "mongodb://localhost:27017/rhl",
  54. SESSION_SECRET: "short-secret",
  55. NAS_ROOT_PATH: "/mnt/niederlassungen",
  56. })
  57. ).toThrow(/SESSION_SECRET/i);
  58. });
  59. it("rejects placeholder-like SESSION_SECRET even if long enough", () => {
  60. const secret = `change-me-${"x".repeat(64)}`;
  61. expect(() =>
  62. validateEnv({
  63. MONGODB_URI: "mongodb://localhost:27017/rhl",
  64. SESSION_SECRET: secret,
  65. NAS_ROOT_PATH: "/mnt/niederlassungen",
  66. })
  67. ).toThrow(/placeholder/i);
  68. });
  69. it("rejects NAS_ROOT_PATH that is not absolute", () => {
  70. expect(() =>
  71. validateEnv({
  72. MONGODB_URI: "mongodb://localhost:27017/rhl",
  73. SESSION_SECRET: validSecret(),
  74. NAS_ROOT_PATH: "mnt/niederlassungen",
  75. })
  76. ).toThrow(/NAS_ROOT_PATH/i);
  77. });
  78. it('rejects NAS_ROOT_PATH containing ".." segments', () => {
  79. expect(() =>
  80. validateEnv({
  81. MONGODB_URI: "mongodb://localhost:27017/rhl",
  82. SESSION_SECRET: validSecret(),
  83. NAS_ROOT_PATH: "/mnt/../etc",
  84. })
  85. ).toThrow(/NAS_ROOT_PATH/i);
  86. });
  87. it("rejects invalid NODE_ENV values", () => {
  88. expect(() =>
  89. validateEnv({
  90. MONGODB_URI: "mongodb://localhost:27017/rhl",
  91. SESSION_SECRET: validSecret(),
  92. NAS_ROOT_PATH: "/mnt/niederlassungen",
  93. NODE_ENV: "staging",
  94. })
  95. ).toThrow(/NODE_ENV/i);
  96. });
  97. it("rejects invalid PORT values", () => {
  98. expect(() =>
  99. validateEnv({
  100. MONGODB_URI: "mongodb://localhost:27017/rhl",
  101. SESSION_SECRET: validSecret(),
  102. NAS_ROOT_PATH: "/mnt/niederlassungen",
  103. PORT: "70000",
  104. })
  105. ).toThrow(/PORT/i);
  106. expect(() =>
  107. validateEnv({
  108. MONGODB_URI: "mongodb://localhost:27017/rhl",
  109. SESSION_SECRET: validSecret(),
  110. NAS_ROOT_PATH: "/mnt/niederlassungen",
  111. PORT: "abc",
  112. })
  113. ).toThrow(/PORT/i);
  114. });
  115. });