Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/unreleased/Bugfix-20260713-180016.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: Bugfix
body: FilterPredicate.Validate now rejects any CaseSensitive value (true or false) on
predicate types that do not support case sensitivity (e.g. exists, matches), since
the API ignores the value and returns null for it.
time: 2026-07-13T18:00:16.000000Z
5 changes: 4 additions & 1 deletion filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ func (filterPredicate *FilterPredicate) validateCaseSensitivity() error {
PredicateTypeEnumDoesNotMatch,
PredicateTypeEnumSatisfiesJqExpression,
}
if slices.Contains(knownNotCaseSensitiveTypes, filterPredicate.Type) && *filterPredicate.CaseSensitive {
// The API ignores CaseSensitive for these predicate types and returns null for it
// in responses, so any value set here (true or false) would silently disagree with
// the API response for clients that round-trip it. Reject any non-nil value.
if slices.Contains(knownNotCaseSensitiveTypes, filterPredicate.Type) {
return fmt.Errorf("FilterPredicate type '%s' cannot have CaseSensitive value set", filterPredicate.Type)
}
return nil
Expand Down
63 changes: 63 additions & 0 deletions filters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,66 @@ func TestDeleteFilter(t *testing.T) {
// Assert
autopilot.Equals(t, nil, err)
}

func TestFilterPredicateValidateCaseSensitivity(t *testing.T) {
boolPtr := func(b bool) *bool { return &b }

testCases := map[string]struct {
predicate ol.FilterPredicate
wantErr bool
}{
"nil on not-case-sensitive type is valid": {
predicate: ol.FilterPredicate{
Key: ol.PredicateKeyEnumRepositoryIDs,
Type: ol.PredicateTypeEnumExists,
CaseSensitive: nil,
},
wantErr: false,
},
"true on not-case-sensitive type is an error": {
predicate: ol.FilterPredicate{
Key: ol.PredicateKeyEnumRepositoryIDs,
Type: ol.PredicateTypeEnumExists,
CaseSensitive: boolPtr(true),
},
wantErr: true,
},
"false on not-case-sensitive type is an error": {
predicate: ol.FilterPredicate{
Key: ol.PredicateKeyEnumRepositoryIDs,
Type: ol.PredicateTypeEnumExists,
CaseSensitive: boolPtr(false),
},
wantErr: true,
},
"true on case-sensitive type is valid": {
predicate: ol.FilterPredicate{
Key: ol.PredicateKeyEnumLanguage,
Type: ol.PredicateTypeEnumEquals,
Value: "Go",
CaseSensitive: boolPtr(true),
},
wantErr: false,
},
"false on case-sensitive type is valid": {
predicate: ol.FilterPredicate{
Key: ol.PredicateKeyEnumLanguage,
Type: ol.PredicateTypeEnumEquals,
Value: "Go",
CaseSensitive: boolPtr(false),
},
wantErr: false,
},
}

for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
err := tc.predicate.Validate()
if tc.wantErr {
autopilot.Assert(t, err != nil, "expected an error but got nil")
} else {
autopilot.Equals(t, nil, err)
}
})
}
}
Loading