fix(frontend): reject null payloads in dashboard type predicates#6443
fix(frontend): reject null payloads in dashboard type predicates#6443eugenegujing wants to merge 3 commits into
Conversation
Add an `isNonNullObject` guard to `common/util/predicate.ts` (with a new predicate.spec.ts, which also covers the previously untested `isDefined`), use it in the four object-payload guards, and switch all five guards to `!!value` so they always return strict booleans. `isDashboardProject`'s `!value.workflow` exclusion is deliberately unchanged. Spec updated: the four "(current behavior)" null-payload pins now assert false; the 5x5 cross-classification matrix and its 25 expected values are untouched, so no realistic entry changes classification. Fixes apache#6439
Automated Reviewer SuggestionsBased on the
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6443 +/- ##
=========================================
Coverage 74.65% 74.66%
Complexity 3438 3438
=========================================
Files 1160 1160
Lines 45793 45795 +2
Branches 5069 5070 +1
=========================================
+ Hits 34189 34191 +2
Misses 9953 9953
Partials 1651 1651
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
/request-review @aglinxinyuan |
There was a problem hiding this comment.
Pull request overview
This PR fixes a correctness gap in the frontend dashboard entry type guards by ensuring nested “payload” fields are rejected when they are null (avoiding the JavaScript typeof null === "object" trap) and by making the guards return strict booleans for null/undefined inputs. This prevents invalid dashboard entries from being misclassified and crashing DashboardEntry construction with unrelated TypeErrors.
Changes:
- Add a shared
isNonNullObjectpredicate utility and unit tests for it (and for the previously-untestedisDefined). - Update dashboard type predicates to use
isNonNullObjectfor nested object payload checks and!!valueto return strict booleans. - Update dashboard predicate unit tests to assert the corrected null-handling behavior while keeping the cross-classification matrix unchanged.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| frontend/src/app/dashboard/type/type-predicates.ts | Switch nested payload checks to isNonNullObject and ensure strict-boolean returns. |
| frontend/src/app/dashboard/type/type-predicates.spec.ts | Flip the “current behavior” null-payload pins to assert corrected false results; tighten null/undefined expectations to false. |
| frontend/src/app/common/util/predicate.ts | Introduce reusable isNonNullObject helper alongside isDefined. |
| frontend/src/app/common/util/predicate.spec.ts | Add focused unit tests for isNonNullObject and isDefined. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-null-guard # Conflicts: # frontend/src/app/common/util/predicate.spec.ts
What changes were proposed in this PR?
The five type guards in
dashboard/type/type-predicates.tschecked their nested payload withtypeof value.<field> === "object", which also accepts null becausetypeof null === "object"in JavaScript, so an entry like{workflow: null}passedisDashboardWorkflowand theDashboardEntryconstructor then crashed with an unrelatedTypeError: Cannot read properties of nullwhile dereferencing the payload, instead of reaching its intentional"Unexpected type in DashboardEntry."error path. The guards also returned the falsy input itself rather thanfalsefor null/undefined input, violating their declared boolean type-guard signatures.This PR adds an
isNonNullObjecttype guard (typeof x === "object" && x !== null) to the shared predicate utility (common/util/predicate.ts, next toisDefined) so the correct non-null object check is discoverable and reusable, uses it in the four object-payload guards, and switches all five guards to!!value && ...so they return strict booleans in every path.isDashboardProject's!value.workflowexclusion is deliberately unchanged: a nullworkflowfield means "no workflow data", so an object with a stringnamestill classifies as a project and no valid entry changes classification.Any related issues, documentation, discussions?
Fixes #6439. The buggy behavior was pinned by the five "(current behavior)" tests added in #6425 (issue #6400), which this PR flips to assert the corrected behavior.
How was this PR tested?
Added
predicate.spec.ts(8 tests) coveringisNonNullObjectand the previously untestedisDefined. Updatedtype-predicates.spec.ts: the four null-payload pins now asserttoBe(false), the null/undefined input cases are tightened fromtoBeFalsy()totoBe(false), and theisDashboardProjectnull-workflow case keeps assertingtruewith a comment marking it as an intentional decision; the 5x5 cross-classification matrix and all of its 25 expected values are untouched, confirming that classification of realistic entries is unaffected. Ran locally viayarn ng test --watch=false --include='**/common/util/predicate.spec.ts' --include='**/dashboard/type/type-predicates.spec.ts'(61/61 pass), plus the full frontend suite whose failure set is identical to the unmodified main baseline (pre-existing, environment-related failures only), andtsc --noEmitwith zero errors.Was this PR authored or co-authored using generative AI tooling?
Co-authored using Claude Code(Fable 5).