Skip to content

Add regression test: Dehumanize() with trailing digit after a word - #1972

Open
hikmetba-bit wants to merge 1 commit into
Humanizr:mainfrom
hikmetba-bit:test/1959-dehumanize-trailing-digit-regression
Open

hikmetba-bit wants to merge 1 commit into
Humanizr:mainfrom
hikmetba-bit:test/1959-dehumanize-trailing-digit-regression

Conversation

@hikmetba-bit

@hikmetba-bit hikmetba-bit commented Sep 16, 2026 •

Copy link
Copy Markdown

Summary

Relates to #1959, which reported that "Item1".Dehumanize() returned "Item 1" in 3.0.1+ instead of "Item1" (the v2.14.1 behavior), tracing the cause to PascalizePattern's capture group excluding digits.

I went to fix PascalizePattern, but tracing the current code by hand, I believe this is already fixed on main — as a side effect of the ASCII fast-path optimizations added since the issue was filed, not the regex path the issue described:

  • Dehumanize() calls word.Humanize().Pascalize().
  • Humanize("Item1") goes through TryFromAsciiPascalCase (in StringHumanizeExtensions.cs), which via ReadAsciiWord correctly splits the trailing digit run into its own word, producing "Item 1".
  • Pascalize("Item 1") goes through TryPascalizeAscii (in InflectorExtensions.cs), whose separator check is c is ' ' or '_' or '-' or '.' — digits are not excluded from the "keep capitalizing" logic the way the old regex's [a-zA-Z] capture group was, so the space before 1 is correctly stripped, giving back "Item1".

This matches the existing Pascalize test suite, which already has [InlineData("customer name 1", "CustomerName1")] in InflectorTests.cs — the equivalent case for Pascalize alone is already covered. What's missing is coverage for the exact Dehumanize() round-trip from the issue.

Change

Adds [InlineData("Item1", "Item1")] and [InlineData("Item 1", "Item1")] to StringDehumanizeTests.CanDehumanizeIntoAPascalCaseWord. No production code changes.

Test plan

  • Could not run the test suite (no .NET SDK in this environment).
  • Verified by hand-tracing TryFromAsciiPascalCase and TryPascalizeAscii character-by-character for both "Item1" and "Item 1", and cross-checked that trace with a direct line-for-line port of both functions' character loop to Python, run against both inputs, to make sure I wasn't making an arithmetic mistake tracing it manually. Both confirm the expected "Item1" result.
  • If it turns out I'm wrong and this still fails on main, this test will make that failure visible and point at the actual root cause directly — happy to turn it into a real code fix if so.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests
    • Added coverage for dehumanizing words that include numerals, whether adjacent to or separated from the preceding word.

Humanizr#1959 reported that "Item1".Dehumanize() returned "Item 1" in 3.0.1+
instead of "Item1" (v2.14.1 behavior), tracing it to PascalizePattern's
capture group excluding digits.

Traced the current Dehumanize() -> Humanize() -> Pascalize() chain by
hand against the current ASCII fast paths (TryFromAsciiPascalCase /
TryPascalizeAscii in StringHumanizeExtensions.cs / InflectorExtensions.cs):
neither excludes digits from the "keep capitalizing/copying" logic the
way the old PascalizePattern regex did, so "Item1" now round-trips
correctly already. This appears to have been fixed as a side effect of
the ASCII fast-path optimization added after this issue was filed
(Pascalize's own test suite already covers the equivalent
"customer name 1" -> "CustomerName1" case), but Dehumanize() itself had
no regression test for this specific scenario.

Adds that coverage so a future change to either fast path that
reintroduces the regression fails a test instead of shipping silently.

No production code change - Humanizr#1959 appears already fixed on main.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: dae7dfc0-7bfa-46b3-bbd4-9b75fb285893

📥 Commits

Reviewing files that changed from the base of the PR and between ffc2b77 and f17cc9c.

📒 Files selected for processing (1)
  • tests/Humanizer.Tests/StringDehumanizeTests.cs

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

Changes

Dehumanize test coverage

Layer / File(s) Summary
Numeric suffix test cases
tests/Humanizer.Tests/StringDehumanizeTests.cs
The CanDehumanizeIntoAPascalCaseWord theory now tests "Item1" and "Item 1", with "Item1" as the expected result.

Priority: ⬇️ Low

Estimated code review effort: 1 (Trivial) | ~5 minutes

Change: Other

Merge Risk: ⚪ Minimal · up to f17cc

This PR adds regression tests for the reported numeric-suffix behavior without changing production code; it is mergeable pending normal test execution when the .NET SDK is available.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: regression coverage for Dehumanize() with a trailing digit after a word.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant