refactor(graph): group and test the properties that cannot move to a mixin - #1131
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe change initializes ChangesGraph state and serialization
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…mixin mixInto installs mixin members on the AbstractGraph prototype, so a property with a mutable default declared in a mixin would be shared by every graph instance: mutating it on one graph would mutate it for all of them, with no compile error and no failing test to signal it. AbstractGraph already has a dedicated group for the properties concerned, but the group was neither complete nor guarded. Move pageFormat and warningImage into it. Both have exactly that constraint, yet were declared in the generic "Variables managed here" group, so nothing at the declaration said why they must stay. Cover every property of the group with the same data-driven test: two graphs, distinct references, then mutate one and check the other is untouched. Each case also asserts that its own mutation is effective, so a case cannot pass by accident with a mutation that does nothing. Verified by temporarily sharing pageFormat between instances: only that case fails, the others still pass. The group header now points at these tests, so adding a property without its case becomes an obvious omission rather than a silent one. Document why sizeDidChange cannot be extracted while at it. It sits in EventsMixin but reads container-sizing members only, so it looks like an obvious candidate for a move, and the question would otherwise be re-opened by every contributor who spots the mismatch. AbstractGraph calls it from its constructor, from graphModelChanged and from refresh, none of which can depend on an optional plugin. Written as a plain comment rather than JSDoc on purpose, a reader of the public API has no use for a refactoring constraint. Declaration order drives the order of the child elements produced by the Codec export, so the expected XML of the all-graph-classes serialization test is updated and the changelog records the change. It is not breaking, decoding matches elements by their "as" attribute, but consumers comparing exported XML as text will see a diff.
b170d25 to
a3132d8
Compare
…eGraph BaseGraph.test.ts and Graph.test.ts each checked that the properties coming from the mixins are not shared between graph instances, with two diverging copies of the same suite. BaseGraph used hand-written tests that omitted pageFormat and warningImage and relied on deep inequality, while Graph used a data-driven table that also asserts the mutation took effect, so that a leak cannot pass unnoticed. The properties under test are declared on AbstractGraph, so the guarantee is identical for every concrete implementation. Keeping two copies meant a new property had to be added twice, and in practice it was added only to one of them. Extract the table and its assertions into describeNoGlobalStateForMixinProperties(), a suite factory parameterized by a graph factory, and call it from both files. selectionModel joins the table as its read/mutate/signature shape fits. The helper is a plain .ts file, so Jest does not collect it as a suite of its own.
|



First implementation step of the plan recorded in ADR 0003 (#1130). No behavior change for library users.
Problem
mixIntoinstalls mixin members on theAbstractGraphprototype. A property with a mutable default declared in a mixin is therefore shared by every graph instance: mutating it on one graph mutates it for all of them. There is no compile error, and until this PR, no failing test either.AbstractGraphalready has a dedicated group for the properties concerned,Variables that should be in the mixins but requiring per-instance initialization. That group was neither complete nor guarded.Changes
pageFormatandwarningImagejoin the group. Both have exactly that constraint, yet were declared in the genericVariables managed heregroup, so nothing at the declaration said why they must stay. The source diff is a pure relocation, 20 lines out and the same 20 lines in.Every property of the group is now covered by a test, in the existing
Expect no global state for properties coming from mixinsblock: two graphs, distinct references, then mutate one and check the other is untouched. Each case also asserts that its own mutation is effective, so a case cannot pass by accident with a mutation that does nothing.Verified that the tests can actually fail, by temporarily sharing
pageFormatbetween instances the way a mixin would: only that case failed, the other six passed.The group header now points at these tests, so adding a property there without its case becomes an obvious omission rather than a silent one.
sizeDidChangegets a comment explaining why it cannot be extracted. It sits inEventsMixinbut reads container-sizing members only, so it looks like an obvious candidate for a move, and the question would otherwise be re-opened by every contributor who spots the mismatch.AbstractGraphcalls it from its constructor, fromgraphModelChangedand fromrefresh, none of which can depend on an optional plugin. Written as a plain comment rather than JSDoc on purpose: a reader of the public API has no use for a refactoring constraint.One consequence worth reviewing
Declaration order drives the order of the child elements produced by the Codec export, so moving the two properties moved their elements in the exported XML. The expected XML of
all-graph-classes.test.tsis updated accordingly, and the changelog records it.This is not breaking: decoding matches elements by their
asattribute and is order-independent, existing documents decode identically, and previously exported documents stay valid. It is recorded only for consumers comparing exported XML as text, for instance in golden-file tests.The changelog entry sits under a new
Other Changesheading, since theUnreleasedsection is documented as holding breaking changes only. Happy to drop it if you would rather keep that section strictly for breaking changes.Validation
Run locally on Node 24 (
.nvmrc):build,test-check, the full suite (505 tests, 60 suites),lint,check:circular-dependencies. All passing.Summary by CodeRabbit
Bug Fixes
Serialization
pageFormatandwarningImageimmediately afteroptionsfor graphs.Documentation