Skip to content

Commit f1da52a

Browse files
committed
fix: ensure the ServiceNow case ID matches the expected pattern
1 parent cf058fa commit f1da52a

2 files changed

Lines changed: 24 additions & 59 deletions

File tree

application/CohortManager/src/Web/app/lib/formValidationSchemas.test.ts

Lines changed: 19 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ describe("formValidationSchemas", () => {
44
describe("updateExceptionsSchema", () => {
55
describe("serviceNowID validation", () => {
66
describe("valid ServiceNow case IDs", () => {
7-
it("should accept valid ServiceNow case ID with 9 characters", () => {
7+
it("should accept valid ServiceNow case ID with 2 letters and 7 digits", () => {
88
const validData = { serviceNowID: "CS1234567" };
99
const result = updateExceptionsSchema().safeParse(validData);
1010

@@ -14,7 +14,7 @@ describe("formValidationSchemas", () => {
1414
}
1515
});
1616

17-
it("should accept valid ServiceNow case ID with more than 9 characters", () => {
17+
it("should accept valid ServiceNow case ID with more than 7 digits after the two letters", () => {
1818
const validData = { serviceNowID: "CS123456789" };
1919
const result = updateExceptionsSchema().safeParse(validData);
2020

@@ -24,36 +24,8 @@ describe("formValidationSchemas", () => {
2424
}
2525
});
2626

27-
it("should accept all uppercase letters", () => {
28-
const validData = { serviceNowID: "ABCD12345" };
29-
const result = updateExceptionsSchema().safeParse(validData);
30-
31-
expect(result.success).toBe(true);
32-
});
33-
34-
it("should accept all lowercase letters", () => {
35-
const validData = { serviceNowID: "abcd12345" };
36-
const result = updateExceptionsSchema().safeParse(validData);
37-
38-
expect(result.success).toBe(true);
39-
});
40-
41-
it("should accept mixed case letters", () => {
42-
const validData = { serviceNowID: "AbCd12345" };
43-
const result = updateExceptionsSchema().safeParse(validData);
44-
45-
expect(result.success).toBe(true);
46-
});
47-
48-
it("should accept all numbers", () => {
49-
const validData = { serviceNowID: "123456789" };
50-
const result = updateExceptionsSchema().safeParse(validData);
51-
52-
expect(result.success).toBe(true);
53-
});
54-
55-
it("should accept all letters", () => {
56-
const validData = { serviceNowID: "ABCDEFGHI" };
27+
it("should accept case-insensitive letters prefix", () => {
28+
const validData = { serviceNowID: "cS1234567" };
5729
const result = updateExceptionsSchema().safeParse(validData);
5830

5931
expect(result.success).toBe(true);
@@ -84,15 +56,15 @@ describe("formValidationSchemas", () => {
8456
});
8557
});
8658

87-
describe("invalid ServiceNow case IDs - minimum length", () => {
88-
it("should reject case ID with less than 9 characters", () => {
59+
describe("invalid ServiceNow case IDs - format and length", () => {
60+
it("should reject case ID with fewer than 7 digits after two letters", () => {
8961
const invalidData = { serviceNowID: "CS12345" };
9062
const result = updateExceptionsSchema().safeParse(invalidData);
9163

9264
expect(result.success).toBe(false);
9365
if (!result.success) {
9466
expect(result.error.issues[0].message).toBe(
95-
"ServiceNow case ID must be nine characters or more"
67+
"ServiceNow case ID must start with two letters followed by at least seven digits (e.g. CS0619153)"
9668
);
9769
}
9870
});
@@ -104,7 +76,7 @@ describe("formValidationSchemas", () => {
10476
expect(result.success).toBe(false);
10577
if (!result.success) {
10678
expect(result.error.issues[0].message).toBe(
107-
"ServiceNow case ID must be nine characters or more"
79+
"ServiceNow case ID must start with two letters followed by at least seven digits (e.g. CS0619153)"
10880
);
10981
}
11082
});
@@ -116,7 +88,7 @@ describe("formValidationSchemas", () => {
11688
expect(result.success).toBe(false);
11789
if (!result.success) {
11890
expect(result.error.issues[0].message).toBe(
119-
"ServiceNow case ID must be nine characters or more"
91+
"ServiceNow case ID must start with two letters followed by at least seven digits (e.g. CS0619153)"
12092
);
12193
}
12294
});
@@ -130,7 +102,7 @@ describe("formValidationSchemas", () => {
130102
expect(result.success).toBe(false);
131103
if (!result.success) {
132104
expect(result.error.issues[0].message).toBe(
133-
"ServiceNow case ID must only contain letters and numbers"
105+
"ServiceNow case ID must start with two letters followed by at least seven digits (e.g. CS0619153)"
134106
);
135107
}
136108
});
@@ -142,7 +114,7 @@ describe("formValidationSchemas", () => {
142114
expect(result.success).toBe(false);
143115
if (!result.success) {
144116
expect(result.error.issues[0].message).toBe(
145-
"ServiceNow case ID must only contain letters and numbers"
117+
"ServiceNow case ID must start with two letters followed by at least seven digits (e.g. CS0619153)"
146118
);
147119
}
148120
});
@@ -154,7 +126,7 @@ describe("formValidationSchemas", () => {
154126
expect(result.success).toBe(false);
155127
if (!result.success) {
156128
expect(result.error.issues[0].message).toBe(
157-
"ServiceNow case ID must only contain letters and numbers"
129+
"ServiceNow case ID must start with two letters followed by at least seven digits (e.g. CS0619153)"
158130
);
159131
}
160132
});
@@ -166,7 +138,7 @@ describe("formValidationSchemas", () => {
166138
expect(result.success).toBe(false);
167139
if (!result.success) {
168140
expect(result.error.issues[0].message).toBe(
169-
"ServiceNow case ID must only contain letters and numbers"
141+
"ServiceNow case ID must start with two letters followed by at least seven digits (e.g. CS0619153)"
170142
);
171143
}
172144
});
@@ -178,7 +150,7 @@ describe("formValidationSchemas", () => {
178150
expect(result.success).toBe(false);
179151
if (!result.success) {
180152
expect(result.error.issues[0].message).toBe(
181-
"ServiceNow case ID must only contain letters and numbers"
153+
"ServiceNow case ID must start with two letters followed by at least seven digits (e.g. CS0619153)"
182154
);
183155
}
184156
});
@@ -247,14 +219,14 @@ describe("formValidationSchemas", () => {
247219
}
248220
});
249221

250-
it("should show length error before regex error for short invalid strings", () => {
251-
const invalidData = { serviceNowID: "CS!" };
222+
it("should show space error before format error when spaces present", () => {
223+
const invalidData = { serviceNowID: "CS123 4567" };
252224
const result = updateExceptionsSchema().safeParse(invalidData);
253225

254226
expect(result.success).toBe(false);
255227
if (!result.success) {
256228
expect(result.error.issues[0].message).toBe(
257-
"ServiceNow case ID must be nine characters or more"
229+
"ServiceNow case ID must not contain spaces"
258230
);
259231
}
260232
});
@@ -308,7 +280,8 @@ describe("formValidationSchemas", () => {
308280
expect(result.error.issues).toEqual(
309281
expect.arrayContaining([
310282
expect.objectContaining({
311-
message: "ServiceNow case ID must be nine characters or more",
283+
message:
284+
"ServiceNow case ID must start with two letters followed by at least seven digits (e.g. CS0619153)",
312285
}),
313286
])
314287
);

application/CohortManager/src/Web/app/lib/formValidationSchemas.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import { z } from "zod";
22

33
// This schema validates the ServiceNow case ID for updating exceptions status.
44
// In edit mode, empty input is allowed to clear the ServiceNow ID (convert raised to non-raised).
5-
// In non-edit mode, the ID is required and must be at least 9 characters long,
6-
// contain only alphanumeric characters, and not include spaces.
5+
// In non-edit mode, the ID is required and must start with two letters followed by at least seven digits (e.g. CS0619153).
76
export const updateExceptionsSchema = (isEditMode: boolean = false) =>
87
z.object({
98
serviceNowID: z
@@ -20,21 +19,14 @@ export const updateExceptionsSchema = (isEditMode: boolean = false) =>
2019
if (isEditMode && val === "") {
2120
return true;
2221
}
23-
// Otherwise, require at least 9 characters
24-
return val.length >= 9;
25-
}, "ServiceNow case ID must be nine characters or more")
26-
.refine((val) => {
27-
if (isEditMode && val === "") {
28-
return true;
29-
}
30-
// Otherwise, check for spaces
22+
// Disallow spaces explicitly for clearer error
3123
return !val.includes(" ");
3224
}, "ServiceNow case ID must not contain spaces")
3325
.refine((val) => {
3426
if (isEditMode && val === "") {
3527
return true;
3628
}
37-
// Otherwise, check alphanumeric pattern
38-
return /^[a-zA-Z0-9]+$/.test(val);
39-
}, "ServiceNow case ID must only contain letters and numbers"),
29+
// Must be two letters followed by at least seven digits
30+
return /^[A-Za-z]{2}\d{7,}$/.test(val);
31+
}, "ServiceNow case ID must start with two letters followed by at least seven digits (e.g. CS0619153)"),
4032
});

0 commit comments

Comments
 (0)