userManagementUx.test.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* @vitest-environment node */
  2. import { describe, it, expect } from "vitest";
  3. import {
  4. normalizeUsernameForConfirmation,
  5. isUsernameConfirmationMatch,
  6. normalizeBranchIdInput,
  7. normalizeBranchNumberInput,
  8. formatBranchIdFromNumberInput,
  9. extractBranchNumberInputFromBranchId,
  10. isValidBranchIdFormat,
  11. evaluateBranchExistence,
  12. MASKED_PASSWORD_VALUE,
  13. hasTemporaryPassword,
  14. getDisplayedTemporaryPassword,
  15. } from "./userManagementUx.js";
  16. describe("lib/frontend/admin/users/userManagementUx", () => {
  17. describe("username confirmation", () => {
  18. it("normalizes to lowercase and trims", () => {
  19. expect(normalizeUsernameForConfirmation(" Alice.Admin ")).toBe(
  20. "alice.admin",
  21. );
  22. });
  23. it("matches typed username case-insensitively after trimming", () => {
  24. expect(
  25. isUsernameConfirmationMatch({
  26. expectedUsername: "branch.user",
  27. typedUsername: " BRANCH.USER ",
  28. }),
  29. ).toBe(true);
  30. });
  31. it("returns false for empty or mismatching values", () => {
  32. expect(
  33. isUsernameConfirmationMatch({
  34. expectedUsername: "branch.user",
  35. typedUsername: "other.user",
  36. }),
  37. ).toBe(false);
  38. expect(
  39. isUsernameConfirmationMatch({
  40. expectedUsername: "",
  41. typedUsername: "",
  42. }),
  43. ).toBe(false);
  44. });
  45. });
  46. describe("branch formatting", () => {
  47. it("normalizes branchId input to uppercase + trim", () => {
  48. expect(normalizeBranchIdInput(" nl01 ")).toBe("NL01");
  49. });
  50. it("normalizes numeric branch input and strips non-digits", () => {
  51. expect(normalizeBranchNumberInput(" 001 ")).toBe("1");
  52. expect(normalizeBranchNumberInput(" 32a ")).toBe("32");
  53. expect(normalizeBranchNumberInput("000")).toBe("0");
  54. expect(normalizeBranchNumberInput("abc")).toBe("");
  55. });
  56. it("formats NL branchId with 2+ digit policy", () => {
  57. expect(formatBranchIdFromNumberInput("1")).toBe("NL01");
  58. expect(formatBranchIdFromNumberInput("32")).toBe("NL32");
  59. expect(formatBranchIdFromNumberInput("200")).toBe("NL200");
  60. });
  61. it("extracts numeric branch input from an existing branchId", () => {
  62. expect(extractBranchNumberInputFromBranchId("NL01")).toBe("01");
  63. expect(extractBranchNumberInputFromBranchId("nl200")).toBe("200");
  64. expect(extractBranchNumberInputFromBranchId("XX1")).toBe("");
  65. });
  66. it("validates branchId format", () => {
  67. expect(isValidBranchIdFormat("NL01")).toBe(true);
  68. expect(isValidBranchIdFormat("nl200")).toBe(true);
  69. expect(isValidBranchIdFormat("XX1")).toBe(false);
  70. expect(isValidBranchIdFormat("NL")).toBe(false);
  71. });
  72. });
  73. describe("branch existence decision", () => {
  74. it("blocks submit for unknown branch only when list is ready", () => {
  75. expect(
  76. evaluateBranchExistence({
  77. role: "branch",
  78. branchId: "NL99",
  79. branchesStatus: "ready",
  80. availableBranchIds: ["NL01", "NL02"],
  81. }).shouldBlockSubmit,
  82. ).toBe(true);
  83. });
  84. it("allows submit when branch exists in ready list", () => {
  85. expect(
  86. evaluateBranchExistence({
  87. role: "branch",
  88. branchId: "NL02",
  89. branchesStatus: "ready",
  90. availableBranchIds: ["NL01", "NL02"],
  91. }).shouldBlockSubmit,
  92. ).toBe(false);
  93. });
  94. it("is fail-open when list fetch failed", () => {
  95. const result = evaluateBranchExistence({
  96. role: "branch",
  97. branchId: "NL99",
  98. branchesStatus: "error",
  99. availableBranchIds: null,
  100. });
  101. expect(result.listError).toBe(true);
  102. expect(result.shouldBlockSubmit).toBe(false);
  103. });
  104. it("is irrelevant for non-branch roles", () => {
  105. const result = evaluateBranchExistence({
  106. role: "admin",
  107. branchId: "NL99",
  108. branchesStatus: "ready",
  109. availableBranchIds: ["NL01"],
  110. });
  111. expect(result.isBranchRole).toBe(false);
  112. expect(result.shouldBlockSubmit).toBe(false);
  113. });
  114. });
  115. describe("temporary password display", () => {
  116. it("detects availability of temporary password values", () => {
  117. expect(hasTemporaryPassword("TempPass123!")).toBe(true);
  118. expect(hasTemporaryPassword("")).toBe(false);
  119. expect(hasTemporaryPassword(null)).toBe(false);
  120. });
  121. it("returns masked value by default and reveals only when requested", () => {
  122. expect(
  123. getDisplayedTemporaryPassword({
  124. temporaryPassword: "TempPass123!",
  125. isVisible: false,
  126. }),
  127. ).toBe(MASKED_PASSWORD_VALUE);
  128. expect(
  129. getDisplayedTemporaryPassword({
  130. temporaryPassword: "TempPass123!",
  131. isVisible: true,
  132. }),
  133. ).toBe("TempPass123!");
  134. expect(
  135. getDisplayedTemporaryPassword({
  136. temporaryPassword: "",
  137. isVisible: true,
  138. }),
  139. ).toBe(MASKED_PASSWORD_VALUE);
  140. });
  141. });
  142. });