Restore SnappingOptions runtime setters (4.5.x regression) - #530
Conversation
The 4.5.x release accidentally truncated SnappingOptions.gb.cs right after the property getters (commit c3ab364), dropping the entire Property Setters and collection-helper regions. This removed SetEnabled, SetGridEnabled, SetDistance, SetFeatureEnabled, SetSelfEnabled, SetAttributeRulesEnabled, and SetFeatureSources, breaking runtime snapping/grid toggling for consumers (reported against 4.5.1). Restores the complete generated file from f02afef (the commit immediately before the truncation), which re-adds exactly the 7 setters plus the Add/Remove FeatureSources collection helpers and nothing else. Adds SnappingOptionsApiTests as a public-API contract guard so a future code-generation split cannot silently drop these members again. Versioning/release left to the maintainer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Customer reported (against 4.5.1) that GeometryEngine.Union returned a geometry with a null Extent, breaking map.GoTo(union.Extent). The union/extent code path is unchanged from the working 4.4.4 line, so this is not reproducible from source — these tests lock in the behavior so any future change that drops the extent is caught: - GeometryExtentSerializationTests: unit-level guard deserializing the exact JSON the JS union() produces and asserting Extent (and a full round-trip) survive. - GeometryEngineTests.TestUnion: extends the browser test to assert the unioned geometry has the expected Extent bounds and that GetExtent() returns it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
There was a problem hiding this comment.
Pull request overview
Restores the missing runtime setter/collection-helper APIs on SnappingOptions (regressed in 4.5.x due to generated file truncation) and adds regression tests guarding both the snapping API surface and a reported GeometryEngine.Union extent/serialization behavior.
Changes:
- Re-add
SnappingOptionsruntime setters andFeatureSourcesadd/remove helpers inSnappingOptions.gb.cs. - Add unit-level public API contract tests to prevent future silent removal of
SnappingOptionsmembers. - Add regression tests asserting
GeometryEngine.Unionresults preserve/populateExtentthrough serialization and in browser-based union execution.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
src/dymaptic.GeoBlazor.Core/Components/SnappingOptions.gb.cs |
Restores the missing runtime setters and FeatureSources collection helper methods. |
test/dymaptic.GeoBlazor.Core.Test.Unit/SnappingOptionsApiTests.cs |
Adds API-surface regression tests for SnappingOptions runtime configuration APIs. |
test/dymaptic.GeoBlazor.Core.Test.Unit/GeometryExtentSerializationTests.cs |
Adds serialization regression coverage ensuring Extent survives deserialization/round-trip. |
test/dymaptic.GeoBlazor.Core.Test.Blazor.Shared/Components/GeometryEngineTests.cs |
Adds browser test assertions that union results include a populated Extent and GetExtent() works. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (value is not null) | ||
| { | ||
| foreach (FeatureSnappingLayerSource item in value) | ||
| { | ||
| item.UpdateGeoBlazorReferences(CoreJsModule!, ProJsModule, View, this, Layer); | ||
| } | ||
| } |
| [TestMethod] | ||
| [DataRow("SetEnabled")] | ||
| [DataRow("SetGridEnabled")] | ||
| [DataRow("SetFeatureEnabled")] | ||
| [DataRow("SetSelfEnabled")] | ||
| public void HasRuntimeNullableBoolSetter(string methodName) | ||
| { | ||
| MethodInfo? method = SnappingOptionsType.GetMethod(methodName, | ||
| BindingFlags.Public | BindingFlags.Instance, [typeof(bool?)]); | ||
|
|
||
| Assert.IsNotNull(method, | ||
| $"SnappingOptions.{methodName}(bool?) must exist for runtime snapping toggling (regression from 4.5.x)."); | ||
| Assert.AreEqual(typeof(Task), method.ReturnType, | ||
| $"SnappingOptions.{methodName}(bool?) should return Task."); | ||
| } |
| [TestMethod] | ||
| [DataRow("Enabled")] | ||
| [DataRow("GridEnabled")] | ||
| [DataRow("FeatureEnabled")] | ||
| [DataRow("SelfEnabled")] | ||
| public void HasNullableBoolParameter(string propertyName) | ||
| { | ||
| PropertyInfo? property = SnappingOptionsType.GetProperty(propertyName, | ||
| BindingFlags.Public | BindingFlags.Instance); | ||
|
|
||
| Assert.IsNotNull(property, | ||
| $"SnappingOptions.{propertyName} property must exist (regression from 4.5.x)."); | ||
| Assert.AreEqual(typeof(bool?), property.PropertyType, | ||
| $"SnappingOptions.{propertyName} should be a bool? property."); | ||
| Assert.IsTrue(property.CanRead && property.CanWrite, | ||
| $"SnappingOptions.{propertyName} should be readable and writable."); | ||
| } |
| [TestMethod] | ||
| public void SetEnabled_UpdatesLocalProperty_BeforeRender() | ||
| { | ||
| // Without a JS runtime the setter should still update the local value (used for binding / | ||
| // initial render). The customer reported that even binding Enabled "didn't take effect". | ||
| SnappingOptions options = new(); | ||
|
|
||
| // Should not throw when there is no JS component yet; should set the local property. | ||
| options.SetEnabled(true).GetAwaiter().GetResult(); | ||
| Assert.IsTrue(options.Enabled.GetValueOrDefault(), "SetEnabled should update the local Enabled value."); | ||
|
|
||
| options.SetGridEnabled(true).GetAwaiter().GetResult(); | ||
| Assert.IsTrue(options.GridEnabled.GetValueOrDefault(), "SetGridEnabled should update the local GridEnabled value."); | ||
| } |
|
@magmoe did you or Claude do a search for any similarly truncated files? It's possible I manually truncated this file to fix a merge conflict, but I want to make sure it's not a larger issue. |
Addresses Copilot review: the contract test only guarded the 4 bool? setters and 4 bool? properties. Since the goal is to catch any future truncation of the generated runtime API, cover everything the 4.5.x cut removed: - all 7 setters (SetEnabled/GridEnabled/FeatureEnabled/SelfEnabled/AttributeRulesEnabled, plus SetDistance(double?) and SetFeatureSources(IReadOnlyList<...>)) - all 7 parameters (the 5 bool?, Distance, FeatureSources) - the AddToFeatureSources/RemoveFromFeatureSources collection helpers Also makes the behavioral test async/await instead of blocking on GetResult(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Yes, it's isolated to the one file. Claude checked to make sure |
buildDotNetGeometry now computes a missing extent from the geometry's coordinates, so results from the operator API (e.g. unionOperator) carry an Extent instead of null. Geometry.GetExtent() also falls back to a client-side CalculateExtent() (overridden by Polygon/Polyline) when neither the cached value nor the JS component supplies one. Adds extent assertions to TestUnionWithParamsArray and a GeometryExtentTests unit test for the calculation fallback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Added the source fix behind the Union/Extent regression guards on this branch (commit c5f7b16) — these were previously assertion-only, so Root cause: results from the geometry operator API (e.g. Fix (centralized, so every operator benefits — not just Union):
Tests:
Verification: 21/21 unit tests pass on the branch; C#/TS compile clean (ESLint passed). I could not run the browser automation suite ( Your 🤖 Generated with Claude Code |
TimPurdum
left a comment
There was a problem hiding this comment.
Copilot: I found one edge case that should be addressed before merging.
In src/dymaptic.GeoBlazor.Core/Components/Geometries/Geometry.cs around CalculateExtentFromPaths, and the matching fallback in src/dymaptic.GeoBlazor.Core/Scripts/geometry.ts, the newly calculated extent only carries xmin/ymin/xmax/ymax. For paths/rings/points with Z or M coordinates, the fallback drops zmin/zmax and mmin/mmax, even though GeoBlazor's Extent model and ArcGIS Extent both support those values. That makes the fallback less equivalent to geometry.extent for Z/M-enabled geometry results, and can return an incomplete extent for 3D/M geometries when the ArcGIS cached extent is missing.
Suggested fix: while scanning vertices, also track coordinate index 2 when hasZ is true and the M index (3 when hasZ, otherwise 2) when hasM is true, then populate Zmin/Zmax/Mmin/Mmax in C# and zmin/zmax/mmin/mmax in TypeScript. Adding a regression test with 3D or M-valued polygon/polyline coordinates would lock this down.
Addresses PR review: the extent computed by CalculateExtentFromPaths (C#) and calculateGeometryExtent (geometry.ts) only carried x/y. For Z/M-enabled geometries it now also tracks zmin/zmax and mmin/mmax (z at coord index 2 when hasZ; m at index 3 when hasZ, else 2), matching geometry.extent for 3D/M results. Adds Z (polygon) and M (polyline) regression tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Addressed the Z/M edge case in
Added regression coverage in The remaining Copilot inline note on 🤖 Generated with Claude Code |
Per review: rather than calculating the bounding box in C# (CalculateExtent/CalculateExtentFromPaths) or by hand in TypeScript, buildDotNetGeometry now obtains the extent from ArcGIS. When an operator result (e.g. unionOperator) doesn't expose a cached .extent, it rebuilds a typed ArcGIS geometry via buildJsGeometry so the SDK recomputes it (including Z/M bounds). Reverts the C# extent calculation and its Polygon/Polyline overrides, and removes the now-obsolete C# GeometryExtentTests (the calculation is JS-only; covered by GeometryExtentSerializationTests and the browser TestUnion assertions). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Reworked the extent fix (
Verified: Core compiles, 19/19 unit tests pass, TS recompiles clean (ESLint OK). The browser e2e still needs a CI run. 🤖 Generated with Claude Code |
What
Restores the runtime setter methods on
SnappingOptionsthat were accidentally dropped in the 4.5.x line, plus regression guards.Why
Commit
c3ab36411truncatedSnappingOptions.gb.csright after the property getters, deleting the entire Property Setters and collection-helper regions. That removedSetEnabled,SetGridEnabled,SetDistance,SetFeatureEnabled,SetSelfEnabled,SetAttributeRulesEnabled, andSetFeatureSources, so consumers can no longer toggle snapping / grid snapping at runtime (reported against 4.5.1). It's isolated to this one component and is still broken ondevelopand in 4.5.1–4.5.3.Changes
SnappingOptions.gb.csfromf02afefeb(the commit immediately before the truncation) — re-adds exactly the 7 setters + the Add/RemoveFeatureSourceshelpers and nothing else.SnappingOptionsApiTests— public-API contract test so a future code-generation split can't silently drop these members again.GeometryExtentSerializationTests+ additions toGeometryEngineTests.TestUnion— guards for the separately-reportedGeometryEngine.Unionextent issue. That one is not reproducible from code (the union/extent path is identical to the working 4.4.4), so these lock in the behavior rather than fix a found bug.Notes
developbecause the regression is present there too; also serves as the cut point for a 4.5.4 hotfix.🤖 Generated with Claude Code