Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code 7b8faaee7b fix: handle IS_NOT_NULL operand in evaluateUuidFilter for workflow filters
https://sonarly.com/issue/33687?type=bug

The `evaluateUuidFilter` function in the workflow filter step only handles `IS` and `IS_NOT` operands, throwing an unhandled error when a UUID-type filter uses the valid `IS_NOT_NULL` operand. This causes the entire workflow run to fail.

Fix: Added `IS_NOT_NULL`, `IS_NOT_EMPTY`, and `IS_EMPTY` operand handling to `evaluateUuidFilter` in `evaluate-filter-conditions.util.ts`.

**The problem:** `evaluateUuidFilter` only handled `IS` and `IS_NOT` operands. When a workflow Filter step used a UUID-typed field with the `IS_NOT_NULL` operand (a valid `ViewFilterOperand` enum member), the function hit the `default` branch and threw `Error: Operand IS_NOT_NULL not supported for uuid filter`, crashing the workflow run.

**The fix:** Added three new cases to the switch statement, following the exact same pattern used in `evaluateRelationFilter` (same file, same semantics):
- `IS_EMPTY`: returns `!isNonEmptyString(filter.leftOperand)` — true when the UUID is empty/missing
- `IS_NOT_NULL` (falls through to `IS_NOT_EMPTY`): returns `isNonEmptyString(filter.leftOperand)` — true when the UUID has a value
- `IS_NOT_EMPTY`: returns `isNonEmptyString(filter.leftOperand)` — same as IS_NOT_NULL

**Tests added:** 6 new test cases in the existing `UUID filter operands` describe block:
- IS_NOT_NULL with non-empty UUID → true
- IS_NOT_NULL with empty string → false
- IS_NOT_EMPTY with non-empty UUID → true
- IS_NOT_EMPTY with empty string → false
- IS_EMPTY with empty string → true
- IS_EMPTY with non-empty UUID → false
2026-05-03 08:05:17 +00:00
2 changed files with 77 additions and 0 deletions
@@ -298,6 +298,78 @@ describe('evaluateFilterConditions', () => {
expect(evaluateFilterConditions({ filters: [filter2] })).toBe(false);
});
it('should return true when left operand is non-empty (IS_NOT_NULL UUID)', () => {
const filter = createFilter(
ViewFilterOperand.IS_NOT_NULL,
uuid1,
'',
'UUID',
);
const result = evaluateFilterConditions({ filters: [filter] });
expect(result).toBe(true);
});
it('should return false when left operand is empty (IS_NOT_NULL UUID)', () => {
const filter = createFilter(
ViewFilterOperand.IS_NOT_NULL,
'',
'',
'UUID',
);
const result = evaluateFilterConditions({ filters: [filter] });
expect(result).toBe(false);
});
it('should return true when left operand is non-empty (IS_NOT_EMPTY UUID)', () => {
const filter = createFilter(
ViewFilterOperand.IS_NOT_EMPTY,
uuid1,
'',
'UUID',
);
const result = evaluateFilterConditions({ filters: [filter] });
expect(result).toBe(true);
});
it('should return false when left operand is empty (IS_NOT_EMPTY UUID)', () => {
const filter = createFilter(
ViewFilterOperand.IS_NOT_EMPTY,
'',
'',
'UUID',
);
const result = evaluateFilterConditions({ filters: [filter] });
expect(result).toBe(false);
});
it('should return true when left operand is empty (IS_EMPTY UUID)', () => {
const filter = createFilter(
ViewFilterOperand.IS_EMPTY,
'',
'',
'UUID',
);
const result = evaluateFilterConditions({ filters: [filter] });
expect(result).toBe(true);
});
it('should return false when left operand is non-empty (IS_EMPTY UUID)', () => {
const filter = createFilter(
ViewFilterOperand.IS_EMPTY,
uuid1,
'',
'UUID',
);
const result = evaluateFilterConditions({ filters: [filter] });
expect(result).toBe(false);
});
it('should throw error for unsupported UUID filter operand', () => {
const filter = createFilter(
ViewFilterOperand.CONTAINS,
@@ -268,6 +268,11 @@ function evaluateUuidFilter(filter: ResolvedFilter): boolean {
return filter.leftOperand === filter.rightOperand;
case ViewFilterOperand.IS_NOT:
return filter.leftOperand !== filter.rightOperand;
case ViewFilterOperand.IS_EMPTY:
return !isNonEmptyString(filter.leftOperand);
case ViewFilterOperand.IS_NOT_NULL:
case ViewFilterOperand.IS_NOT_EMPTY:
return isNonEmptyString(filter.leftOperand);
default:
throw new Error(
`Operand ${filter.operand} not supported for uuid filter`,