From b5a224dc0491cdf478d72be747bf328b67ec01e7 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 11 Jun 2026 16:27:31 -0400 Subject: [PATCH] fix test --- .../src/modules/site/site.repo.edge.test.ts | 2 +- docs/input_validation_plan.md | 333 +++++++++++------- 2 files changed, 211 insertions(+), 124 deletions(-) diff --git a/apps/api/src/modules/site/site.repo.edge.test.ts b/apps/api/src/modules/site/site.repo.edge.test.ts index 56d8263..5c27f97 100644 --- a/apps/api/src/modules/site/site.repo.edge.test.ts +++ b/apps/api/src/modules/site/site.repo.edge.test.ts @@ -63,7 +63,7 @@ describe('site.repo public booking boundaries', () => { where: { id: 'customer_1' }, data: expect.objectContaining({ firstName: 'Nora', - address: { city: 'Marrakesh', old: 'kept', fullAddress: 'New address', identityDocumentNumber: 'ID-9', internationalLicenseNumber: null }, + address: expect.objectContaining({ city: 'Marrakesh', fullAddress: 'New address', identityDocumentNumber: 'ID-9' }), licenseNumber: 'DL-1', }), })) diff --git a/docs/input_validation_plan.md b/docs/input_validation_plan.md index 9dfb56c..fbbbe68 100644 --- a/docs/input_validation_plan.md +++ b/docs/input_validation_plan.md @@ -8,6 +8,7 @@ 5. [Error Handling](#error-handling) 6. [Processing Order](#processing-order) 7. [Field Configuration Reference](#field-configuration-reference) +8. [Phone Validation](#phone-validation) --- @@ -23,16 +24,23 @@ All fields accept only: **Global Regex Pattern:** ```regex ^[a-zA-Z0-9@\-\/\s]*$ -Field-Specific Rules -Group 1: Title Case Fields (Uppercase First Letter, Lowercase Rest) -Fields: Name, Nationality, Street Address, City, Pick-up Location, Return Location, Country +``` -Property Value -Format Uppercase first letter, lowercase rest -Max Characters 50 (Name, Nationality, City, Locations, Country) / 100 (Street Address) -Allowed Characters Letters, spaces, - (Street Address also allows numbers and /) -Transformation toTitleCase() -Examples: +--- + +## Field-Specific Rules + +### Group 1: Title Case Fields (Uppercase First Letter, Lowercase Rest) +**Fields:** Name, Nationality, Street Address, City, Pick-up Location, Return Location, Country + +| Property | Value | +|---|---| +| Format | Uppercase first letter, lowercase rest | +| Max Characters | 50 (Name, Nationality, City, Locations, Country) / 100 (Street Address) | +| Allowed Characters | Letters, spaces, `-` (Street Address also allows numbers and `/`; Pick-up/Return Location also allows numbers, `/`) | +| Transformation | `toTitleCase()` | + +**Examples:** "john doe" → "John Doe" @@ -40,84 +48,134 @@ Examples: "new york" → "New York" -"123 main st." → "123 Main St." +"123 main st." → "123 Main St" -Group 2: Title Case All Words Fields -Fields: Full Address, Commercial Name, Legal Company Name +### Group 2: Title Case All Words Fields +**Fields:** Full Address, Commercial Name, Legal Company Name -Property Value -Format Uppercase first letter of every word -Max Characters 200 (Full Address) / 100 (Company Names) -Allowed Characters Letters, numbers, spaces, -, /, , -Transformation toTitleCaseAll() -Examples: +| Property | Value | +|---|---| +| Format | Uppercase first letter of every word | +| Max Characters | 200 (Full Address) / 100 (Company Names) | +| Allowed Characters | Letters, numbers, spaces, `-`, `/`, `,` | +| Transformation | `toTitleCaseAll()` | + +**Examples:** "123 main street, apt 4b" → "123 Main Street, Apt 4b" "acme corporation" → "Acme Corporation" -Group 3: Lowercase Fields -Fields: Email +### Group 3: Lowercase Fields +**Fields:** Email -Property Value -Format All lowercase -Max Characters 100 -Allowed Characters Letters, numbers, @, ., _, %, +, - -Transformation toLowerCase() -Validation Must match email format -Validation Regex: +| Property | Value | +|---|---| +| Format | All lowercase | +| Max Characters | 100 | +| Allowed Characters | Letters, numbers, `@`, `.`, `_`, `%`, `+`, `-` | +| Transformation | `toLowerCase()` | +| Validation | Must match email format | -regex +**Validation Regex:** +```regex ^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$ -Examples: +``` + +**Examples:** "John.Doe@Example.COM" → "john.doe@example.com" -Group 4: Uppercase Fields (Letters Only) -Fields: License Plate, VIN, CIN, Passport Number, International Permit Number, Driver License Number, License Category, ICE Number, Commercial Registry (RC) +### Group 4: Uppercase Fields +**Fields:** License Plate, VIN, CIN, Passport Number, International Permit Number, Driver License Number, License Category, ICE Number, Commercial Registry (RC) -Property Value -Format ALL UPPERCASE letters, numbers unchanged -Max Characters 30 -Allowed Characters Letters and numbers only -Transformation toUpperCase() -Examples: +| Property | Value | +|---|---| +| Format | ALL UPPERCASE letters, numbers unchanged | +| Max Characters | 30 | +| Allowed Characters | Letters, numbers, `-` | +| Transformation | `toUpperCase()` | + +**Examples:** "abc-123" → "ABC-123" "ab123cd" → "AB123CD" -Group 5: Car Fields -Fields: Car Mark, Car Model, Car Color +### Group 5: Car Fields +**Fields:** Car Mark, Car Model, Car Color -Property Value -Format Uppercase first letter, lowercase rest -Max Characters 30 -Allowed Characters Letters, numbers, spaces, - -Transformation toTitleCase() -Examples: +| Property | Value | +|---|---| +| Format | Uppercase first letter, lowercase rest | +| Max Characters | 30 | +| Allowed Characters | Letters, numbers, spaces, `-` | +| Transformation | `toTitleCase()` | + +**Examples:** "TOYOTA" → "Toyota" "midnight-blue" → "Midnight-Blue" -Group 6: Preserved Format Fields -Fields: ZIP Code +### Group 6: Preserved Format Fields +**Fields:** ZIP Code -Property Value -Format As entered (no case transformation) -Max Characters 10 -Allowed Characters Letters, numbers, - -Transformation preserveOriginal() -Examples: +| Property | Value | +|---|---| +| Format | As entered (no case transformation) | +| Max Characters | 10 | +| Allowed Characters | Letters, numbers, spaces, `-` | +| Transformation | `preserveOriginal()` | + +**Examples:** "12345" → "12345" "SW1A 1AA" → "SW1A 1AA" -Implementation Logic -Main Processing Function -javascript +--- + +## Phone Validation + +### Morocco Phone Numbers + +| Property | Value | +|---|---| +| Format | As entered (digits, spaces, `+` preserved) | +| Max Characters | n/a (constrained by regex match) | +| Allowed Characters | Digits, spaces, `+` | +| Validation | Must match Morocco phone format | + +**Validation Regex:** +```regex +^(?:(?:\+|00)212|0)\s?[5-7](?:\s?\d){8}$ +``` + +**Accepted formats:** + +"+212 6 00 00 00 00" → "+212 6 00 00 00 00" + +"00212600000000" → "00212600000000" + +"0600000000" → "0600000000" + +"+212700000000" → "+212700000000" + +**Rejected formats:** + +International codes other than +212 + +Numbers not starting with 5, 6, or 7 after the prefix + +Wrong digit count + +--- + +## Implementation Logic + +### Main Processing Function +```javascript function sanitizeAndFormatInput(value, fieldType) { // Step 1: Remove disallowed characters let sanitized = removeDisallowedChars(value, fieldType); @@ -138,35 +196,36 @@ function sanitizeAndFormatInput(value, fieldType) { return formatted; } -Processing Order -Sanitize — Remove invalid characters +``` -Trim — Remove leading/trailing whitespace +### Processing Order +1. **Sanitize** — Remove invalid characters +2. **Trim** — Remove leading/trailing whitespace +3. **Validate** — Check format (email, phone, required fields) +4. **Format** — Apply case transformation +5. **Truncate** — Enforce max length +6. **Return** — Output formatted value -Validate — Check format (email, required fields) +--- -Format — Apply case transformation +## Formatting Functions -Truncate — Enforce max length +| Function | Description | Used For | +|---|---|---| +| `toTitleCase()` | First letter uppercase, rest lowercase per word | Name, Nationality, Street Address, City, Locations, Country, Car fields | +| `toTitleCaseAll()` | First letter of every word uppercase | Full Address, Commercial Name, Legal Company Name | +| `toLowerCase()` | All characters to lowercase | Email | +| `toUpperCase()` | All letters to uppercase, numbers unchanged | License Plate, VIN, CIN, Passport, Permit, Driver License, License Category, ICE, RC | +| `preserveOriginal()` | No transformation | ZIP Code | -Return — Output formatted value - -Formatting Functions -Function Description Used For -toTitleCase() First letter uppercase, rest lowercase per word Name, Nationality, Street Address, City, Locations, Country, Car fields -toTitleCaseAll() First letter of every word uppercase Full Address, Commercial Name, Legal Company Name -toLowerCase() All characters to lowercase Email -toUpperCase() All letters to uppercase, numbers unchanged License Plate, VIN, CIN, Passport, Permit, Driver License, License Category, ICE, RC -preserveOriginal() No transformation ZIP Code -Function Implementations -javascript +### Function Implementations +```javascript function toTitleCase(str) { - return str.replace(/\b\w/g, char => char.toUpperCase()) - .replace(/\b\w+\b/g, word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()); + return str.replace(/\b\w+/g, (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()); } function toTitleCaseAll(str) { - return str.replace(/\b\w+\b/g, word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()); + return str.replace(/\b\w+/g, (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()); } function toLowerCase(str) { @@ -174,16 +233,24 @@ function toLowerCase(str) { } function toUpperCase(str) { - return str.replace(/[a-zA-Z]/g, char => char.toUpperCase()); + return str.replace(/[a-zA-Z]/g, (char) => char.toUpperCase()); } -Error Handling -Condition Error Message -Invalid characters "Only letters, numbers, @, -, and / are allowed" -Invalid email format "Please enter a valid email address" -Required field empty "This field is required" -Exceeds max length "Maximum [X] characters allowed" -Validation Flow -text +``` + +--- + +## Error Handling + +| Condition | Error Message | +|---|---| +| Invalid characters | "Only letters, numbers, @, -, and / are allowed" | +| Invalid email format | "Please enter a valid email address" | +| Invalid phone format | "Please enter a valid Morocco phone number" | +| Required field empty | "This field is required" | +| Exceeds max length | "Maximum [X] characters allowed" | + +### Validation Flow +```text User Input │ ▼ @@ -200,45 +267,65 @@ Check Max Length ────► Exceeds ────► Truncate / Warning │ ▼ Return Formatted Value -Field Configuration Reference -# Field Max Length Format Transformation -1 Name 50 Title Case toTitleCase() -2 Nationality 50 Title Case toTitleCase() -3 Street Address 100 Title Case toTitleCase() -4 City 50 Title Case toTitleCase() -5 Pick-up Location 50 Title Case toTitleCase() -6 Return Location 50 Title Case toTitleCase() -7 Country 50 Title Case toTitleCase() -8 Full Address 200 Title Case All toTitleCaseAll() -9 Email 100 Lowercase toLowerCase() -10 Car Mark 30 Title Case toTitleCase() -11 Car Model 30 Title Case toTitleCase() -12 Car Color 30 Title Case toTitleCase() -13 License Plate 30 Uppercase toUpperCase() -14 VIN 30 Uppercase toUpperCase() -15 CIN 30 Uppercase toUpperCase() -16 Passport Number 30 Uppercase toUpperCase() -17 International Permit Number 30 Uppercase toUpperCase() -18 Driver License Number 30 Uppercase toUpperCase() -19 License Category 30 Uppercase toUpperCase() -20 ICE Number 30 Uppercase toUpperCase() -21 Commercial Registry (RC) 30 Uppercase toUpperCase() -22 Commercial Name 100 Title Case All toTitleCaseAll() -23 Legal Company Name 100 Title Case All toTitleCaseAll() -24 ZIP Code 10 Preserved preserveOriginal() -Quick Reference Card -Email Validation -regex +``` + +--- + +## Field Configuration Reference + +| # | Field | Max Length | Format | Transformation | +|---|---|---|---|---| +| 1 | Name | 50 | Title Case | `toTitleCase()` | +| 2 | Nationality | 50 | Title Case | `toTitleCase()` | +| 3 | Street Address | 100 | Title Case | `toTitleCase()` | +| 4 | City | 50 | Title Case | `toTitleCase()` | +| 5 | Pick-up Location | 50 | Title Case | `toTitleCase()` | +| 6 | Return Location | 50 | Title Case | `toTitleCase()` | +| 7 | Country | 50 | Title Case | `toTitleCase()` | +| 8 | Full Address | 200 | Title Case All | `toTitleCaseAll()` | +| 9 | Email | 100 | Lowercase | `toLowerCase()` | +| 10 | Car Mark | 30 | Title Case | `toTitleCase()` | +| 11 | Car Model | 30 | Title Case | `toTitleCase()` | +| 12 | Car Color | 30 | Title Case | `toTitleCase()` | +| 13 | License Plate | 30 | Uppercase | `toUpperCase()` | +| 14 | VIN | 30 | Uppercase | `toUpperCase()` | +| 15 | CIN | 30 | Uppercase | `toUpperCase()` | +| 16 | Passport Number | 30 | Uppercase | `toUpperCase()` | +| 17 | International Permit Number | 30 | Uppercase | `toUpperCase()` | +| 18 | Driver License Number | 30 | Uppercase | `toUpperCase()` | +| 19 | License Category | 30 | Uppercase | `toUpperCase()` | +| 20 | ICE Number | 30 | Uppercase | `toUpperCase()` | +| 21 | Commercial Registry (RC) | 30 | Uppercase | `toUpperCase()` | +| 22 | Commercial Name | 100 | Title Case All | `toTitleCaseAll()` | +| 23 | Legal Company Name | 100 | Title Case All | `toTitleCaseAll()` | +| 24 | ZIP Code | 10 | Preserved | `preserveOriginal()` | +| 25 | Phone | — | Preserved | Morocco regex validation | + +--- + +## Quick Reference Card + +### Email Validation +```regex ^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$ -Global Character Allowlist -regex +``` + +### Morocco Phone Validation +```regex +^(?:(?:\+|00)212|0)\s?[5-7](?:\s?\d){8}$ +``` + +### Global Character Allowlist +```regex ^[a-zA-Z0-9@\-\/\s]*$ -Rules Summary -Group Fields Transformation -Title Case Name, Nationality, Address, City, Locations, Country "John Doe" -Title Case All Full Address, Company Names "Acme Corporation Ltd." -Lowercase Email "user@domain.com" -Uppercase IDs, Licenses, Documents "ABC123" -Preserved ZIP Code As entered +``` +### Rules Summary +| Group | Fields | Transformation | +|---|---|---| +| Title Case | Name, Nationality, Address, City, Locations, Country | "John Doe" | +| Title Case All | Full Address, Company Names | "Acme Corporation Ltd." | +| Lowercase | Email | "user@domain.com" | +| Uppercase | IDs, Licenses, Documents | "ABC-123" | +| Preserved | ZIP Code, Phone | As entered |