fix: Update getInitialsFromName to sanitize name#3743
fix: Update getInitialsFromName to sanitize name#3743mannycarrera4 wants to merge 5 commits intoWorkday:masterfrom
Conversation
Workday/canvas-kit
|
||||||||||||||||||||||||||||||||||||||||
| Project |
Workday/canvas-kit
|
| Branch Review |
mc-fix-avatar-initials-sanitize
|
| Run status |
|
| Run duration | 02m 24s |
| Commit |
|
| Committer | Manuel Carrera |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
1
|
|
|
86
|
|
|
0
|
|
|
862
|
| View all changes introduced in this branch ↗︎ | |
UI Coverage
19.36%
|
|
|---|---|
|
|
1539
|
|
|
367
|
Accessibility
99.33%
|
|
|---|---|
|
|
6 critical
5 serious
0 moderate
2 minor
|
|
|
77
|
There was a problem hiding this comment.
Pull request overview
This PR fixes a bug where getInitialsFromName didn't handle names with parenthetical content (like titles or departments). The implementation now sanitizes names by removing parenthetical content and filtering out numeric and Roman numeral suffixes before extracting initials.
Changes:
- Updated
getInitialsFromNameto remove parenthetical content using regex - Added filtering for numeric suffixes and Roman numeral suffixes (III, IV, etc.)
- Added comprehensive test suite with 14 test cases covering various edge cases
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| modules/preview-react/avatar/lib/getInitialsFromName.ts | Enhanced sanitization logic to handle parenthetical content and suffix filtering |
| modules/preview-react/avatar/spec/getInitialsFromName.spec.tsx | New comprehensive test suite covering various name formats and edge cases |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| expect(getInitialsFromName('Mohammed Al-Rashid')).toBe('MA'); | ||
| }); |
There was a problem hiding this comment.
The function doesn't handle hyphenated names or names with apostrophes consistently. For example:
- "Mary-Jane Smith" would produce "MS" (treating "Mary-Jane" as one word)
- "O'Brien" would be treated as one word
- "Jean-Luc Picard" would produce "JP"
While the current behavior may be acceptable, consider whether hyphenated first/last names should be split or kept together. The test case for "Mohammed Al-Rashid" expects "MA", which suggests the current behavior is intentional, but this should be explicitly tested for various hyphenation scenarios to ensure consistency.
| expect(getInitialsFromName('Logan McNeil iii')).toBe('LM'); | ||
| expect(getInitialsFromName('Logan McNeil Iii')).toBe('LM'); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Missing test coverage for edge case where someone has a single-letter name that happens to be I, V, or X (e.g., "X Æ A-12" or "Malcolm X"). Due to the overly broad Roman numeral regex /^[IVX]+$/i, these valid name parts would be incorrectly filtered out.
Add test cases like:
getInitialsFromName('Malcolm X')should return 'MX', not 'M'getInitialsFromName('X Smith')should return 'XS', not 'S'
This edge case will be resolved when the Roman numeral regex is fixed to match only valid Roman numeral suffixes.
| // Filter out parts that are purely numeric or Roman numerals (suffixes like III, IV) | ||
| const filteredParts = nameParts.filter(part => { | ||
| const isNumeric = /^\d+$/.test(part); | ||
| const isRomanNumeral = /^[IVX]+$/i.test(part); |
There was a problem hiding this comment.
The Roman numeral regex pattern is too broad and will incorrectly match valid name parts. For example, it will match "Vin" (contains only I, V, X), "Vivi" (contains only I, V, X), or any word composed solely of the letters I, V, and X in any combination. This could incorrectly filter out legitimate names or parts of names.
Consider using a more precise pattern that matches only valid Roman numerals like: /^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/i or a simpler whitelist approach that matches common suffixes: /^(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV)$/i
| const isRomanNumeral = /^[IVX]+$/i.test(part); | |
| const isRomanNumeral = /^(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV)$/i.test(part); |
There was a problem hiding this comment.
Yeah, I don't think we need to test for roman numerals like LX. Low odds of running into Alan Smith the 60th, but let's say Pope Leo XIV is on Workday. We should probably accommodate his Holiness.
| it('should handle mixed case Roman numerals', () => { | ||
| expect(getInitialsFromName('Logan McNeil iii')).toBe('LM'); | ||
| expect(getInitialsFromName('Logan McNeil Iii')).toBe('LM'); |
There was a problem hiding this comment.
These test cases expose a flaw in the implementation. "Iii" and "iii" are not valid Roman numerals (the valid form is "III"), yet the implementation's regex /^[IVX]+$/i will match them. This test passes because it validates the current buggy behavior.
When the Roman numeral regex is fixed to only match valid Roman numerals, these tests should be updated to either:
- Expect "LI" as the result (treating "Iii" as a name part, not a suffix), or
- Use valid Roman numerals like "III" if the intent is to test suffix filtering
| it('should handle mixed case Roman numerals', () => { | |
| expect(getInitialsFromName('Logan McNeil iii')).toBe('LM'); | |
| expect(getInitialsFromName('Logan McNeil Iii')).toBe('LM'); | |
| it('should filter valid Roman numeral suffixes', () => { | |
| expect(getInitialsFromName('Logan McNeil III')).toBe('LM'); | |
| expect(getInitialsFromName('Logan McNeil II')).toBe('LM'); |
| expect(getInitialsFromName('Logan McNeil iii')).toBe('LM'); | ||
| expect(getInitialsFromName('Logan McNeil Iii')).toBe('LM'); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
The function does not handle unmatched parentheses or other bracket types (e.g., square brackets, curly braces). Consider adding test cases for edge cases like:
- Unmatched opening parenthesis: "John Smith ("
- Unmatched closing parenthesis: "John Smith )"
- Square brackets: "John Smith [Department]"
- Nested parentheses: "John Smith ((nested))"
The current regex /\([^)]*\)/g only handles matched parentheses, which could leave orphaned opening parentheses in the sanitized string.
| // Trim and split by one or more whitespace characters | ||
| const nameParts = name.trim().split(/\s+/).filter(Boolean); | ||
| // Remove parenthetical content (e.g., titles, departments) and trim | ||
| const sanitized = name.replace(/\([^)]*\)/g, '').trim(); |
There was a problem hiding this comment.
The parenthetical content removal only handles round parentheses (). If the intent is to sanitize titles, departments, or similar metadata, you should also consider removing content in other bracket types like square brackets [] or curly braces {}, which are also commonly used for similar purposes.
For example, the current implementation won't sanitize "John Smith [Engineering]" or "John Smith {CEO}". Consider using a pattern like /[\(\[\{][^\)\]\}]*[\)\]\}]/g if you want to handle all bracket types.
| const sanitized = name.replace(/\([^)]*\)/g, '').trim(); | |
| const sanitized = name.replace(/[\(\[\{][^\)\]\}]*[\)\]\}]/g, '').trim(); |
| @@ -1,10 +1,20 @@ | |||
| export const getInitialsFromName = (name: string) => { | |||
There was a problem hiding this comment.
The function lacks JSDoc documentation. Based on the codebase convention (see modules/preview-react/select/lib/utils.ts and modules/preview-react/select/lib/scrolling.ts), exported utility functions should have JSDoc comments that describe their purpose, parameters, and return values.
Consider adding JSDoc documentation like:
/**
- Extracts initials from a person's name by taking the first letter of the first and last name parts.
- Removes parenthetical content (e.g., titles, departments) and filters out numeric and Roman numeral suffixes.
- @param name - The full name to extract initials from
- @returns A string containing the extracted initials in uppercase, or an empty string if no valid name parts are found
*/
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Alan B Smith <a.bax.smith@gmail.com>
|
I'm gonna close this PR, there's too many edge cases, unless we come up with a standard to handle all of these, this is just going to cause more confusion, teams should use preferredInitials |
Summary
Fixes: #3740
Release Category
Components
Checklist
ready for reviewhas been added to PRFor the Reviewer
Where Should the Reviewer Start?
Areas for Feedback? (optional)
Testing Manually
Screenshots or GIFs (if applicable)
Thank You Gif (optional)