Skip to content

Extracted read-only Graph.js state functions into typed graphState module - #1825

Merged
david-yz-liu merged 2 commits into
masterfrom
graph-state-queries
Nov 2, 2026
Merged

david-yz-liu merged 2 commits into
masterfrom
graph-state-queries

Conversation

@david-yz-liu

@david-yz-liu david-yz-liu commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Proposed Changes

This continues breaking up Graph.js. It extracts the functions that only read graph state into a new typed module, js/components/graph/graphState.ts. Each is a pure function that takes the relevant state as an explicit GraphState parameter (a Pick of LoadedGraphData). Graph.js now calls them with this.state, which keeps the same timing as the old methods, since those also read this.state when called.

Moved out of Graph.js:

  • Selection queries: isSelected, isSelectedNode, isSelectedBool. These were removed from Graph as methods.
  • Prerequisite checks: arePrereqsSatisfiedBool, arePrereqsSatisfiedNode, arePrereqsSatisfiedHybrid. These were removed from Graph as methods.
  • Status computations pulled out of methods that also call setState:
    • computeNodeStatus, from updateNode
    • computeBoolStatus, from updateNodeBool
    • computeEdgeStatus, from updateEdgeStatus
    • totalSelectedCredits, from componentDidUpdate

Small simplifications made while moving the code (no behaviour change):

  • arePrereqsSatisfiedNode no longer handles nested arrays of parents. loadGraphData only produces flat string[] parent lists, so that branch could never run.
  • arePrereqsSatisfiedBool merged an if/else whose two branches were identical. It also returns false instead of undefined for a bool that isn't "and"/"or". Its only caller treats both values the same.

Added js/components/graph/__tests__/graphState.test.js, which covers each function on a small sample graph containing course nodes, hybrid nodes and bools.

Screenshots of your changes (if applicable)

Type of Change

(Write an X or a brief description next to the type or types that best describe your changes.)

Type Applies?
🚨 Breaking change (fix or feature that would cause existing functionality to change)
✨ New feature (non-breaking change that adds functionality)
🐛 Bug fix (non-breaking change that fixes an issue)
🎨 User interface change (change to user interface; provide screenshots)
♻️ Refactoring (internal change to codebase, without changing functionality) X
🚦 Test update (change that only adds or modifies tests)
📦 Dependency update (change that updates a dependency)
🔧 Internal (change that only affects developers or continuous integration)

Checklist

(Complete each of the following items for your pull request. Indicate that you have completed an item by changing the [ ] into a [x] in the raw text, or by clicking on the checkbox in the rendered description on GitHub.)

Before opening your pull request:

  • I have performed a self-review of my changes.
    • Check that all changed files included in this pull request are intentional changes.
    • Check that all changes are relevant to the purpose of this pull request, as described above.
  • I have added tests for my changes, if applicable.
    • This is required for all bug fixes and new features.
  • I have updated the project documentation, if applicable.
    • This is required for new features.
  • If this is my first contribution, I have added myself to the list of contributors.
  • I have updated the project Changelog (this is required for all changes).

After opening your pull request:

  • I have verified that the CI checks have passed.
  • I have reviewed the test coverage changes reported by Coveralls.
  • I have requested a review from a project maintainer.

Questions and Comments

  • Locally, all 181 js/components/graph tests pass, and graphState.ts has 100% line and branch coverage. tsc and eslint pass.
  • Known bug, not fixed here: the early-return branch of updateNode reads this.state.edgesStatus[edge] where every other branch reads edgesJSON. Because edgesStatus values are strings, currentEdge.id_, .source and .target are all undefined. As a result, that branch never recalculates the node's edges, and it writes a stray "undefined" entry into edgesStatus. Fixing it changes behaviour, so it will be a separate PR with its own test.
  • The obvious next step is consolidating the selection cascade (updateNode / focusPrereqs and related methods, which chain many setState calls) into a single pure update in graphState.ts that calls one setState.

🤖 Generated with Claude Code

david-yz-liu and others added 2 commits November 1, 2026 11:15
Moves isSelected, isSelectedNode, isSelectedBool, and the
arePrereqsSatisfied{Bool,Node,Hybrid} methods out of Graph.js into pure
functions in graphState.ts that take the relevant state slice explicitly,
and adds unit tests for them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves the pure status calculations out of updateNode, updateNodeBool,
updateEdgeStatus, and the FCE total in componentDidUpdate into
computeNodeStatus, computeBoolStatus, computeEdgeStatus, and
totalSelectedCredits in graphState.ts, with unit tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 41326257887

Coverage increased (+0.1%) to 60.788%

Details

  • Coverage increased (+0.1%) from the base build.
  • Patch coverage: 60 of 60 lines across 2 files are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 4294
Covered Lines: 2668
Line Coverage: 62.13%
Relevant Branches: 1008
Covered Branches: 555
Branch Coverage: 55.06%
Branches in Coverage %: Yes
Coverage Strength: 158.38 hits per line

💛 - Coveralls

@david-yz-liu
david-yz-liu merged commit f4579ec into master Nov 2, 2026
3 checks passed
@david-yz-liu
david-yz-liu deleted the graph-state-queries branch November 2, 2026 20:22
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.

2 participants