Skip to content

[9/11] Add contains/starts-with/ends-with substring checkers - #232

Merged
cinar merged 1 commit into
mainfrom
p1-09-contains-family
Sep 5, 2026
Merged

[9/11] Add contains/starts-with/ends-with substring checkers#232
cinar merged 1 commit into
mainfrom
p1-09-contains-family

Conversation

@cinar

@cinar cinar commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Problem

Common needs for password composition rules, URL/path prefix checks, and identifier conventions — trivial to implement, but previously required a custom RegisterMaker each.

Fix

Add contains/starts-with/ends-with:

  • contains.go/starts_with.go/ends_with.go are thin wrappers around strings.Contains/HasPrefix/HasSuffix, following the established checker pattern. Each error carries the expected substring/prefix/suffix in its data so failures are actionable.
  • All three registered in maker.go.
  • Mapped to JSON Schema's pattern in schema_maker.go (.*substr.* / ^prefix.* / .*suffix$), running the parameter through regexp.QuoteMeta first so a literal value containing regex metacharacters (e.g. starts-with:a.b) doesn't produce a broken or unintentionally permissive pattern.
  • NOT_CONTAINS/NOT_STARTS_WITH/NOT_ENDS_WITH messages added to all 23 locale files plus en-US.
  • Documented in the README's checker table.

Testing

  • contains_test.go/starts_with_test.go/ends_with_test.go: valid/invalid, non-string-field panic, struct-tag valid/invalid.
  • TestJSONSchemaContainsStartsWithEndsWithPatterns for the pattern mappings.
  • Full suite passes, 100% coverage maintained.
  • go vet, gosec, revive clean.

Fixes #206


Chain note: PR 9 of 11.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FLdVmP5daHiknrTW4Geh2i

Base automatically changed from p1-08-alpha-numeric to main September 5, 2026 17:25
@cinar
cinar force-pushed the p1-09-contains-family branch from ce47377 to acdf1ac Compare September 5, 2026 17:40
Common needs for password composition rules, URL/path prefix checks,
and identifier conventions, and trivial to implement, but previously
required a custom RegisterMaker each.

- contains.go/starts_with.go/ends_with.go are thin wrappers around
  strings.Contains/HasPrefix/HasSuffix, following the established
  checker pattern. Each error carries the expected substring/prefix/
  suffix in its data so failures are actionable.
- All three registered in maker.go.
- Mapped to JSON Schema's pattern in schema_maker.go
  (".*substr.*" / "^prefix.*" / ".*suffix$"), running the parameter
  through regexp.QuoteMeta first so a literal value containing regex
  metacharacters (e.g. starts-with:a.b) doesn't produce a broken or
  unintentionally permissive pattern.
- NOT_CONTAINS/NOT_STARTS_WITH/NOT_ENDS_WITH messages added to all 23
  locale files plus en-US.
- Documented in the README's checker table.

Fixes #206

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FLdVmP5daHiknrTW4Geh2i
@cinar
cinar force-pushed the p1-09-contains-family branch from acdf1ac to aefa310 Compare September 5, 2026 17:50
@codecov

codecov Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (b8bd5ac) to head (aefa310).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #232   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           60        63    +3     
  Lines         1106      1163   +57     
=========================================
+ Hits          1106      1163   +57     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cinar
cinar merged commit ca5b02f into main Sep 5, 2026
8 checks passed
@cinar
cinar deleted the p1-09-contains-family branch September 5, 2026 17:52
cinar added a commit that referenced this pull request Sep 5, 2026
Replaces #233, which GitHub auto-closed (rather than retargeted) when
its base branch (`p1-09-contains-family`) was deleted after #232 merged.
Same content, rebased onto current `main`.

## Problem

`min-len`/`max-len` exist but there was no single-tag way to require an
exact length — phone numbers, fixed-width codes, postal codes.

## Fix

Add `len`, mirroring `min_len.go` exactly:

- The generic `Len[T any]` signature is usable standalone with any
`Len()`-able type, and uses the same `v.Len()` (byte length, not rune
count) semantics already used by `min-len`/`max-len` — kept consistent
with its siblings rather than introducing a rune-counting discrepancy
between the three.
- Registered in `maker.go`.
- Mapped in `schema_maker.go` to matching Min/Max pairs
(`MinLength`=`MaxLength`, `MinItems`=`MaxItems`, or
`MinProperties`=`MaxProperties`, depending on kind), since an exact
length is just min=max.
- `NOT_LEN` message added to all 23 locale files plus en-US.
- Documented in the README's checker table.

## Testing

- `len_test.go`: standalone generic usage, string/slice struct-tag
valid/invalid, bad-param panic, non-Len()-able-type panic.
- `TestJSONSchemaLenExactLength` covering string/slice/map, plus a
bad-param panic test.
- Full suite passes, 100% coverage maintained.
- `go vet`, `gosec`, `revive` clean.

Fixes #207

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01FLdVmP5daHiknrTW4Geh2i

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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.

Add contains/starts-with/ends-with substring checkers

1 participant