Skip to content

Deep review of ngx-reactome-diagram: 15 confirmed bugs #14

Open

Description

@adamjohnwright

A full-depth code review of projects/ngx-reactome-diagram/src (2026-10-09). Each finding below was checked by an independent verifier, and most were reproduced against the stored fixtures. The website's own diagram (WebsiteAngular projects/pathway-browser) already avoids #1 and #13. Not fixed yet, because dev_curator is changing the same files.

  • 1. getElements builds unquoted data selectors ([acc=${token}], [reactomeId=${token}]). A non-numeric token is an invalid selector, which cytoscape treats as matching everything: ?flag=PKM flags every element, and ?select=P04637 selects nearly all of them and fires ~215 navigations.
  • 2. Clearing a flag leaves the flagged lines with an inline black underlay, and re-hides the sub-pathway bands.
  • 3. loadDiagram has no cancellation or error handling: a slower earlier response replaces the current diagram, and a 404 is swallowed.
  • 4. Graph nodes with one child map to the child, so homomultimers carry their monomer's stId (clicking TP53 Tetramer selects R-HSA-69488).
  • 5. URL sync: a parameter removed from the address never resets state, and every write replaces the host's whole query string and fragment.
  • 6. Clicking an element with no graph data (the faded normal-pathway elements of a disease diagram) sets select to '', which unselects everything.
  • 7. stateToDiagram() in displayNetwork runs outside avoidSideEffect: a selection from the URL is never zoomed to, and its events reach the host as clicks.
  • 8. distinctUntilChanged comes before filter(!_ignore), so legend clicks get dropped as duplicates.
  • 9. In compare mode a state selection fits to the compare pane, not the view.
  • 10. Deselecting never clears select, so re-selecting is dropped and a cleared selection comes back.
  • 11. Cytoscape cores, the $dark subscription and cyCompare are never torn down on destroy (leak, plus events from a previous diagram).
  • 12. While flagged, trivial molecules use inline opacity instead of .trivial.always-visible, so a restyle hides them.
  • 13. Flagging a reaction type from the legend flags the reaction nodes but not their lines.
  • 14. (Plausible) In zoneless hosts, nothing marks the component dirty after comparing = true, so the compare overlay never shows.
  • 15. DarkService calls JSON.parse on a generic localStorage key without a guard (one bad value breaks creation) and toggles body.dark on the host page.

Smaller:

  • cdkDragHandle is not imported, so the whole legend drags.
  • legend2state dereferences cy before any diagram has loaded.
  • DIAGRAM_CONFIG_TOKEN is required but undocumented.
  • The getEdgeId counter never advances.
  • Compartment radius uses prop.x where prop.y is meant.
  • replacement stores a raw Edge.
  • avoidOverlap's gravity pulls sub-pathway labels far from their sub-pathways.

Cleanup:

  • Cores are created inside NgZone, so change detection runs every frame.
  • vectorious geometry takes ~88% of the transform.
  • <video> tags have no preload="none", and request undefined.mov when there's no accession.
  • Leftover PSICQUIC code forces @angular/forms and @angular/material into the peer dependencies.
  • Dead code: randomNetwork, roundness.ts, assets/data/*.txt.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions