Skip to content

docs(changeset): Removing Interactive Graph Builder and refactoring tests/storybook to use more standardized generator patterns.#3415

Merged
SonicScrewdriver merged 18 commits intomainfrom
maximum-overline
Apr 29, 2026
Merged

docs(changeset): Removing Interactive Graph Builder and refactoring tests/storybook to use more standardized generator patterns.#3415
SonicScrewdriver merged 18 commits intomainfrom
maximum-overline

Conversation

@SonicScrewdriver
Copy link
Copy Markdown
Contributor

@SonicScrewdriver SonicScrewdriver commented Mar 25, 2026

Summary:

Remove the old Interactive Graph Builder and refactor our tests to use the same generator patterns as the rest of Perseus.

Issue: LEMS-4008

Test plan:

  • Tests Pass

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review.

Tip: disable this comment in your organization's Code Review settings.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 25, 2026

🗄️ Schema Change: No Changes ✅

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 25, 2026

Size Change: +211 B (+0.04%)

Total Size: 502 kB

📦 View Changed
Filename Size Change
packages/perseus-core/dist/es/index.js 25.4 kB +211 B (+0.84%)
ℹ️ View Unchanged
Filename Size
packages/kas/dist/es/index.js 20.6 kB
packages/keypad-context/dist/es/index.js 1 kB
packages/kmath/dist/es/index.js 6.36 kB
packages/math-input/dist/es/index.js 98.5 kB
packages/math-input/dist/es/strings.js 1.61 kB
packages/perseus-core/dist/es/index.item-splitting.js 12 kB
packages/perseus-editor/dist/es/index.js 103 kB
packages/perseus-linter/dist/es/index.js 9.42 kB
packages/perseus-score/dist/es/index.js 9.78 kB
packages/perseus-utils/dist/es/index.js 403 B
packages/perseus/dist/es/index.js 198 kB
packages/perseus/dist/es/strings.js 8.46 kB
packages/pure-markdown/dist/es/index.js 1.39 kB
packages/simple-markdown/dist/es/index.js 6.71 kB

compressed-size-action

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 25, 2026

🛠️ Item Splitting: No Changes ✅

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 25, 2026

npm Snapshot: Published

Good news!! We've packaged up the latest commit from this PR (7eb6d2a) and published it to npm. You
can install it using the tag PR3415.

Example:

pnpm add @khanacademy/perseus@PR3415

If you are working in Khan Academy's frontend, you can run the below command.

./dev/tools/bump_perseus_version.ts -t PR3415

If you are working in Khan Academy's webapp, you can run the below command.

./dev/tools/bump_perseus_version.js -t PR3415

});
});

describe("generateIGExponentialGraph", () => {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decided to round out the tests for the new graphs while I was in here.


export function generateIGAngleGraph(
options?: Partial<PerseusGraphTypeAngle>,
options?: Partial<Omit<PerseusGraphTypeAngle, "type">>,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just some additional type safety that brings these generators inline with the implementation of the rest of the IG generators.

Comment thread .eslintrc.js
"*.cypress.ts",
"*.test.ts",
"*.test.tsx",
"*.testdata.ts",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It made sense to me to add a global override for our test data as it seems reasonable for these files to be exempt, but I'm also happy to remove this and re-add the file-specific override for interactive-graph.testdata.ts.

Comment thread packages/perseus-core/src/utils/generators/interactive-graph-widget-generator.ts Outdated
Comment on lines +243 to +265

export function generateInteractiveGraphQuestion(
options?: Partial<PerseusInteractiveGraphWidgetOptions> & {
content?: string;
isStatic?: boolean;
},
): PerseusRenderer {
const {content, isStatic, ...widgetOptions} = options ?? {};

// The `graph` and `correct` fields share all fields except for
// the answers (coords, center, etc.) When only `correct` is provided,
// derive `graph` from it by stripping the answer-specific fields.
// This allows us to keep our test data more succinct.
if (widgetOptions.correct && !widgetOptions.graph) {
const {
coords: _,
coord: __,
center: ___,
radius: ____,
asymptote: _____,
match: ______,
...graphConfig
} = widgetOptions.correct as Record<string, unknown>;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 The developer architecture notes in logarithm.md (line 322) and tangent.md (line 187) still reference interactive-graph-question-builder.ts, which this PR deletes. Developers following these notes to implement a new graph type will hit a broken file reference; update both notes to point to the replacement module interactive-graph-widget-generator.ts.

Extended reasoning...

What the bug is and how it manifests

This PR deletes packages/perseus/src/widgets/interactive-graphs/interactive-graph-question-builder.ts and replaces it with packages/perseus-core/src/utils/generators/interactive-graph-widget-generator.ts. However, two developer architecture notes — logarithm.md and tangent.md — were not updated alongside this deletion. Both notes contain explicit file-path references that are now dead.

  • packages/perseus/src/widgets/interactive-graphs/__docs__/notes/logarithm.md line 322 references ...interactive-graph-question-builder.ts — withLogarithm(), LogarithmGraphConfig
  • packages/perseus/src/widgets/interactive-graphs/__docs__/notes/tangent.md line 187 references ...interactive-graph-question-builder.ts — Builder

The specific code path that triggers it

These notes are static Markdown documentation files intended to guide developers implementing new graph types. They list the files and functions a developer needs to touch, with interactive-graph-question-builder.ts called out as containing the builder class. Since that file no longer exists in the repository after this PR, any developer following the guide will look for a file that is simply gone.

Why existing code doesn't prevent it

The deletion of the builder was a source-code change; there is no automated tooling that cross-checks prose documentation for file-path accuracy. The notes were written to describe the old architecture and were not updated in this refactor.

What the impact would be

A developer tasked with adding a new interactive graph type (e.g., logarithm or tangent) would consult these notes, encounter the dead reference, and either waste time searching for the file or be left confused about where the builder logic now lives. The correct file is packages/perseus-core/src/utils/generators/interactive-graph-widget-generator.ts, which is where all the new generator functions (e.g., generateIGExponentialGraph, generateIGAbsoluteValueGraph) live.

How to fix it

In both logarithm.md:322 and tangent.md:187, replace the reference to interactive-graph-question-builder.ts with packages/perseus-core/src/utils/generators/interactive-graph-widget-generator.ts and update the function/class names cited to match the new generator API (e.g., the generator functions instead of withLogarithm()/LogarithmGraphConfig/Builder).

Step-by-step proof

  1. The PR diff shows interactive-graph-question-builder.ts deleted (entire file removed with --- a/.../interactive-graph-question-builder.ts diff header).
  2. logarithm.md line 322 contains the literal string interactive-graph-question-builder.ts — withLogarithm(), LogarithmGraphConfig — a path that no longer resolves.
  3. tangent.md line 187 contains the literal string interactive-graph-question-builder.ts — Builder — also a dead path.
  4. The new replacement module interactive-graph-widget-generator.ts is added by this PR and exports graph generators such as generateIGTangentGraph, generateIGExponentialGraph, etc.
  5. Neither doc file appears in the PR diff, confirming neither was updated.

@ivyolamit
Copy link
Copy Markdown
Contributor

@SonicScrewdriver just reading the PR description, what do you think of adding an info in our notes as a tip? To ensure that this pattern will be followed moving forward.

🔗 https://github.com/Khan/perseus/blob/main/packages/perseus/src/widgets/interactive-graphs/__docs__/notes/new-graph-type.md#tips

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous feedback addressed — critical fixture bugs fixed, intentional display-graph-type changes acknowledged. LGTM.

Extended reasoning...

Overview

This PR removes the class (and its duplicate in the editor package) and replaces all call sites with the functional / generators already exported from @khanacademy/perseus-core. Changes touch test data files, Storybook stories, and test files across three packages; no production widget logic is modified.

Security risks

None. All changes are confined to test utilities, Storybook stories, and test data. No auth, crypto, or user-facing code paths are touched.

Level of scrutiny

This is a large but mechanical refactoring of test/story infrastructure. The main risk is behavioral divergence during migration (old builder had implicit defaults like SegmentGraphConfig as the fallback graph type), which is exactly what the prior review rounds surfaced and which the author has now addressed. The PR is appropriate for bot approval given: (1) the logic being changed is test-only, (2) all identified regressions were fixed, and (3) no new bugs were found.

Other factors

Prior inline comments flagged circle fixture missing center/radius defaults, several segmentWith* fixtures defaulting to a linear graph, segmentWithLockedFunction missing a correct field, and the match field leaking into graph for polygon questions. The current file state confirms all of these were remediated. The author explicitly resolved the display-story graph-type comments as intentional. One minor residual: logarithm.md and tangent.md still reference the deleted builder file path, but that is a documentation-only nit that does not affect runtime behaviour.

Comment thread .github/workflows/node-ci.yml Outdated
Comment on lines +99 to +100
# cdn.jsdelivr.net: speech-engine-rules files are hosted here
extra-domains: registry.npmjs.org cdn.jsdelivr.net
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you rebase on the latest main, cdn.jsdelivr.net is no longer needed!

Suggested change
# cdn.jsdelivr.net: speech-engine-rules files are hosted here
extra-domains: registry.npmjs.org cdn.jsdelivr.net
extra-domains: registry.npmjs.org

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh thank you! Yeah I think my branch got stale there, and John added a commit to help unstick me earlier on :)

Copy link
Copy Markdown
Contributor

@ivyolamit ivyolamit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SonicScrewdriver sorry took me a while to get to this, changes LGTM. It's also way better than the previous way. Thanks for taking time to improve this!

- **TypeScript exhaustiveness:** Both `initializeGraphState` and `renderGraphElements` use `UnreachableCaseError` / `throw` on the default branch. TypeScript will report a compile error if you add a type to the union without handling it in those switches — use this as your checklist.
- **Accessibility:** Each graph component must return an `interactiveElementsDescription` node. See `graphs/screenreader-text.ts` for helper utilities that format numbers and coordinates for screen readers.
- **Snap & bound:** Always use `boundAndSnapToGrid()` (or `boundToEdgeAndSnapToGrid()`) when processing user movement in the reducer to keep points on the grid and within bounds.
- **Test data generator:** Add a `generateIGXxxGraph()` function in `packages/perseus-core/src/utils/generators/interactive-graph-widget-generator.ts` following the existing pattern, and export it from `packages/perseus-core/src/index.ts`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is something standard we want to have moving forward we can also add the info for Claude Context in https://github.com/Khan/perseus/blob/main/CLAUDE.md?plain=1#L111

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

.withShowAxisArrows({
question={generateInteractiveGraphQuestion({
correct: generateIGNoneGraph(),
range: [
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is way better approach than before, thanks for taking time to go through and improving these.

@SonicScrewdriver SonicScrewdriver merged commit e21c523 into main Apr 29, 2026
12 checks passed
@SonicScrewdriver SonicScrewdriver deleted the maximum-overline branch April 29, 2026 17:12
jeremywiebe pushed a commit that referenced this pull request May 4, 2026
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.


# Releases
## @khanacademy/perseus-core@26.0.0

### Major Changes

-   [#3517](#3517) [`957970dfdb`](957970d) Thanks [@benchristel](https://github.com/benchristel)! - Breaking change: The deprecated `violatingWidgets` function has been removed. Callers should use `isItemAccessible` instead. `isItemAccessible` now checks for inaccessible widgets in hints as well as question content.

### Patch Changes

-   [#3415](#3415) [`e21c523f5d`](e21c523) Thanks [@SonicScrewdriver](https://github.com/SonicScrewdriver)! - Removing Interactive Graph Builder and refactoring tests/storybook to use more standardized generator patterns.

## @khanacademy/perseus-editor@31.0.0

### Major Changes

-   [#3568](#3568) [`896e869ef5`](896e869) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Remove unused `paths` field from `LinterContextProps` and the corresponding `contentPaths` prop from `EditorPage`, `ArticleEditor`, and `HintEditor`. The field was never read by any linter rule or renderer.

### Minor Changes

-   [#3532](#3532) [`3263332fe2`](3263332) Thanks [@benchristel](https://github.com/benchristel)! - The issue panels in the article editor now show only issues for their associated article section. Previously, each panel showed the full set of issues for the entire article.

### Patch Changes

-   [#3543](#3543) [`51ebddf119`](51ebddf) Thanks [@SonicScrewdriver](https://github.com/SonicScrewdriver)! - Refactoring Start Coords for efficiency


-   [#3415](#3415) [`e21c523f5d`](e21c523) Thanks [@SonicScrewdriver](https://github.com/SonicScrewdriver)! - Removing Interactive Graph Builder and refactoring tests/storybook to use more standardized generator patterns.


-   [#3538](#3538) [`8b95cdf6e3`](8b95cdf) Thanks [@ivyolamit](https://github.com/ivyolamit)! - Add Storybook MCP addon for AI-assisted UI development

-   Updated dependencies \[[`494f287541`](494f287), [`743ad9d5f4`](743ad9d), [`0bf97ee3b6`](0bf97ee), [`957970dfdb`](957970d), [`e21c523f5d`](e21c523), [`e5ddaef207`](e5ddaef), [`ce83363534`](ce83363), [`dee6ce680c`](dee6ce6), [`896e869ef5`](896e869), [`cf5147d61c`](cf5147d), [`afc4f33090`](afc4f33), [`8b95cdf6e3`](8b95cdf), [`1dbd5742dc`](1dbd574)]:
    -   @khanacademy/perseus@77.3.2
    -   @khanacademy/perseus-core@26.0.0
    -   @khanacademy/perseus-linter@5.0.0
    -   @khanacademy/kmath@2.4.3
    -   @khanacademy/math-input@26.4.17
    -   @khanacademy/keypad-context@3.2.45
    -   @khanacademy/perseus-score@8.7.1

## @khanacademy/perseus-linter@5.0.0

### Major Changes

-   [#3568](#3568) [`896e869ef5`](896e869) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Remove unused `paths` field from `LinterContextProps` and the corresponding `contentPaths` prop from `EditorPage`, `ArticleEditor`, and `HintEditor`. The field was never read by any linter rule or renderer.

### Patch Changes

-   Updated dependencies \[[`957970dfdb`](957970d), [`e21c523f5d`](e21c523), [`cf5147d61c`](cf5147d)]:
    -   @khanacademy/perseus-core@26.0.0
    -   @khanacademy/kmath@2.4.3

## @khanacademy/keypad-context@3.2.45

### Patch Changes

-   Updated dependencies \[[`957970dfdb`](957970d), [`e21c523f5d`](e21c523)]:
    -   @khanacademy/perseus-core@26.0.0

## @khanacademy/kmath@2.4.3

### Patch Changes

-   [#3534](#3534) [`cf5147d61c`](cf5147d) Thanks [@marnikostman](https://github.com/marnikostman)! - Remove `underscore` and `jquery` as peer and dev dependencies. All usages have been replaced with native JavaScript equivalents.

-   Updated dependencies \[[`957970dfdb`](957970d), [`e21c523f5d`](e21c523)]:
    -   @khanacademy/perseus-core@26.0.0

## @khanacademy/math-input@26.4.17

### Patch Changes

-   [#3572](#3572) [`afc4f33090`](afc4f33) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Bumped deps

-   Updated dependencies \[[`957970dfdb`](957970d), [`e21c523f5d`](e21c523)]:
    -   @khanacademy/perseus-core@26.0.0
    -   @khanacademy/keypad-context@3.2.45

## @khanacademy/perseus@77.3.2

### Patch Changes

-   [#3293](#3293) [`494f287541`](494f287) Thanks [@benchristel](https://github.com/benchristel)! - Internal: remove unused default value for polygon graph point coordinates


-   [#3539](#3539) [`743ad9d5f4`](743ad9d) Thanks [@mark-fitzgerald](https://github.com/mark-fitzgerald)! - [Radio] Adjust styling to resolve an axe-core incomplete test result


-   [#3506](#3506) [`0bf97ee3b6`](0bf97ee) Thanks [@nishasy](https://github.com/nishasy)! - [Image] | (DX) | Add delay to flakey Graphie image regression test


-   [#3415](#3415) [`e21c523f5d`](e21c523) Thanks [@SonicScrewdriver](https://github.com/SonicScrewdriver)! - Removing Interactive Graph Builder and refactoring tests/storybook to use more standardized generator patterns.


-   [#3521](#3521) [`e5ddaef207`](e5ddaef) Thanks [@SonicScrewdriver](https://github.com/SonicScrewdriver)! - Allow the asymptote to be placed between points. Also allow for points to be on asymptote line so long as they don't overlap with the drag handle.


-   [#3567](#3567) [`ce83363534`](ce83363) Thanks [@ivyolamit](https://github.com/ivyolamit)! - Fix interactive graph x-axis label overlapping with content below when y-range starts at 0 or higher


-   [#3435](#3435) [`dee6ce680c`](dee6ce6) Thanks [@Myranae](https://github.com/Myranae)! - Convert hardcoded color values to semantic tokens for label image


-   [#3538](#3538) [`8b95cdf6e3`](8b95cdf) Thanks [@ivyolamit](https://github.com/ivyolamit)! - Add Storybook MCP addon for AI-assisted UI development


-   [#3524](#3524) [`1dbd5742dc`](1dbd574) Thanks [@SonicScrewdriver](https://github.com/SonicScrewdriver)! - Ensure that Ray and Linear points cannot overlap

-   Updated dependencies \[[`957970dfdb`](957970d), [`e21c523f5d`](e21c523), [`896e869ef5`](896e869), [`cf5147d61c`](cf5147d), [`afc4f33090`](afc4f33)]:
    -   @khanacademy/perseus-core@26.0.0
    -   @khanacademy/perseus-linter@5.0.0
    -   @khanacademy/kmath@2.4.3
    -   @khanacademy/math-input@26.4.17
    -   @khanacademy/keypad-context@3.2.45
    -   @khanacademy/perseus-score@8.7.1

## @khanacademy/perseus-score@8.7.1

### Patch Changes

-   Updated dependencies \[[`957970dfdb`](957970d), [`e21c523f5d`](e21c523), [`cf5147d61c`](cf5147d)]:
    -   @khanacademy/perseus-core@26.0.0
    -   @khanacademy/kmath@2.4.3


Issue: LEMS-4090

Author: khan-actions-bot

Reviewers: claude[bot], jeremywiebe

Required Reviewers:

Approved By: jeremywiebe

Checks:

Pull Request URL: #3533
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants